diff --git a/Makefile b/Makefile index 1e66e6cde..5919324c5 100644 --- a/Makefile +++ b/Makefile @@ -3,18 +3,22 @@ run: cp -R static-html/* generated/updated_site/ cp -R redirects/* generated/updated_site/ cp -R static/* generated/updated_site/ - sed -i '' 's/\(^.*~~.*$$\)/\1<\/span>/g' generated/updated_site/pages/*.html - sed -i '' 's/~~//g' generated/updated_site/pages/*.html - cp generated/updated_site/pages/* generated/updated_site/ - rm -rf generated/updated_site/pages/ + sed -i '' 's/\(^.*~~.*$$\)/\1<\/span>/g' generated/updated_site/pages/*.html sed -i '' 's/\(^.*~~.*$$\)/\1<\/span>/g' generated/updated_site/blog/*.html + sed -i '' 's/~~//g' generated/updated_site/pages/*.html + cp generated/updated_site/pages/* generated/updated_site/ sed -i '' 's/~~//g' generated/updated_site/blog/*.html +prod: run + rm -rf generated/updated_site/pages/ + sed -i '' 's/\(.[a-zA-Z0-9()_]*\)<\/span>/\1/g; s/\(.[a-zA-Z0-9 ()_]*\)<\/span>/\1/g; s/\(.[a-zA-Z0-9 ()_.~*=&;/-]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 ()_,&;:#{}]*\)<\/span>/\1/g; s/\(.[0-9]*\)<\/span>/\1/g; s/\(.[a-zA-Z0-9 ()_]*\)<\/span>/\1/g; s/\(.[a-zA-Z0-9 ()_]*\)<\/span>/\1/g; s/\(.[a-zA-Z0-9()_]*\)<\/span>/\1/g; s/\(.[a-zA-Z0-9 ()_.]*\)<\/span>/\1/g; s/\(.[a-zA-Z0-9 ()_.]*\)<\/span>/\1/g; s/\(.[a-zA-Z0-9 ()_.]*\)<\/span>/\1/g; s/\(.[a-zA-Z0-9 ()_.]*\)<\/span>/\1/g; s/\(.[a-zA-Z0-9 ()_]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 ()_,&;:#{}]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 /()_,.&^;:+#{}*!%-]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 /()_,.&^;:+#{}*!%-]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 /()_,.&^;:+#{}*!%-]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 /()_,.&^;:+#{}*!%-]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 /()_,.&^\\\;:+#{}~*@`!?%-]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 /()_,.&^;:+#{}*!%-]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 /()_,.&^\\\;:+#{}~*@`!?%-]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 /\\\()_,.&$^;:+#{}|=~*@`!?%-]*\)<\/span>/\1/g; s/\(.[][a-zA-Z0-9 /()_,.&^;:+#{}*@`!%-]*\)<\/span>/\1/g; s/<\/span>//g; s/<\/span>//g' generated/updated_site/*.html generated/updated_site/blog/*.html + + bookbuild: - mkdir tempcontent - cp -R content/pages tempcontent/pages - rm -rf tempcontent/pages/examples + mkdir -p tempcontent/pages + cp -R content/pages/0* tempcontent/pages + cp -R content/pages/meta tempcontent/pages python transform_book.py pdf pelican -t theme -s book_settings.py -o generated/book tempcontent cp -R static-html/* generated/book/ diff --git a/content/pages/01-introduction/01-learning-programming.markdown b/content/pages/01-introduction/01-learning-programming.markdown index 217546782..08f676d8e 100644 --- a/content/pages/01-introduction/01-learning-programming.markdown +++ b/content/pages/01-introduction/01-learning-programming.markdown @@ -125,11 +125,6 @@ repositories and sites with practice problems and solutions: * [TeachCraft](https://teachcraft.net/) combines Minecraft with Python to learn coding. -* [500 Data Structures and Algorithms practice problems and their solutions](https://techiedelight.quora.com/500-Data-Structures-and-Algorithms-practice-problems-and-their-solutions) - covers a large swath of the computer science space. It is not important - to know all of these algorithms and data structures but experience with - many of them will be greatly beneficial in becoming a better developer. - ### First-hand advice These articles are written by programmers who explain how they learned to @@ -145,11 +140,6 @@ give example paths you can think about taking as a beginner: including persistence, respecting others and considering ideas that are outside your comfort zone. -* [Mastering programming](https://www.facebook.com/notes/kent-beck/mastering-programming/1184427814923414) - by [Kent Beck](https://en.wikipedia.org/wiki/Kent_Beck) contains - patterns and observations for how experienced programmers he has worked - with in the past became great software developers. - * [This Picture Will Change the Way You Learn to Code](https://dev.to/nextdotxyz/this-picture-will-change-the-way-you-learn-tocode-4kmh) covers a well done graphics of many up-to-date concepts and tools that developers use. The post reminds you that you will not and should not learn @@ -170,10 +160,6 @@ your teaching experience: is an awesome resource that explains how you can use simple but fun drawings to teach otherwise difficult technical concepts to students. -* [Teaching programming to working professionals](http://pgbovine.net/PG-Podcast-21-Trey-Hunner.htm) - is a video podcast with [Trey Hunter](https://twitter.com/treyhunner) - about his experience teaching Python to experienced professionals. - * [Teach Yourself Computer Science](https://teachyourselfcs.com/) is intended as a self-teaching tool with many resources that are classic computer science textbooks. There are also nice explanations for why diff --git a/content/pages/01-introduction/02-python-programming-language.markdown b/content/pages/01-introduction/02-python-programming-language.markdown index c99bf04ff..a3b046bb1 100644 --- a/content/pages/01-introduction/02-python-programming-language.markdown +++ b/content/pages/01-introduction/02-python-programming-language.markdown @@ -79,9 +79,6 @@ Dictionary comprehension: ### General Python language resources -* The [online Python tutor](http://www.pythontutor.com/) visually walks - through code and shows how it executes on the Python interpreter. - * [Python Module of the Week](http://pymotw.com/2/index.html) is a tour through the Python standard library. @@ -108,9 +105,6 @@ Dictionary comprehension: * Armin Roacher presented [things you didn't know about Python](https://speakerdeck.com/mitsuhiko/didntknow) at PyCon South Africa in 2012. -* [Writing idiomatic Python](http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/) - is a guide for writing Pythonic code. - ### Python ecosystem resources There's an entire page on [best Python resources](/best-python-resources.html) @@ -153,7 +147,7 @@ the very beginner topics. [comprehensions](http://python-3-patterns-idioms-test.readthedocs.org/en/latest/Comprehensions.html) including code examples and diagrams to explain how they work. -* [Comprehensions in Python the Jedi way](https://gist.github.com/bearfrieze/a746c6f12d8bada03589) +* [Comprehensions in Python the Jedi way](https://gist.github.com/mjhea0/1c0031bd6fcd9263f844) shows off comprehensions with a Star Wars theme to walk through the nuts and bolts. All examples use Python 3.5. @@ -167,10 +161,6 @@ the very beginner topics. covers what the code for list comprehensions looks like and gives some example code to show how they work. -* [An Introduction to Python Lists](http://effbot.org/zone/python-list.htm) - is a solid overview of Python lists in general and tangentially covers - list comprehensions. - ### Python generator resources * This blog post entitled diff --git a/content/pages/01-introduction/03-why-use-python.markdown b/content/pages/01-introduction/03-why-use-python.markdown index 63405e70c..86a0e3ecd 100644 --- a/content/pages/01-introduction/03-why-use-python.markdown +++ b/content/pages/01-introduction/03-why-use-python.markdown @@ -33,10 +33,7 @@ The IEEE ranked Python as the [#1 programming language in 2019](https://spectrum.ieee.org/computing/software/the-top-programming-languages-2019), which continued its hot streak after ranking it -[#1 in 2018](https://spectrum.ieee.org/at-work/innovation/the-2018-top-programming-languages), -[#1 in 2017](https://spectrum.ieee.org/at-work/innovation/the-2017-top-programming-languages) -and -[#3 top programming language in 2016](http://spectrum.ieee.org/computing/software/the-2016-top-programming-languages). +[#1 in 2018](https://spectrum.ieee.org/at-work/innovation/the-2018-top-programming-languages) and 2017. [RedMonk's June 2019 ranking](https://redmonk.com/sogrady/2019/07/18/language-rankings-6-19/) had Python at #3, which held consistent from previous years' rankings in [2018](https://redmonk.com/sogrady/2018/08/10/language-rankings-6-18/) @@ -47,9 +44,9 @@ Stack Overflow's community-created question and answer data confirms the [incredible growth of the Python ecosystem](https://stackoverflow.blog/2017/09/06/incredible-growth-python/) and tries to determine [why it growing so quickly](https://stackoverflow.blog/2017/09/14/python-growing-quickly/) -with their own analysis. In the 2018 Stack Overflow developer survey the +with their own analysis. In the 2020 Stack Overflow developer survey the data indicated that -[Python was the fastest growing major programming language](https://insights.stackoverflow.com/survey/2018/#technology-programming-scripting-and-markup-languages) +[Python was the fastest growing major programming language](https://insights.stackoverflow.com/survey/2020/#technology-programming-scripting-and-markup-languages) and that there is a close alignment between the languages and tools that developers choose to learn and the usage in developers' professional work. @@ -133,13 +130,6 @@ language. system versus statically typed languages, be sure to [read this thorough explanation of the topic](http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html). -* [Why I swapped C#.NET for Python as my default language and platform (and won’t be going back)](https://medium.com/@anthonypjshaw/why-i-swapped-c-net-for-python-as-my-default-language-and-platform-and-wont-be-going-back-e0063a25e491) - provides a viewpoint from someone who is not a professional developer but - uses coding to hack out some projects. He found Microsoft's .NET ecosystem - lacking when it came to satisfying his needs and Python filled the gap for - him with its wide array of open source code libraries, package management - and ability to work well on platforms other than Windows. - * [Python, Machine Learning, and Language Wars](http://sebastianraschka.com/blog/2015/why-python.html) compares Python with R, MATLAB and Julia for data science work. While Python is great for [deployment automation](/deployment.html) and diff --git a/content/pages/01-introduction/04-python-2-or-3.markdown b/content/pages/01-introduction/04-python-2-or-3.markdown index eaf166982..a362e7b49 100644 --- a/content/pages/01-introduction/04-python-2-or-3.markdown +++ b/content/pages/01-introduction/04-python-2-or-3.markdown @@ -78,7 +78,7 @@ gone through the process and have advice for making it less painful. implementations. There is also a [quick reference for writting code with Python 2 and 3 compatibility](https://wiki.python.org/moin/PortingToPy3k/BilingualQuickRef). -* [Upgrading to Python 3 with Zero Downtime](https://tech.yplanapp.com/2016/08/24/upgrading-to-python-3-with-zero-downtime/) +* [Upgrading to Python 3 with Zero Downtime](https://adamj.eu/tech/2016/08/24/upgrading-yplan-to-python-3-with-zero-downtime/) supplies advice on transitioning a large existing Python 2 web application to Python 3. Their process involved upgrading dependencies, testing and deploying the new version before going back to clean up unnecessary code diff --git a/content/pages/01-introduction/05-enterprise-python.markdown b/content/pages/01-introduction/05-enterprise-python.markdown index d00e8fbe0..c50052847 100644 --- a/content/pages/01-introduction/05-enterprise-python.markdown +++ b/content/pages/01-introduction/05-enterprise-python.markdown @@ -39,12 +39,14 @@ frameworks when otherwise they should not make technical design decisions. ## Why are there misconceptions about Python in enterprise environments? Traditionally large organizations building enterprise software have used -statically typed languages such as C++, .NET and Java. Throughout the 1980s -and 1990s large companies such as Microsoft, Sun Microsystems and Oracle -marketed these languages as "enterprise grade". The inherent snub to other -languages was that they were not appropriate for CIOs' difficult technical -environments. Languages other than Java, C++ and .NET were seen as risky and -therefore not worthy of investment. +statically typed languages and platforms such as C++, C# and Java. +Throughout the 1990s and early 2000s, large companies such as +Microsoft, Sun Microsystems and Oracle marketed these languages as +"enterprise grade". The inherent message about other programming +ecosystem was that they were not appropriate for CIOs' difficult +technical environments. Languages other than Java, C++ and C# (along +with its broader .NET platform) were seen as risky and therefore not +worthy of investment. In addition, "scripting languages" such as Python, Perl and Ruby were not yet robust enough in the 1990s because their core standard libraries were @@ -68,7 +70,7 @@ best maintained and fully featured pieces of code for any language. Meanwhile, some of the traditional enterprise software development languages such as Java have languished due to underinvestment by their major corporate -backers. When [Oracle purchased Sun Microsystems in 2009](http://www.oracle.com/us/corporate/press/018363) +backers. When Oracle purchased Sun Microsystems in 2009, there was a long lag time before Java was enhanced with new language features in Java 7. Oracle also [bundles unwanted adware with the Java installation](http://www.engadget.com/2015/03/06/java-adware-mac/), diff --git a/content/pages/01-introduction/06-community.markdown b/content/pages/01-introduction/06-community.markdown index 1baec5f4f..a5f463319 100644 --- a/content/pages/01-introduction/06-community.markdown +++ b/content/pages/01-introduction/06-community.markdown @@ -77,7 +77,7 @@ resources provide perspective on offline events like and [PyCon US 2016](http://www.dreisbach.us/blog/pycon-2016/). There are many other retrospectives for other - [community-led conferences such as EuroPython](http://www.artima.com/weblogs/viewpost.jsp?thread=261930). + [community-led conferences such as EuroPython](https://www.artima.com/weblogs/viewpost.jsp?thread=261930). These summaries can be a great way to get a slice of the experience before purchasing a ticket and booking a trip. @@ -112,16 +112,11 @@ the community. provides a starter page with links to community-run newsletters, resources and conferences. -* There are many large active online communities on - [Reddit](https://www.reddit.com/r/python) and - [IRC channels](https://freenode.net/) such as #python, #python-dev - and #distutils. - * The Python community has a concept known as "Benevolent Dictator For Life" that may appear odd to newcomers. Essentially, Guido Van Rossum created the language and still has the ability to decide community arguments one way or the other. This post on the - [origin of BDFL](http://www.artima.com/weblogs/viewpost.jsp?thread=235725) + [origin of BDFL](https://www.artima.com/weblogs/viewpost.jsp?thread=235725) has more context about Guido's role. * [Python Community and Python at Dropbox](https://talkpython.fm/episodes/show/30/python-community-and-python-at-dropbox) diff --git a/content/pages/01-introduction/07-companies.markdown b/content/pages/01-introduction/07-companies.markdown index cbd58c14a..c4e02cfc8 100644 --- a/content/pages/01-introduction/07-companies.markdown +++ b/content/pages/01-introduction/07-companies.markdown @@ -37,7 +37,7 @@ below). at job descriptions on sites like [Glassdoor with "Python Goldman Sachs" keywords](https://www.glassdoor.com/Jobs/Goldman-Sachs-python-Jobs-EI_IE2800.0,13_KO14,20.htm) and - [Indeed for JP Morgan Chase](https://www.indeed.com/salaries/Python-Developer-Salaries-at-JPMorgan-Chase). + [Indeed for JP Morgan Chase](https://www.indeed.com/cmp/JPMorgan-Chase/salaries/Python-Developer). Salaries and responsibilities vary widely based on the role and whether Python is used for data analysis, [web application development](/web-development.html) or DevOps. @@ -145,7 +145,7 @@ like the CIA, FBI and NSA. [SEC uses Python and proposes organizations use Python to comply with regulations](http://jsdelfino.blogspot.com/2010/05/security-exchange-commission-python.html). * A quick search for government jobs that require or recommend Python - [via USAJobs](https://sec.usajobs.gov/Search/?k=python&p=1) + [via USAJobs](https://www.usajobs.gov/Search/Results?k=python) turns up numerous listings at organizations such as the Smithsonian Institution, Department of Education, Department of the Navy and National Institute of Standards and Technology (NIST). diff --git a/content/pages/01-introduction/08-best-python-resources.markdown b/content/pages/01-introduction/08-best-python-resources.markdown index 81113487a..6677ba3d2 100644 --- a/content/pages/01-introduction/08-best-python-resources.markdown +++ b/content/pages/01-introduction/08-best-python-resources.markdown @@ -47,13 +47,6 @@ should skip down to the next section for "experienced developers". and problems rather than jumping into a specific language that's recommended to you by a friend. -* [A Python Crash Course](https://www.grahamwheeler.com/posts/python-crash-course.html) - gives an awesome overview of the history of Python, what drives the - programming community and dives into example code. You will likely need - to read this in combination with other resources to really let the syntax - sink in, but it's a great article to read several times over as you - continue to learn. - * The [Python projects tag](https://www.twilio.com/blog/tag/python) on the Twilio blog is constantly updated with fun tutorials you can build to learn Python, such as the @@ -61,9 +54,6 @@ should skip down to the next section for "experienced developers". [Choose Your Own Adventures Presentations using Flask and WebSockets](https://www.twilio.com/blog/2014/11/choose-your-own-adventure-presentations-with-reveal-js-python-and-websockets.html) and [Martianify Photos with OpenCV](https://www.twilio.com/blog/2015/11/getting-started-with-opencv-and-python-featuring-the-martian-2.html). -* [A Byte of Python](http://www.swaroopch.com/notes/python/) is a beginner's - tutorial for the Python language. - * Google put together a great compilation of materials and subjects you should read and learn from if you want to be a [professional programmer](https://www.google.com/about/careers/students/guide-to-technical-development.html). diff --git a/content/pages/01-introduction/09-best-python-videos.markdown b/content/pages/01-introduction/09-best-python-videos.markdown index b265bc34b..14be9bccd 100644 --- a/content/pages/01-introduction/09-best-python-videos.markdown +++ b/content/pages/01-introduction/09-best-python-videos.markdown @@ -163,6 +163,7 @@ like [PyCon US](https://us.pycon.org/) and Python language. * PyCon US videos from + [2020](https://www.youtube.com/playlist?list=PL2Uw4_HvXqvbpFquYIE57BEAqkQWk-iFg), [2019](https://www.youtube.com/channel/UCxs2IIVXaEHHA4BtTiWZ2mQ/videos), [2018](https://www.youtube.com/channel/UCsX05-2sVSH7Nx3zuk3NYuQ/videos), [2017](https://www.youtube.com/channel/UCrJhliKNQ8g0qoE_zvL8eVg/videos), @@ -172,6 +173,7 @@ like [PyCon US](https://us.pycon.org/) and are all available online for free. * All of the talk videos are available on YouTube for + [EuroPython 2020](https://www.youtube.com/playlist?list=PL8uoeex94UhHgMD9GOCbEHWku7pEPx9fW0), [EuroPython 2019](https://www.youtube.com/playlist?list=PL8uoeex94UhHFRew8gzfFJHIpRFWyY4YW), [EuroPython 2018](https://www.youtube.com/watch?v=LoRq9yGeBWY&list=PL8uoeex94UhFrNUV2m5MigREebUms39U5), [EuroPython 2017](https://www.youtube.com/watch?v=OCHrzW-R3QI&list=PL8uoeex94UhG9QAoRICebFpeKK2M0Herh), diff --git a/content/pages/01-introduction/10-best-python-podcasts.markdown b/content/pages/01-introduction/10-best-python-podcasts.markdown index b52a474a5..a2c528fee 100644 --- a/content/pages/01-introduction/10-best-python-podcasts.markdown +++ b/content/pages/01-introduction/10-best-python-podcasts.markdown @@ -38,15 +38,19 @@ listen and learn. on [testing](/testing.html) and related topics such as mocking and [code metrics](/code-metrics.html). +* [Django Riffs](https://djangoriffs.com/) is a podcast for learning + [web application development](/web-development.html) in Python using the + [Django web framework](/django.html). + +* [The Real Python Podcast](https://realpython.com/podcasts/rpp/) is a weekly + podcast with interviews, coding tips, and conversation with guests from the + Python community. + * [Teaching Python](https://www.teachingpython.fm/) is a podcast by two teachers about their adventures teaching middle school computer science, problem solving, handling failure, frustration, and success with teaching Python programming. -* Professor Philip Guo has a video podcast called - [PG Podcast](http://pgbovine.net/PG-Podcast.htm), typically on - Python subjects. - [All episodes are listed on a separate page](http://pgbovine.net/PG-Podcast-summary.htm). ## Favorite podcast episodes diff --git a/content/pages/02-development-environments/00-development-environments.markdown b/content/pages/02-development-environments/00-development-environments.markdown index 1a71cbc68..4b7dc8b94 100644 --- a/content/pages/02-development-environments/00-development-environments.markdown +++ b/content/pages/02-development-environments/00-development-environments.markdown @@ -8,17 +8,21 @@ meta: Development environments allow programmers to read, write and work with co A development environment is a combination of a -[text editor](/text-editors-ides.html) and a Python runtime environment. -The text editor allows you to write the code. The runtime environment -implementation such as [CPython](https://github.com/python/cpython) -or [PyPy](https://pypy.org/) provides the method for executing your code. +[text editor](/text-editors-ides.html) and a Python runtime implementation. +The text editor allows you to write code for your applications. The runtime +implementation, such as [CPython](https://github.com/python/cpython) +or [PyPy](https://pypy.org/), provides the method for executing your code. tmux plus Vim editor on a dark background. -A text editor can be as simple as Notepad on Windows or more complicated -as a complete integrated development environment (IDE) such as -[PyCharm](https://www.jetbrains.com/pycharm/) which runs on any major -operating system. +A text editor can be as simple as Notepad running on Windows or a more +complicated +[integrated development environment (IDE)](/text-editors-ides.html) with +syntax checking, integrated [test runner](/testing.html) and code highlighting. +A couple of common IDEs for Python development are +[PyCharm](https://www.jetbrains.com/pycharm/) and +[VSCode](https://code.visualstudio.com/), both of which runs on any major +[operating system](/operating-systems.html). ## Why is a development environment necessary? @@ -89,7 +93,7 @@ getting started and then require payment as you scale up your application. [Stdlib](https://stdlib.com/) that can integrate with external [web APIs](/application-programming-interfaces.html). -* [GitLab Web IDE](https://about.gitlab.com/2018/06/15/introducing-gitlab-s-integrated-development-environment/) +* [GitLab Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/) is integrated into the GitLab web application for modifying your [Git](/git.html) repository files directly in your browser. @@ -117,12 +121,6 @@ configuration as a starting point and customize it from there. [which version of Python to use](/python-2-or-3.html) and adding [code metrics](/code-metrics.html) libraries for checking syntax. -* [Three Ways to Install Python on your Windows Computer](http://blog.yhat.com/posts/installing-python-on-windows.html) - provides multiple avenues for Windows users to get Python on their machine - before setting up the rest of their development environment. Unlike - macOS and Linux, the Windows [operating system](/operating-systems.html) - does not include Python with its default installation. - * [PyCharm: The Good Parts](http://nafiulis.me/pycharm-the-good-parts-i.html) shows you how to be more efficient and productive with that IDE if it's your choice for writing Python code. diff --git a/content/pages/02-development-environments/01-text-editors-ides.markdown b/content/pages/02-development-environments/01-text-editors-ides.markdown index 9f23de412..f179ee45d 100644 --- a/content/pages/02-development-environments/01-text-editors-ides.markdown +++ b/content/pages/02-development-environments/01-text-editors-ides.markdown @@ -78,7 +78,7 @@ gathering [code metrics](/code-metrics.html), running free editions for students and open source projects. * [Thonny](http://thonny.org/) is an - [open source](https://bitbucket.org/plas/thonny/src) Python IDE for new + [open source](https://github.com/thonny/thonny) Python IDE for new programmers. The tool bakes in syntax highlighting, code completion, a simple debugger, a beginner-friendly shell and in situ documentation to assist new developers who are just starting to code. diff --git a/content/pages/02-development-environments/02-vim.markdown b/content/pages/02-development-environments/02-vim.markdown index 1d2ee09b5..f37c04a5d 100644 --- a/content/pages/02-development-environments/02-vim.markdown +++ b/content/pages/02-development-environments/02-vim.markdown @@ -20,7 +20,10 @@ Vim's philosophy is that developers are more productive when they avoid taking their hands off the keyboard. Code should flow naturally from the developer's thoughts through the keyboard and onto the screen. Using a mouse or other peripheral is a detriment to the rate at which a developer's -thoughts become code. +thoughts become code. This "efficiency by keyboard" +[keeps Vim as one of the most popular text editors](https://pragmaticpineapple.com/how-did-vim-become-so-popular/) +despite having been around for decades. Few programming tools have that kind +of staying power. Vim has a logical, structured command language. When a beginner is learning the editor she may feel like it is impossible to understand all the key @@ -88,6 +91,31 @@ If a Vimrc file does not already exist, just create it within the user's home directory and it will be picked up by Vim the next time you open the editor. +The following are a few resources for learning what to put in, and how to +structure a `.vimrc` file. I recommend adding configuration options one +at a time to test them individually instead of going whole hog with a Vimrc +you are unfamiliar with. + +* [A Good Vimrc](http://dougblack.io/words/a-good-vimrc.html) is a fantastic, + detailed overview and opinionated guide to configuring Vim. Highly + recommended for new and experienced Vim users. + +* [5 lines for a blank .vimrc](https://swordandsignals.com/2020/12/13/5-lines-in-vimrc.html) + shows settings for case insensitive search, highlighting as you search, + disabling swap, and a couple more "must have" enhancements to the + default configuration. + +* [Vim and Python](https://justin.abrah.ms/vim/vim_and_python.html) shows + and explains many Python-specific .vimrc options. + +* This + [repository's folder with Vimrc files](https://github.com/amix/vimrc/tree/master/vimrcs) + has example configurations that are well commented and easy to learn from. + +* For people who are having trouble getting started with Vim, check out this + blog post on the + [two simple steps that helped this author learn Vim](http://adamdelong.com/two-simple-steps-helped-me-learn-vim/). + ### Vim tutorials Vim has a reputation for a difficult learning curve, but it's much easier @@ -139,11 +167,6 @@ to get started with these tutorials. * [Vim Adventures](http://vim-adventures.com/) is a cute, fun browser-based game that helps you learn Vim commands by playing through the adventure. -* In [Vim: revisited](http://mislav.uniqpath.com/2011/12/vim-revisited/) the - author explains his on-again off-again relationship with using Vim. He then - shows how he configures and uses the editor so it sticks as his primary - code editing tool. - * [Things About Vim I Wish I Knew Earlier](https://blog.petrzemek.net/2016/04/06/things-about-vim-i-wish-i-knew-earlier/) explores the lessons one developer learned while exclusively using Vim for several years. The author includes using relative instead of absolute @@ -156,31 +179,6 @@ to get started with these tutorials. habits. -### Vimrc resources -These are a few resources for learning how to structure a `.vimrc` file. I -recommend adding configuration options one at a time to test them -individually instead of going whole hog with a Vimrc you are unfamiliar with. - -* [A Good Vimrc](http://dougblack.io/words/a-good-vimrc.html) is a fantastic, - detailed overview and opinionated guide to configuring Vim. Highly - recommended for new and experienced Vim users. - -* [Vim and Python](https://justin.abrah.ms/vim/vim_and_python.html) shows - and explains many Python-specific .vimrc options. - -* [Vim as a Python IDE](http://liuchengxu.org/posts/use-vim-as-a-python-ide/) - shows a slew of plugins and configuration options for coding with Python - in Vim. - -* This - [repository's folder with Vimrc files](https://github.com/amix/vimrc/tree/master/vimrcs) - has example configurations that are well commented and easy to learn from. - -* For people who are having trouble getting started with Vim, check out this - blog post on the - [two simple steps that helped this author learn Vim](http://adamdelong.com/two-simple-steps-helped-me-learn-vim/). - - ### Vim installation guides These installation guides will help you get Vim up and running on Mac OS X, Linux and Windows. diff --git a/content/pages/02-development-environments/04-sublime-text.markdown b/content/pages/02-development-environments/04-sublime-text.markdown index 841687737..196df3b51 100644 --- a/content/pages/02-development-environments/04-sublime-text.markdown +++ b/content/pages/02-development-environments/04-sublime-text.markdown @@ -68,10 +68,6 @@ links should get your editor customized with linters, is a spectacular tutorial that covers installing Sublime Text and configuring a multitude of helpful Python programming plugins. -* [Sublime Text 3 Heaven](https://www.kennethreitz.org/essays/sublime-text-3-heaven) - is a quick overview of the extensions, packages and bonus toys that - one developer uses for his own Sublime Text development setup. - * [Sublime Tutor](https://sublimetutor.com/) is an interactive in-editor keyboard shortcuts tutorial that plugs into Sublime so you can learn and become more productive as you use the editor. diff --git a/content/pages/02-development-environments/05-pycharm.markdown b/content/pages/02-development-environments/05-pycharm.markdown index c6810f26c..c464d6e87 100644 --- a/content/pages/02-development-environments/05-pycharm.markdown +++ b/content/pages/02-development-environments/05-pycharm.markdown @@ -29,10 +29,6 @@ Python code. is a solid discussion thread with different developers' perspectives on using PyCharm for coding their applications. -* [How to Get Started with PyCharm and Have a Productive Python IDE](https://pedrokroger.net/getting-started-pycharm-python-ide/) - covers the basics of configuring PyCharm for running code within - virtualenvs, macros, using the console and code completion. - * [Using PyCharm with Pyramid](https://docs.pylonsproject.org/projects/pyramid-cookbook/en/latest/development_tools/pycharm.html) is specific to developing and debugging [with the Pyramid web framework](/pyramid.html). diff --git a/content/pages/02-development-environments/06-jupyter-notebook.markdown b/content/pages/02-development-environments/06-jupyter-notebook.markdown index 30ff049cc..58c9c32b6 100644 --- a/content/pages/02-development-environments/06-jupyter-notebook.markdown +++ b/content/pages/02-development-environments/06-jupyter-notebook.markdown @@ -73,6 +73,18 @@ your own productive workflow. data science notebook projects such as MATLAB and Mathematica to set the stage for IPython and Jupyter's creation. +* [How to use Jupyter Notebooks in 2020 (Part 1: The data science landscape)](https://ljvmiranda921.github.io/notebook/2020/03/06/jupyter-notebooks-in-2020/) + is a high-level overview post that starts a series on Jupyter Notebooks. + This first post covers why a tool like Jupyter Notebook is needed in + the broader landscape of data science. + [Part 2](https://ljvmiranda921.github.io/notebook/2020/03/16/jupyter-notebooks-in-2020-part-2/) + examines the growth of the Jupyter ecosystem and the jump from exploratory + analysis notebooks to production notebooks. + +* [Jupyter Notebook Best Practices](https://levelup.gitconnected.com/jupyter-notebook-best-practices-fc326eb5cd22) + contains tips for beginners such as learning shortcuts and properly + documenting the analysis you work on. + * [How to Version Control Jupyter Notebooks](https://nextjournal.com/schmudde/how-to-version-control-jupyter) explains how Jupyter Notebooks are stored in JSON, the issues with that format for [source control](/source-control.html) and how to get @@ -134,6 +146,13 @@ like advanced interactive visualizations. code that is suitable for [deployment](/deployment.html) to a production environment. +* [How to use ipywidgets to make your Jupyter notebook interactive](https://www.wrighters.io/use-ipywidgets-with-jupyter-notebooks/) + is a tutorial on how to use the + [ipywidgets](https://ipywidgets.readthedocs.io/en/latest/) library + to make Jupyter Notebooks respond to users' input and go beyond + simply presenting data into having users be able to do some additional + analysis themselves. + * [28 Jupyter Notebook tips, tricks and shortcuts](https://www.dataquest.io/blog/jupyter-notebook-tips-tricks-shortcuts/) explains many of the lesser-known keyboard shortcuts and mechanisms to output settings. @@ -143,10 +162,6 @@ like advanced interactive visualizations. you will eventually want to handle within your notebooks as you get comfortable in the environment. -* [Hacking my way to a Jupyter notebook powered blog](https://nipunbatra.github.io/blog/2017/Jupyter-powered-blog.html) - explores how the author created a blog using Jupyter but ran into some - issues along the way, along with how to solve those problems. - * [Making Publication Ready Python Notebooks](http://blog.juliusschulz.de/blog/ultimate-ipython-notebook) explores the plugins that the author uses when creating and exporting reports from Jupyter. @@ -186,6 +201,11 @@ like advanced interactive visualizations. is a kernel that allows you to run [Ansible](/ansible.html) tasks and playbooks from within your Jupyter environment. +* [Jupyter Notebooks in the IDE](https://towardsdatascience.com/jupyter-notebooks-in-the-ide-visual-studio-code-versus-pycharm-5e72218eb3e8) + explains how to use Jupyter files in Visual Studio Code or + [PyCharm](/pycharm.html) with Jupytext, which defines the + pairing information and notebook kernel. + * [The Notebook Wars](https://yihui.name/en/2018/09/notebook-war/) is not a tutorial but instead points to the weaknesses that become apparent when using Jupyter and the current generation of notebook projects. The diff --git a/content/pages/02-development-environments/07-shells.markdown b/content/pages/02-development-environments/07-shells.markdown index 845728809..aa5ac671f 100644 --- a/content/pages/02-development-environments/07-shells.markdown +++ b/content/pages/02-development-environments/07-shells.markdown @@ -45,3 +45,7 @@ environment named `fullstackpython` within the macOS Terminal application. little tool that shows how input and arguments in the shell break down and are interpreted by commands. The data is pulled from the [Ubuntu](/ubuntu.html) `man` pages. + +* [Shell productivity tips and tricks](https://blog.balthazar-rouberol.com/shell-productivity-tips-and-tricks.html) + covers how to increase your effectiveness on the shell across topics such as + navigating history, autocompletion, and pattern matching. diff --git a/content/pages/02-development-environments/08-bash-shell.markdown b/content/pages/02-development-environments/08-bash-shell.markdown index 7e553ed6e..22c7877bc 100644 --- a/content/pages/02-development-environments/08-bash-shell.markdown +++ b/content/pages/02-development-environments/08-bash-shell.markdown @@ -20,12 +20,150 @@ during Python software development as part of a programmer's
Bash is an implementation of the shells concept. Learn more in the development environments chapter or view the table of contents for all topics.
-### Bash resources +### How do Python developers use Bash? +If you are programming in the terminal on [macOS](/macos.html) +or [Linux](/ubuntu.html), or using the +[Windows Subsystem for Linux on Windows 10](https://docs.microsoft.com/en-us/windows/wsl/install-win10), +you can easily gain access to Bash if it is not already +your default shell. + +You can show what shell you are currently using by echoing the +`SHELL` environment variable, like so: + +``` +$ echo "$SHELL" +``` + +Which will then print the shell you are currently using. For example, +on macOS I am using Bash by default so the echo command prints: + +``` +/bin/bash +``` + +How much you use Bash or any shell will likely depend on your +[development environment](/development-environments.html), especially +if you are using an editor like [Vim](/vim.html) instead of an +IDE like [PyCharm](/pycharm.html), because it is often easier to do +certain tasks in the shell. For example, most developers I know who +use PyCharm will search for some instance of source code right in +their IDE, whereas I use a combination of Vim and [tmux](/tmux.html) +so I frequently flip between panes to use commands like `grep` to +do my source code searches. + +There is no right way to perform a task like source code searching, it's +really just what works for your brain as a developer that will guide +how often you interact with the Bash shell. + + +### Getting started with Bash +Working with a shell, Bash or otherwise, is intimidating the first time +you try to get started. You are staring at the `$` prompt without a +whole lot of direction. + +When you are completely new to using Bash, it is a good idea to at least +scan, if not take some additional time for in-depth reading of the +documentation for commands that every developer uses. The following +commands are used so frequently in Bash that an experienced developer +probably does not even think about them anymore, they become just a +natural part of your workflow: + +* `echo`: [print text to the command line](https://man7.org/linux/man-pages/man1/echo.1.html) +* `ls`: [list the contents of a directory](https://man7.org/linux/man-pages/man1/ls.1.html) +* `cd`: [change the working directory](https://man7.org/linux/man-pages/man1/cd.1p.html) +* `cp`: [copy a file or directory](https://man7.org/linux/man-pages/man1/cp.1.html) +* `mv`: [move one or more files](https://man7.org/linux/man-pages/man1/mv.1.html) +* `rm`: [delete one or more files or directories](https://man7.org/linux/man-pages/man1/rm.1.html) + +If you know how to use the above commands then you will at least be able +to move around the file system, create, move and update files and know +what is on your storage device(s). + +The following commands are somewhat more advanced but also frequently +used by developers: + +* `su`: [run comamnds as different users or groups](https://man7.org/linux/man-pages/man1/su.1.html) +* `whoami`: [print which user you are currently logged in as](https://man7.org/linux/man-pages/man1/whoami.1.html) +* `grep`: [searches for patterns in files](https://man7.org/linux/man-pages/man1/grep.1.html) + +The above lists are not even close to exhaustive for what commands +you need to know when working with Bash. Read some of the following +introductory tutorials to gain a better understanding of working +with this shell: + +* [The Linux command line for beginner](https://ubuntu.com/tutorials/command-line-for-beginners) + by [Ubuntu](/ubuntu.html) will provide you with context for how to + use the command line, working with files and directories, and handling + superuser commands. + * [Bash Guide for beginners](http://www.tldp.org/LDP/Bash-Beginners-Guide/html/Bash-Beginners-Guide.html) - is an entire book for those new to working with commandlines. It covers + is an entire book for those new to working with command lines. It covers commands, paths, Bash shell scripting, variables and many other critical topics that are necessary to move from beginner to advanced Bash user. +* [101 Bash Commands and Tips for Beginners to Experts](https://dev.to/awwsmm/101-bash-commands-and-tips-for-beginners-to-experts-30je) + gives a well-done laundry list of tricks to explore. + +* [Bash Quick References](https://shellmagic.xyz/) is a cheat sheet for + common operators and signals that come up when working with scripts. + + +### Bash scripting +Bash is used not only as an interactive prompt but also for scripting, which +makes it possible to execute one or more Bash commands stored within a file. +These scripts can be short, with only a single command, or very complicated +with control-flow logic, for loops, and almost anything you want to automate +or compute because +[Bash is a Turing-complete programming language](https://www.quora.com/Is-Bash-Turing-complete). + +Complex Bash scripts sometimes get a negative reputation because they can be +difficult to read and understand if you are not the original author (or you +are reading your own script after a significant period of time has elapsed). +There are many ways to accomplish the same tasks with Bash so the files are +often confusing to read unless the author of a script included clear +documentation. This readability problem is typically less of an issue with +Python scripts because spacing is enforced and the standard library +encapsulates common tasks. + +It's a good idea to think about how you want to structure your Bash scripts +as they grow larger. The following resources provide insight into what you +should consider while coding Bash scripts. + +* This [minimal safe Bash template](https://betterdev.blog/minimal-safe-bash-script-template/) + contains an 86-line Bash script that the author claims once you + understand and use it as a base then it will make your scripts + easier to maintain over time. + +* [Creating a bash completion script](https://iridakos.com/tutorials/2018/03/01/bash-programmable-completion-tutorial.html) + is a great tutorial that walks you through a reasonably complex Bash + script for completing syntax in other Bash shell scripts. + +* [Anybody can write good bash (with a little effort)](https://blog.yossarian.net/2020/01/23/Anybody-can-write-good-bash-with-a-little-effort) + covers the basics of shell scripting and provides some recommendations + for creating more maintainable scripts such as using linters and + formatters. + +* Google's [Shell Style Guide](https://google.github.io/styleguide/shell.xml) + covers how to write consistent, maintainable shell scripts, which is + particularly important if you have ever tried to debug a hacky shell + script that was never meant to be used by anyone other than the original + author. + +* [Bash scripting quirks & safety tips](https://jvns.ca/blog/2017/03/26/bash-quirks/) + explains Bash basic programming constructs like `for` loops and variable + assignment then goes into ways to avoid weird issues in your code. + +* If all else fails when you're trying to use Bash scripts, this article + on [replacing Bash scripts with Python](https://github.com/ninjaaron/replacing-bash-scripting-with-python) + is a guide on swapping in Python for administrative scripting, including + what to do about replacing invaluable command line tools such as `awk`, + `sed` and `grep`. + + +### Additional Bash resources +The following resources cover more advanced Bash use cases and what pitfalls +to try to avoid as you work with the shell or write scripts. + * [Advancing in the Bash shell](http://samrowe.com/wordpress/advancing-in-the-bash-shell/) covers important concepts such as bang syntax, movement commands, tab completion and aliases. @@ -46,19 +184,6 @@ during Python software development as part of a programmer's `PROMPT_COMMAND`, `CDPATH` and `REPLY` which can simplify your scripts by using values that Bash already has stored for you. -* Google's [Shell Style Guide](https://google.github.io/styleguide/shell.xml) - covers how to write consistent, maintainable shell scripts, which is - particularly important if you have ever tried to debug a hacky shell - script that was never meant to be used by anyone other than the original - author. - -* [101 Bash Commands and Tips for Beginners to Experts](https://dev.to/awwsmm/101-bash-commands-and-tips-for-beginners-to-experts-30je) - is a well-done laundry list of tricks to explore. - -* [Bash scripting quirks & safety tips](https://jvns.ca/blog/2017/03/26/bash-quirks/) - explains Bash basic programming constructs like `for` loops and variable - assignment then goes into ways to avoid weird issues in your code. - * [Safe ways to do things in bash](https://github.com/anordal/shellharden/blob/master/how_to_do_things_safely_in_bash.md) shows you how to not shoot yourself in the foot by using safe coding practices with your shell scripts. @@ -76,19 +201,10 @@ during Python software development as part of a programmer's application that generates a hostable, customizable status page for your services. -* [Replacing Bash scripts with Python](https://github.com/ninjaaron/replacing-bash-scripting-with-python) - is a guide on using using Python for administrative scripting, including - what to do about replacing invaluable command line tools such as `awk`, - `sed` and `grep`. - * [Using Aliases to Speed Up Your Git Workflow](https://dev.to/robertcoopercode/using-aliases-to-speed-up-your-git-workflow-2f5a) has a bunch of shell aliases that make it easier for you to execute complicated or uncommon [Git](/git.html) commands. -* [Creating a bash completion script](https://iridakos.com/tutorials/2018/03/01/bash-programmable-completion-tutorial.html) - is a great tutorial that walks you through a reasonably complex Bash - script for completing syntax in other Bash shell scripts. - * [6 Tips Before You Write Your Next Bash Cronjob](https://yasoob.me/posts/6-tips-before-you-write-your-next-bash-cronjob/) covers starting your scripts with shebang, redirecting output, timeouts and sudo privileges. @@ -102,3 +218,16 @@ during Python software development as part of a programmer's presents a list of commands *you should never run*, but can learn about their destructive abilities by reading through the descriptions provided by the author. + +* [Faster bash startup](https://danpker.com/posts/faster-bash-startup/) + and + [Even faster bash startup](https://work.lisk.in/2020/11/20/even-faster-bash-startup.html) + are two great tutorials that will save you a bunch of time if you frequently + open new Bash shells. On many systems you can easily cut down the startup + time for the shell which can be unnecessarily sluggish. + +* [Bash HTTP monitoring dashboard](https://raymii.org/s/software/Bash_HTTP_Monitoring_Dashboard.html) + ([source code](https://github.com/RaymiiOrg/bash-http-monitoring)) + is a useful application fully written in Bash shell scripts that + monitors the health of one or more websites to make sure they are + up and running. diff --git a/content/pages/02-development-environments/10-powershell.markdown b/content/pages/02-development-environments/10-powershell.markdown index 6c399fb52..d4449544b 100644 --- a/content/pages/02-development-environments/10-powershell.markdown +++ b/content/pages/02-development-environments/10-powershell.markdown @@ -39,6 +39,13 @@ of a Python programmer's give historical perspective on how the Windows shell has evolved from MS-DOS days into the current Windows 10 world. +* [Learning a New REST API with PowerShell](https://www.cloudsavvyit.com/2454/learning-a-new-rest-api-with-powershell/) + covers how to create the common GET, POST, PUT and DELETE requests that are + used to work with [RESTful APIs](/application-programming-interfaces.html). + The the tutorial also contains some tips and tricks for reading API + documentation and how to use PowerShell more effectively in these + situations. + * [PowerShell in Azure Functions](http://www.brianbunke.com/blog/2018/02/27/powershell-in-azure-functions/) shows you how to use PowerShell scripting language code in your Azure Functions. The language is only in experimental mode on Azure Functions @@ -55,3 +62,9 @@ of a Python programmer's * [Invoke-Build](https://github.com/nightroman/Invoke-Build) is a build automation tool. There is also extensive documentation on their [wiki](https://github.com/nightroman/Invoke-Build/wiki). + +* [Two months with Powershell on a UNIX](https://code.joejag.com/2020/a-month-with-powershell.html) + examines one developer's experience using PowerShell not on Windows + but on a \*nix [operating system](/operating-systems.html). The author + covers the advantages and disadvantages he found during his experience + and some of the bugs he hopes are fixed in PowerShell 7. diff --git a/content/pages/02-development-environments/12-tmux.markdown b/content/pages/02-development-environments/12-tmux.markdown index 4da1c3016..4b95fba6c 100644 --- a/content/pages/02-development-environments/12-tmux.markdown +++ b/content/pages/02-development-environments/12-tmux.markdown @@ -28,14 +28,16 @@ easier to use many shells at once and attaching to both local and remote tmux+Vim user myself, I can attest to how great these two tools complement each other. +* [Writing & Coding Workflow](http://jacobzelko.com/workflow/) shows one + developer's configuration that combines [Vim](/vim.html) and several plugins + with tmux for a productive setup. + * [Making tmux Pretty and Usable - A Guide to Customizing your tmux.conf](http://www.hamvocke.com/blog/a-guide-to-customizing-your-tmux-conf/) * [Tmux Pairing Anywhere: On Your Box](http://iamvery.com/2013/11/16/tmux-pairing-anywhere-on-your-box.html) * [Using tmux Properly](http://danielallendeutsch.com/blog/16-using-tmux-properly.html) -* [Differences between tmux vs screen](https://wtanaka.com/node/8136) - * [The Power Of tmux Hooks](https://devel.tech/tips/n/tMuXz2lj/the-power-of-tmux-hooks/) * There are a slew of "cheat sheets" for tmux out there, here are a few diff --git a/content/pages/02-development-environments/14-environment-configuration.markdown b/content/pages/02-development-environments/14-environment-configuration.markdown index 2c87e88fb..d65114eb7 100644 --- a/content/pages/02-development-environments/14-environment-configuration.markdown +++ b/content/pages/02-development-environments/14-environment-configuration.markdown @@ -34,6 +34,13 @@ Either one can be used in your applications but there are slight differences that can make one better than the other in various situations. Other useful environment variables resources: +* [How to Set Environment Variables in Linux and Mac: The Missing Manual](https://doppler.com/blog/how-to-set-environment-variables-in-linux-and-mac) + is a wonderfully detailed guide with many tips and tricks throughout + the walkthrough such as quickly setting environment variables for a + single command, passing environment variables through when using sudo + and executing a command in a "clean" environment without everything + you have already set interfering or being accessible to that script. + * [The Twelve-Factor App](https://12factor.net/) describes a method for securing environment data for your applications. The twelve factors are commonly referenced across many programming ecosystems, not just Python, diff --git a/content/pages/02-development-environments/15-application-dependencies.markdown b/content/pages/02-development-environments/15-application-dependencies.markdown index a01f2eba9..927a3720d 100644 --- a/content/pages/02-development-environments/15-application-dependencies.markdown +++ b/content/pages/02-development-environments/15-application-dependencies.markdown @@ -39,9 +39,6 @@ all yourself. A few of the best collections of Python libraries are shows the open source Python projects trending today, this week, and this month. -* This list of [20 Python libraries you can’t live without](http://freepythontips.wordpress.com/2013/07/30/20-python-libraries-you-cant-live-without/) - is a wide-ranging collection from data analysis to testing tools. - * Wikipedia actually has an extensive [page dedicated to Python libraries](http://en.wikipedia.org/wiki/List_of_Python_software) grouped by categories. @@ -161,16 +158,6 @@ so far to get up to speed on building and releasing your own packages. provides a collection of resources to understand how to package and distribute Python code libraries. -* [Alice in Python projectland](https://veekaybee.github.io/2017/09/26/python-packaging/) - is an amazing post that takes the reader from simple Python script - into a complete Python package. - -* [Perils of packaging](https://malramsay.com/post/perils_of_packaging/) - covers several edge cases that come up when trying to put together - pieces like Travis CI, PyPI and conda. The post walks through the errors - and how to get around them until they are smoothed out by updates to the - tools. - * [How to Publish Your Package on PyPI](https://blog.jetbrains.com/pycharm/2017/05/how-to-publish-your-package-on-pypi/) is for developers who have created a code library they would like to share and make installable for other developers. @@ -230,10 +217,6 @@ developers. dependency management tools including newer ones such as pipenv and Poetry. -* Occasionally arguments about using Python's dependency manager versus - one of Linux's dependency managers comes up. This provides - [one perspective on that debate](http://notes.pault.ag/debian-python/). - * [Open source trust scaling](http://lucumr.pocoo.org/2016/3/24/open-source-trust-scaling/) is a good piece for the [Python community](/python-community.html) (and other programming communities) that is based on the diff --git a/content/pages/02-development-environments/17-localhost-tunnels.markdown b/content/pages/02-development-environments/17-localhost-tunnels.markdown index 4cfe9d86e..f82b2c81e 100644 --- a/content/pages/02-development-environments/17-localhost-tunnels.markdown +++ b/content/pages/02-development-environments/17-localhost-tunnels.markdown @@ -23,7 +23,11 @@ experience with to the ones I have not used. * [ngrok](https://ngrok.com/) is the service I use most often. It is easy and worth the small fee to upgrade your account with a few - extra features such as fixed, customizable subdomains. + extra features such as fixed, customizable subdomains. There is + also a + [Python wrapper for ngrok called pyngrok](https://github.com/alexdlaird/pyngrok) + that makes it easy to programmatically access the ngrok client + from Python applications. * [Localtunnel](https://localtunnel.github.io/www/) is a localhost tunnel written in Node.js. diff --git a/content/pages/02-development-environments/18-source-control.markdown b/content/pages/02-development-environments/18-source-control.markdown index 064f9729b..c96745a51 100644 --- a/content/pages/02-development-environments/18-source-control.markdown +++ b/content/pages/02-development-environments/18-source-control.markdown @@ -118,10 +118,6 @@ control services are: part of an ongoing deployment guide written by the folks at [Rainforest](https://www.rainforestqa.com/). -* This lighthearted guide to the - [ten astonishments in version control history](http://www.flourish.org/2011/12/astonishments-ten-in-the-history-of-version-control/) - is a fun way to learn how systems developed over the past several decades. - * [A visual guide to version control](http://betterexplained.com/articles/a-visual-guide-to-version-control/) is a detailed article with real-life examples for why version control is necessary in software development. @@ -198,9 +194,9 @@ implementation. free online version of the O'Reilly [Version Control with Subversion](https://www.amazon.com/dp/B002SR2QIW/) book. -* [How to use Subversion (SVN)](https://deveo.com/svn-tutorial/) lays out - the basic concepts and provides the first few steps for getting started - tracking files. +* [How to Host SVN Repositories](https://www.perforce.com/blog/vcs/how-host-subversion-svn) + lays out the basic concepts and provides the first few steps for getting + started tracking files. * [10 Most Used SVN Commands with Examples](http://www.thegeekstuff.com/2011/04/svn-command-examples/) is a good refresher list if you've used SVN in the past but it has been diff --git a/content/pages/02-development-environments/19-git.markdown b/content/pages/02-development-environments/19-git.markdown index 3233bff32..5bffca262 100644 --- a/content/pages/02-development-environments/19-git.markdown +++ b/content/pages/02-development-environments/19-git.markdown @@ -141,6 +141,12 @@ workflow. These resources will come in handy for specific Git subjects. important when working with others on a long-lasting project where you dive through the commit history via `git log` and related commands. +* [How to squash Git commits](https://gitbetter.substack.com/p/how-to-squash-git-commits) + explains how to use the `git rebase` command in interactive mode to + consolidated the number of commits in your history. This technique is + useful when a group of commits are related and it's easier to understand + them as a single commit rather than a collection of smaller commits. + * [Oh shit, Git!](http://ohshitgit.com/) is a profanity-filled description of tips to get you out of binds you may find yourself in when you get too tricky with Git commands. @@ -163,9 +169,10 @@ workflow. These resources will come in handy for specific Git subjects. the Git history, and good practices for using Git based on the knowledge of how it works internally. -* [How Microsoft uses Git](https://docs.microsoft.com/en-us/azure/devops/learn/devops-at-microsoft/use-git-microsoft) - gives a high-level overview of their repository structure and hosting - at the extremely large scale organization. +* [Chasing a bad commit](https://vishaltelangre.com/chasing-a-bad-commit/) + examines the `git bisect` command and how it can be used in either + interactive mode or on its own with `git bisect run` to find the + problematic code commit that needs to be fixed. * [GitTips](https://git.wiki.kernel.org/index.php/GitTips) is a list of pro tips to clean up common issues and how to dive through Git history @@ -184,11 +191,6 @@ workflow. These resources will come in handy for specific Git subjects. through example Git commands. This is a highly recommended read after you've grasped the basics and are looking to go deeper with Git. -* [How To Host Your Own Private Git Repositories](https://eklitzke.org/how-to-how-your-own-private-git-repositories) - provides the steps for handling private Git repositories on your own - server. This setup is great for either mirroring GitHub repositories - or just getting away from hosted services entirely. - * [How I configure my git in a new computer](https://medium.com/@Tiagojdferreira/how-i-set-up-my-git-in-a-new-computer-85bb461b089f) shows how to handle a `.gitconfig` file, with [an example Gist](https://gist.github.com/Tiagojdferreira/115ecac229e176e48d520c59b022e4fb) @@ -217,6 +219,11 @@ workflow. These resources will come in handy for specific Git subjects. system. This is an awesome read to get a view on how Git works under the commands you're using to manipulate these objects. +* [How to Undo Mistakes With Git Using the Command Line](https://www.youtube.com/watch?v=lX9hsdsAeTk) + is a video that covers topics like resetting a file to an old revision, + recovering deleted commits, squashing multiple commits into one with + interactive rebase and recovering deleted branches. + ## Git Workflows Teams of developers can use Git in varying workflows because of Git's @@ -233,10 +240,6 @@ minimize merge conflicts. why at GitHub they do not use the git-flow model and provides an alternative that solves some of the issues they found with git-flow. -* [Git Workflows That Work](http://blog.endpoint.com/2014/05/git-workflows-that-work.html) - is a helpful post with diagrams to show how teams can create a Git workflow - that will help their development process. - * [Comparing workflows](https://www.atlassian.com/git/tutorials/comparing-workflows) provides a slew of examples for how developers on a team can handle merge conflicts and other situations that commonly arise when using Git. diff --git a/content/pages/03-data/00-data.markdown b/content/pages/03-data/00-data.markdown index 739821b81..39a767500 100644 --- a/content/pages/03-data/00-data.markdown +++ b/content/pages/03-data/00-data.markdown @@ -12,7 +12,7 @@ subsections, including (in no particular order): * data processing / wrangling * machine learning -* data analysis +* [data analysis](/data-analysis.html) * [visualization](/data-visualization.html) * geospatial mapping * persistence via [relational databases](/databases.html) and @@ -126,6 +126,12 @@ sets. provides more than just the data, it also includes instructions and code for working with the data in your own development environment. +* [Discovering millions of datasets on the web](https://blog.google/products/search/discovering-millions-datasets-web/) + introduces Google's + [dataset search](https://datasetsearch.research.google.com/) + and explains what they learned from iterating on earlier versions + of it before they released this one. + ### General Python data resources * [PyData](http://pydata.org/) is a community for developer and users of @@ -148,6 +154,17 @@ sets. have evolved over the past 20ish years based on his first-hand experience as a leader and member in that community. +* The State of [Python Speech Recognition](https://www.assemblyai.com/blog/the-state-of-python-speech-recognition-in-2021) + in 2021 is a practical overview of a specific area in data: extracting text + from voice recording data. Looking at verticals like this one can make it + easier to understand changes that are occurring in some parts of data and + programming that could be applied to other areas. + +* [Automated Data Wrangling](https://catalyst.coop/2021/05/23/automated-data-wrangling/) + covers cleaning, labeling, and automating the bunch of activities + that are typically necessary before analysis and data usage can + begin for a project. + * The [Open Source Data Science Masters](http://datasciencemasters.org/) is a well-crafted free curriculum and set of resources for students who want to learn both the theory and technologies for working with data. @@ -157,3 +174,7 @@ sets. [Jupyter Notebook](/jupyter-notebook.html) that [Stripe](/stripe.html) for their data analysis across the company. +* [The Definitive Data Scientist Environment Setup](https://davidadrian.cc/definitive-data-scientist-setup/) + explains how to set up both a hardware and software configuration that + is conducive to data science research and analysis. + diff --git a/content/pages/03-data/01-databases.markdown b/content/pages/03-data/01-databases.markdown index 5eed45185..bad071a2c 100644 --- a/content/pages/03-data/01-databases.markdown +++ b/content/pages/03-data/01-databases.markdown @@ -100,7 +100,7 @@ Find out about Python applications with a MySQL backed on the dedicated To work with a relational database using Python, you need to use a code library. The most common libraries for relational databases are: -* [psycopg2](http://initd.org/psycopg/) +* [psycopg](https://www.psycopg.org/) ([source code](https://github.com/psycopg/psycopg2)) for PostgreSQL. @@ -112,8 +112,6 @@ library. The most common libraries for relational databases are: * [cx\_Oracle](https://oracle.github.io/python-cx_Oracle/index.html) for Oracle Database ([source code](https://github.com/oracle/python-cx_Oracle)). - Oracle moved their - [open source driver code from SourceForge to GitHub in 2017](https://blogs.oracle.com/developers/oracle-database-python-driver-now-on-github). SQLite support is built into Python 2.7+ and therefore a separate library @@ -183,7 +181,7 @@ speed on SQL if you have never previously used it. elaborates on one of the trickiest parts of writing SQL statements that bridge one or more tables: the `JOIN`. -* [Writing better SQL](http://www.craigkerstiens.com/2016/01/08/writing-better-sql/) +* [Writing more legible SQL](https://www.craigkerstiens.com/2016/01/08/writing-more-legible-sql/) is a short code styling guide to make your queries easier to read. * [SQL Intermediate](https://www.dataquest.io/blog/sql-intermediate/) is a @@ -265,7 +263,7 @@ speed on SQL if you have never previously used it. 1. Install PostgreSQL on your server. Assuming you went with Ubuntu run ``sudo apt-get install postgresql``. -1. Make sure the [psycopg2](http://initd.org/psycopg/) library is in your +1. Make sure the [psycopg](https://www.psycopg.org/) library is in your application's dependencies. 1. Configure your web application to connect to the PostgreSQL instance. diff --git a/content/pages/03-data/02-postgresql.markdown b/content/pages/03-data/02-postgresql.markdown index d20271e9c..5e700895a 100644 --- a/content/pages/03-data/02-postgresql.markdown +++ b/content/pages/03-data/02-postgresql.markdown @@ -12,7 +12,7 @@ pronounced "Poss-gres", is an open source [relational database](/databases.html) implementation frequently used by Python applications as a backend for data storage and retrieval. -PostgreSQL logo. +PostgreSQL logo. ## How does PostgreSQL fit within the Python stack? @@ -57,7 +57,7 @@ architecture. To work with relational databases in Python you need to use a database driver, which is also referred to as a database connector. The most common driver library for working with PostgreSQL is -[psycopg2](http://initd.org/psycopg/). There is +[psycopg](https://www.psycopg.org/). There is [a list of all drivers on the PostgreSQL wiki](https://wiki.postgresql.org/wiki/Python), including several libraries that are no longer maintained. If you're working with the @@ -126,17 +126,17 @@ walkthroughs I've read. * This article explains how and why PostgreSQL can handle [full text searching](http://blog.lostpropertyhq.com/postgres-full-text-search-is-good-enough/) - for many use cases. If you're going down this route, read - [this blog post that explains how one developer implemented PostgreSQL full text search with SQLAlchemy](http://blog.garage-coding.com/2015/12/18/postgres-fulltext-search.html). - -* [django-postgres-copy](http://django-postgres-copy.californiacivicdata.org/en/latest/) - is a tool for bulk loading data into a PostgreSQL database based on Django models. - [Say hello to our new open-source software for loading bulk data into PostgreSQL](http://www.californiacivicdata.org/2015/07/17/hello-django-postgres-copy/) - is an introduction to using the tool in your own projects. + for many use cases. * [How to speed up tests in Django and PostgreSQL](http://nemesisdesign.net/blog/coding/how-to-speed-up-tests-django-postgresql/) explains some hacks for making your schema migration-backed run quicker. +* [Thinking psycopg3](https://www.varrazzo.com/blog/2020/03/06/thinking-psycopg3/) + is written by a developer who has worked on this critical Python library + for interacting with PostgreSQL since 2005. The author writes up thoughts + on what should change if backwards-incompatible changes are ever introduced + in a new hypothetical future version. + * [Records](https://pypi.org/project/records/) is a wrapper around the psycopg2 driver that allows easy access to direct SQL access. It's worth a look if you prefer writing SQL over using an @@ -169,9 +169,21 @@ for properly handling your data. past five years. It's amazing to see how far this project has come and how it continues to evolve. +* [The Internals of PostgreSQL](http://www.interdb.jp/pg/) is a book + that goes into how PostgreSQL works, including core topics such as + [query processing](http://www.interdb.jp/pg/pgsql03.html), + [concurrency control](http://www.interdb.jp/pg/pgsql05.html) and the + [layout of heap table files](http://www.interdb.jp/pg/pgsql01.html). + * [PostgreSQL Weekly](http://postgresweekly.com/) is a weekly newsletter of PostgreSQL content from around the web. +* [My Favorite PostgreSQL Extensions - Part One](https://severalnines.com/database-blog/my-favorite-postgresql-extensions-part-one) + and + [part two](https://severalnines.com/database-blog/my-favorite-postgresql-extensions-part-two) + are roundups of useful PostgreSQL extensions that augment the + standard PostgreSQL functionality. + * [An introduction to PostgreSQL physical storage](http://rachbelaid.com/introduction-to-postgres-physical-storage/) provides a solid walkthrough of where PostgreSQL files are located on disk, how the files store your data and what mappings are important for diff --git a/content/pages/03-data/03-mysql.markdown b/content/pages/03-data/03-mysql.markdown index 87edda6a3..27c52b9c4 100644 --- a/content/pages/03-data/03-mysql.markdown +++ b/content/pages/03-data/03-mysql.markdown @@ -133,6 +133,10 @@ A handful of the best of these tutorials are listed below. goes into details for why the company Userlike migrated from their MySQL database setup to PostgreSQL. +* [MySQL sharding at Quora](https://www.quora.com/q/quoraengineering/MySQL-sharding-at-Quora) + provides details behind Quora's at-scale infrastructure and + how their MySQL sharding evolved over time. + * [Growing up with MySQL](https://nylas.com/blog/growing-up-with-mysql/) is a story about how one company went through dramatic growth and had to keep up with it by quickly scaling their MySQL database. diff --git a/content/pages/03-data/04-sqlite.markdown b/content/pages/03-data/04-sqlite.markdown index 2cb4cef26..5c7f3fd00 100644 --- a/content/pages/03-data/04-sqlite.markdown +++ b/content/pages/03-data/04-sqlite.markdown @@ -86,6 +86,10 @@ tutorials will help you get started. It's a great short read which shows that the code is well-tested and maintained. +* [SQLite is not a toy database](https://antonz.org/sqlite-is-not-a-toy-database/) + is a whirlwind overview of some of the best aspects of SQLite and why + you should use it. + * [Data Analysis of 8.2 Million Rows with Python and SQLite](https://plot.ly/ipython-notebooks/big-data-analytics-with-pandas-and-sqlite/) explains how you can load a large dataset in to SQLite and visualize it using the Plotly service. @@ -139,6 +143,9 @@ you are having with SQLite rather than going through a general tutorial. digs into the internals of SQLite and shows some bugs found (and since fixed) while the author was researching the SQLite source code. +* [How to Store Multimedia Files in a SQLite3 Database with Python](https://www.twilio.com/blog/intro-multimedia-file-upload-python-sqlite3-database) + goes through the Python code for storing and accessing BLOB-type objects. + * [Going Fast with SQLite and Python](http://charlesleifer.com/blog/going-fast-with-sqlite-and-python/) shares essential knowledge for working effectively with SQLite in Python, particularly when it comes to transactions, concurrency and commits. @@ -148,11 +155,6 @@ you are having with SQLite rather than going through a general tutorial. [object-relational mapper (ORM)](/object-relational-mappers-orms.html) to implement virtual tables and aggregates on top of SQLite. -* [Use SQLite with Django On AWS Lambda with Zappa](https://blog.zappa.io/posts/use-sqlite-with-django-on-aws-lambda-with-zappa) - provides an example `dev_settings.py` file for - locally testing a [Django](/django.html) application intended for - [AWS Lambda](/aws-lambda.html). - * [SQLite Database Authorization and Access Control with Python](http://charlesleifer.com/blog/sqlite-database-authorization-and-access-control-with-python/) covers how to control access to the SQLite database connection and file even though SQLite normally allows unauthorized access by design. diff --git a/content/pages/03-data/05-object-relational-mappers.markdown b/content/pages/03-data/05-object-relational-mappers.markdown index a642889cc..6451908e8 100644 --- a/content/pages/03-data/05-object-relational-mappers.markdown +++ b/content/pages/03-data/05-object-relational-mappers.markdown @@ -8,7 +8,7 @@ meta: Object-relational mappers (ORMs) bridge relational databases and data repr An object-relational mapper (ORM) is a code library that automates the -transfer of data stored in relational databases tables into objects that +transfer of data stored in relational database tables into objects that are more commonly used in application code. Diagram showing how object-relational mappers bridge the database and Python objects. @@ -64,7 +64,7 @@ there was a pressing reason. Python ORM libraries are not required for accessing relational databases. In fact, the low-level access is typically provided by another library called a *database connector*, such as -[psycopg](http://initd.org/psycopg/) (for PostgreSQL) +[psycopg](https://www.psycopg.org/) (for PostgreSQL) or [MySQL-python](https://pypi.org/project/MySQL-python/1.2.5) (for MySQL). Take a look at the table below which shows how ORMs can work with different web frameworks and connectors and relational databases. @@ -137,7 +137,8 @@ There are numerous ORM implementations written in Python, including 1. [The Django ORM](/django-orm.html) 1. [PonyORM](/pony-orm.html) 1. [SQLObject](http://sqlobject.org/) -1. [Tortoise ORM](https://tortoise-orm.readthedocs.io/en/latest/) +1. [Tortoise ORM](https://tortoise-orm.readthedocs.io/en/latest/) + ([source code](https://github.com/tortoise/tortoise-orm/)) There are other ORMs, such as Canonical's [Storm](https://storm.canonical.com/), but most of them do not appear to diff --git a/content/pages/03-data/06-sqlalchemy.markdown b/content/pages/03-data/06-sqlalchemy.markdown index af57ed512..f4c9abf9d 100644 --- a/content/pages/03-data/06-sqlalchemy.markdown +++ b/content/pages/03-data/06-sqlalchemy.markdown @@ -166,6 +166,10 @@ edge cases. gives a wonderful walkthrough of how to build your own online commenting system in Python using SQLAlchemy. +* [Master SQLAlchemy Relationships in a Performance Friendly Way](https://blog.theodo.com/2020/03/sqlalchemy-relationship-performance/) + dives into code that shows how to improve performance when setting and + accessing relationship-based data in your models. + * [SQLAlchemy and data access in Python](https://talkpython.fm/episodes/show/5/sqlalchemy-and-data-access-in-python) is a podcast interview with the creator of SQLAlchemy that covers the project's history and how it has evolved over the past decade. @@ -193,6 +197,11 @@ implementations. Several open source projects and articles are listed here to make it a bit easier to understand the differences between these implementations. +* [Introduction to SQLAlchemy ORM for Django Developers](https://apirobot.me/posts/introduction-to-sqlalchemy-orm-for-django-developers) + is written by a developer who typically used the [Django ORM](/django-orm.html) + at work and then had a chance to try SQLAlchemy for one project. He covers + differences in how each one handles transactions, models and queries. + * [SQLAlchemy vs Other ORMs](http://www.pythoncentral.io/sqlalchemy-vs-orms/) provides a detailed comparison of SQLAlchemy against alternatives. @@ -212,3 +221,9 @@ implementations. [which is better and why: Django ORM or SQLALchemy](https://www.quora.com/Which-is-better-and-why-Djangos-ORM-or-SQLAlchemy) based on various developers' experiences. + +## Open source code for learning SQLAlchemy +Many open source projects rely on SQLAlchemy. A great way to learn +how to properly work with this tool is to read the code that shows +how those projects use SQLAlchemy. This section alphabetically lists +these code examples by class and function in the SQLAlchemy code base. diff --git a/content/pages/03-data/08-django-orm.markdown b/content/pages/03-data/08-django-orm.markdown index c5ce776ed..59bb49f8b 100644 --- a/content/pages/03-data/08-django-orm.markdown +++ b/content/pages/03-data/08-django-orm.markdown @@ -39,6 +39,10 @@ that have been added throughout the project's history. [Django Silk](http://mtford.co.uk/blog/2/) is another inspection tool and has capabilities to do more than just SQL inspection. +* [Django QuerySet Examples (with SQL code included)](https://davit.tech/django-queryset-examples/) + teaches how QuerySets work and shows the corresponding SQL code behind the + Python code you write to use the ORM. + * [Making a specific Django app faster](http://reinout.vanrees.org/weblog/2014/05/06/making-faster.html) is a Django performance blog post with some tips on measuring performance and optimizing based on the measured results. @@ -176,3 +180,18 @@ following resources should get you past the initial hurdles. added to an existing table, and another where a `Many-to-Many` field needs to be converted to a standard `ForeignKey` column while retaining all of the data. + +* [Double-checked locking with Django ORM](https://lukeplant.me.uk/blog/posts/double-checked-locking-with-django-orm/) + shows how you can implement a double-checking locking pattern in the + Django ORM with [PostgreSQL](/postgresql.html), which is useful + when you want to prevent multiple processes from accessing the same + data at the same time. + +* [Using Django Check Constraints for the Sum of Percentage Fields](https://adamj.eu/tech/2020/03/10/django-check-constraints-sum-percentage-fields/) + shows how you can combine several `PositiveIntegerField` model + fields with a checking constraint and a web form that ensures + all of the fields sum up to a precise amount, such as 100%. + +* [Learn Django ORM - Query and Filters](https://www.youtube.com/playlist?list=PLOLrQ9Pn6cazjoDEnwzcdWWf4SNS0QZml) + is a video tutorials series that gives an overview of the ORM's + querying and filtering capabilities. diff --git a/content/pages/03-data/10-no-sql-datastore.markdown b/content/pages/03-data/10-no-sql-datastore.markdown index 05e47b705..c6c9b4683 100644 --- a/content/pages/03-data/10-no-sql-datastore.markdown +++ b/content/pages/03-data/10-no-sql-datastore.markdown @@ -189,10 +189,6 @@ representing a person could have a property of "female" or "male". * [CAP Theorem overview](http://natishalom.typepad.com/nati_shaloms_blog/2010/10/nocap.html) presents the basic constraints all databases must trade off in operation. -* This post on [What is a NoSQL database? Learn By Writing One in Python](http://jeffknupp.com/blog/2014/09/01/what-is-a-nosql-database-learn-by-writing-one-in-python/) - is a detailed article that breaks the mystique behind what some forms - of NoSQL databases are doing under the covers. - * The [CAP Theorem series](http://blog.thislongrun.com/2015/03/the-cap-theorem-series.html) explains concepts related to NoSQL such as what is ACID compared to CAP, CP versus CA and high availability in large scale deployments. diff --git a/content/pages/03-data/11-redis.markdown b/content/pages/03-data/11-redis.markdown index c05d04741..3600ddae2 100644 --- a/content/pages/03-data/11-redis.markdown +++ b/content/pages/03-data/11-redis.markdown @@ -84,10 +84,6 @@ Redis should be customized out of its default configuration to secure it against unauthorized and unauthenticated users. These resources provide some advice on Reids security and guarding against data breaches. -* [Pentesting Redis servers](http://averagesecurityguy.info/2015/09/17/pentesting-redis-servers/) - shows that security is important not only on your application but also - the databases you're using as well. - * Redis, just as with any relational or NoSQL database, needs to be secured based on [security guidelines](http://www.antirez.com/news/96). There is also a post where the main author of Redis diff --git a/content/pages/03-data/12-mongodb.markdown b/content/pages/03-data/12-mongodb.markdown index 407cb1c30..665144fec 100644 --- a/content/pages/03-data/12-mongodb.markdown +++ b/content/pages/03-data/12-mongodb.markdown @@ -67,6 +67,12 @@ command line and query language. [Google Cloud Function](/google-cloud-functions.html) to store persistent data while running on a serverless platform. +* [Everything You Know About MongoDB is Wrong!](https://developer.mongodb.com/article/everything-you-know-is-wrong) + lists many of the common thoughts developers have about MongoDB and + why some of them are misconceptions. This is a good read for + developers who used MongoDB several years ago and want to know what + major improvements have been made since then. + ### MongoDB security NoSQL databases can be a weak spot in a production deployment environment, @@ -93,11 +99,6 @@ security controls so make sure to lock down your instances. installing and using MongoDB on your own instance. The post covers authentication, SSL and firewalls. -* [Securing MongoDB using Let's Encrypt certificate](https://zohaib.me/securing-mongodb-using-lets-encrypt/) - gives a configuration that encrypts that traffic coming from and - going to your MongoDB instances using free - [Let's Encrypt certificates](https://letsencrypt.org/). - * This 4 post securing MongoDB series covers [Data Security Requirements for Regulatory Compliance](https://www.mongodb.com/blog/post/securing-mongodb-part-1-data-security-requirements-for-regulatory-compliance), [Database Access Control](https://www.mongodb.com/blog/post/securing-mongodb-part-2-database-access-control), @@ -105,11 +106,6 @@ security controls so make sure to lock down your instances. and [Environmental Control & Database Management](https://www.mongodb.com/blog/post/securing-mongodb-part-4-environmental-control-and-database-management). -* Lightweight Directory Access Protocol (LDAP) is common in many - established company environments for security. This post on - [How to Configure LDAP Authentication for MongoDB](https://www.mongodb.com/blog/post/how-to-configure-LDAP-authentication-for-mongodb) - goes over how to authenticate users via LDAP who are using MongoDB. - ### Python with MongoDB resources MongoDB is straightforward to use in a Python application when a driver @@ -120,10 +116,6 @@ configure and start using MongoDB with Python. shows how to use Python to interface with MongoDB via PyMongo and MongoEngine. -* A [Gentle Introduction to MongoDB using Pymongo](http://altons.github.io/python/2013/01/21/gentle-introduction-to-mongodb-using-pymongo/) - reviews a connection configuration file, the basics for data insertion, - aggregation and updating records. - * [How To Set Up Flask with MongoDB and Docker](https://www.digitalocean.com/community/tutorials/how-to-set-up-flask-with-mongodb-and-docker) combines the [Flask](/flask.html) web framework with MongoDB then containerizes the example application with [Docker](/docker.html). diff --git a/content/pages/03-data/14-neo4j.markdown b/content/pages/03-data/14-neo4j.markdown index 13f4cf29c..d53b5711c 100644 --- a/content/pages/03-data/14-neo4j.markdown +++ b/content/pages/03-data/14-neo4j.markdown @@ -35,11 +35,6 @@ of the database. Transform and Load (ETL) tool to move your data from one database such as [MySQL](/mysql.html) into Neo4j. -* [Migrating from MySQL to Neo4j](https://engineering.logicgate.com/migrating-from-mysql-to-neo4j-2f6cb63a73c8) - gives specific advice about how your data can change during a migration from - a relational database to a graph database which the author did not know - before undertaking their own migration. - ### Neo4j resources * [Building a Recommendation Engine with Neo4j and Python](https://www.youtube.com/watch?v=ILjTikVhT9k) diff --git a/content/pages/03-data/16-pandas.markdown b/content/pages/03-data/16-pandas.markdown index b3ccee0d7..a0750eaae 100644 --- a/content/pages/03-data/16-pandas.markdown +++ b/content/pages/03-data/16-pandas.markdown @@ -49,6 +49,14 @@ is a data structures and analysis library. shows how to use the `crosstab` function in pandas so you can summarize and group data. +* [Calculating streaks in pandas](https://joshdevlin.com/blog/calculate-streaks-in-pandas/) + shows how to measure and report on streaks in data, which is where + several events happen in a row consecutively. + +* [How to Convert a Python Dictionary to a Pandas DataFrame](https://www.marsja.se/how-to-convert-a-python-dictionary-to-a-pandas-dataframe/) + is a straightforward tutorial with example code for loading and adding + data stored in a typical Python dictionary into a DataFrame. + * This two-part series on loading data into a pandas DataFrame presents what to do [when CSV files do not match your expectations](http://blog.enthought.com/python/with-and-without-the-canopy-data-import-tool-loading-data-theres-no-such-thing-as-a-simple-csv-file/) @@ -62,15 +70,18 @@ is a data structures and analysis library. and charts that show the pay off period broken down by interest and principal. +* [Efficiently cleaning text with pandas](https://pbpython.com/text-cleaning.html) + provides a really great practical tutorial on different approaches + for cleaning a large data set so that you can begin to do your analysis. + The tutorial also shows how to use the + [sidetable](https://github.com/chris1610/sidetable) library, which + creates summary tables of a DataFrame. + * [tabula-py: Extract table from PDF into Python DataFrame](https://blog.chezo.uno/tabula-py-extract-table-from-pdf-into-python-dataframe-6c7acfa5f302) presents how to use the Python wrapper for the [Tabula](https://tabula.technology/) library that makes it easier to extract table data from PDF files. -* [Analyzing Browser History Using Python and Pandas](https://applecrazy.github.io/blog/2017-11-12/analyzing-browser-hist-using-python) - shows how to take data from Google Chrome and start to visualize it - with pandas and [matplotlib](/matplotlib.html). - * [Time Series Forecast Case Study with Python: Monthly Armed Robberies in Boston](https://machinelearningmastery.com/time-series-forecast-case-study-python-monthly-armed-robberies-boston/) walks through the data wrangling, analysis and visualization steps with a public data set of murders in Boston from 1966 to 1975. This @@ -110,3 +121,32 @@ is a data structures and analysis library. explains that pandas operations can often be parallelized for better performance using the Pandas UDFs feature in PySpark version 2.3 or greater. + +* [How to use Pandas read_html to Scrape Data from HTML Tables](https://www.marsja.se/how-to-use-pandas-read_html-to-scrape-data-from-html-tables/) + has a bunch of great code examples that show how to load + data from HTML directly into your DataFrames. + +* [How to download fundamentals data with Python](http://theautomatic.net/2020/05/05/how-to-download-fundamentals-data-with-python/) + shows how to obtain and use financial data, such as balance sheets, + stock prices, and various ratios to perform your own analysis on. + +* [How to convert JSON to Excel with Python and pandas](https://www.marsja.se/how-to-convert-json-to-excel-python-pandas/) + provides instructions for creating a spreadsheet out of JSON file. + +* [Loading large datasets in Pandas](https://towardsdatascience.com/loading-large-datasets-in-pandas-11bdddd36f7b) + explains how to get around the `MemoryError` issue that occurs + when using `read_csv` because the data set is larger than the + available memory on a machine. You can use chunking with + the `read_csv` function to divide the data set into smaller parts that + each can be loaded into memory. Alternatively, you can use a + [SQLite database](/sqlite.html) to create a [relational database](/databases.html) + with the data then use SQL queries or an + [object-relational mapper (ORM)](/object-relational-mappers-orms.html) + to load the data and perform analysis in pandas. + +* Real-world Excel spreadsheets are often a mess of unstructured data, so + this tutorial on + [Reading Poorly Structured Excel Files with Pandas](https://pbpython.com/pandas-excel-range.html) + gives example code for extracting only part of a file as well + as reading ranges and tables. + diff --git a/content/pages/03-data/17-scipy-numpy.markdown b/content/pages/03-data/17-scipy-numpy.markdown index 9259f5d89..00763c2d0 100644 --- a/content/pages/03-data/17-scipy-numpy.markdown +++ b/content/pages/03-data/17-scipy-numpy.markdown @@ -38,10 +38,11 @@ following resources are broader walkthroughs for the SciPy ecosystem: instructions for various SciPy packages that were previously hosted on the SciPy wiki. -* [Lectures in Quantitative Economics: SciPy](https://lectures.quantecon.org/py/scipy.html) - provides a good overview of SciPy compared to the specific NumPy - project, as well as explanations for the wrappers SciPy provides - over lower-level FORTRAN libraries. +* [Robots and Generative Art and Python, oh my!](https://www.generativehut.com/post/robots-and-generative-art-and-python-oh-my) + uses Scipy, Numpy, and [Matplotlib](/matplotlib.html) to generate + some nice looking art that can even be written to paper using a + plotter. This is a very cool example project that ties together + the scientific world and the art world. * [A plea for stability in the SciPy ecosystem](http://blog.khinsen.net/posts/2017/11/16/a-plea-for-stability-in-the-scipy-ecosystem/) presents concerns from one scientist's perspective about how fast the @@ -61,9 +62,19 @@ following resources are broader walkthroughs for the SciPy ecosystem: computation and how to perform operations that get the results you need for your data analysis. -* [101 NumPy Exercises for Data Analysis](https://www.machinelearningplus.com/101-numpy-exercises-python/) +* [Scientific Computing in Python: Introduction to NumPy and Matplotlib](https://sebastianraschka.com/blog/2020/numpy-intro.html) + is a detailed tutorial that goes through the basics for NumPy and + then connects it to [Matplotlib](/matplotlib.html). + +* [Math to Code](https://mathtocode.com/) provides an interactive + tutorial to learn how to implement math in NumPy. + +* [101 NumPy Exercises for Data Analysis](https://www.machinelearningplus.com/python/101-numpy-exercises-python/) + has a bunch of questions and answers to common ways to work with NumPy + and is useful to understand what you can do with this library. * [NumPy: creating and manipulating numerical data](http://www.scipy-lectures.org/intro/numpy/index.html) + contains many code examples for common operations. * [Python NumPy Array Tutorial](https://www.datacamp.com/community/tutorials/python-numpy-tutorial) is a starter tutorial specifically focused on using and working diff --git a/content/pages/03-data/18-data-visualization.markdown b/content/pages/03-data/18-data-visualization.markdown index 62002fcc0..e56c2b2dc 100644 --- a/content/pages/03-data/18-data-visualization.markdown +++ b/content/pages/03-data/18-data-visualization.markdown @@ -36,7 +36,6 @@ easier for humans to see patterns, trends and other useful information. * [Python & OpenGL for Scientific Visualization](https://www.labri.fr/perso/nrougier/python-opengl/) is a free book that shows how to combine open source tools such as - [Pyglet](https://pyglet.readthedocs.io/en/stable/) and [PyOpenGL](http://pyopengl.sourceforge.net/) with Python [data analysis](/data-analysis.html) libraries to generate interactive scientific data visualizations. @@ -92,11 +91,6 @@ Sometimes you need inspiration from other sources to figure out what you want to build. The following links have made me excited about data visualization and gave me ideas for what to build. -* [Roads to Rome](http://roadstorome.moovellab.com/) is a beautiful - visualization showing the data behind the expression "all roads lead - to Rome" and whether or not there is a "Rome" central city in every - country. - * [Monarchs](https://thebackend.dev/monarchs/) is a wonderful 1,000 year history visual of European rulers. The developer also wrote an in-depth article on @@ -108,10 +102,6 @@ visualization and gave me ideas for what to build. and dark sides, the main characters, various bits about the Force and other data extracted from the movies. -* [Big League Graphs](https://bigleaguegraphs.com/) presents a bunch of - creative ways to view data for sports such as basketball, baseball and - hockey. - * [What do numbers look like?](https://johnhw.github.io/umap_primes/index.md.html) is a Python 3 dimensional visualization of millions of integers, colored by special factors such as prime and Fibonacci numbers. @@ -142,6 +132,12 @@ visualization and gave me ideas for what to build. ### Data visualization resources +* [Guides for visualizing data](https://flowingdata.com/2020/06/01/guides-for-visualizing-reality/) + provides the thought processes that you can use when you are + showing uncertainty, incompletet data, differences, outliers, + and other common scenarios that occur when your data is messy - + and it usually is! + * [Data visualization, from 1987 to today](https://medium.economist.com/data-visualisation-from-1987-to-today-65d0609c6017) is a wonderful reference about the pre-computer age era of visualization which was a combination of cartography, art and statistics rather than @@ -157,8 +153,7 @@ visualization and gave me ideas for what to build. * [Engineering Intelligence Through Data Visualization at Uber](https://eng.uber.com/data-viz-intel/) explains how Uber's data visualization team grew from 1 person to 15 and the output they created along the way, including the open source - tools [react-vis](https://uber.github.io/react-vis/) and - [react-map-gl](https://uber.github.io/react-map-gl/). + tool [react-vis](https://uber.github.io/react-vis/). * The Practitioner's Guide to System Dashboard Design series covers a lot of ground for what you should consider when building one form @@ -168,3 +163,9 @@ visualization and gave me ideas for what to build. * [Part 2: Presentation and Accessibility](http://onemogin.com/observability/dashboards/practitioners-guide-to-system-dashboard-design-p2.html) * [Part 3: What Charts to Use](http://onemogin.com/observability/dashboards/practitioners-guide-to-system-dashboard-design-p3.html) * [Part 4: Context Improvement](http://onemogin.com/observability/dashboards/practitioners-guide-to-system-dashboard-design-p4.html) + +* [Truncating the Y-Axis: Threat or Menace?](https://engineering.tableau.com/truncating-the-y-axis-threat-or-menace-d0bce66d4d08) + is a great in-indepth explanation of why something that seems as + straightforward as laying out the Y-Axis requires thought and + care otherwise the visualization could end up being misleading. + diff --git a/content/pages/03-data/19-bokeh.markdown b/content/pages/03-data/19-bokeh.markdown index 668538d90..22f8d55cc 100644 --- a/content/pages/03-data/19-bokeh.markdown +++ b/content/pages/03-data/19-bokeh.markdown @@ -61,12 +61,6 @@ basic syntax will change as the library's API is not yet stable. an appropriate format then explains the code that uses Bokeh to visualize it. -* [Data is beautiful: Visualizing Roman imperial dynasties](http://machineloveus.com/data-is-beautiful-visualizing-roman-imperial-dynasties/) - provides a walkthrough for creating a gorgeous visualization based on - historical Roman data. The post is about more than just the visual, it also - goes into the ideation, data wrangling and analysis phases that came - before using Bokeh to show the results. - * [Visualizing with Bokeh](https://programminghistorian.org/en/lessons/visualizing-with-bokeh) gives a detailed explanation with the code for number Bokeh visuals you can output while working with a [pandas](/pandas.html) data set. @@ -105,13 +99,6 @@ basic syntax will change as the library's API is not yet stable. project has the code to create a simple chart with Bokeh and [Flask](/flask.html). -* [Bokeh vs Dash — Which is the Best Dashboard Framework for Python?](https://blog.sicara.com/bokeh-dash-best-dashboard-framework-python-shiny-alternative-c5b576375f7f) - contains a single project that was written in both Dash and Bokeh. The - author gives his subjective view on the implementation difficulty - although the web application only contained a single type of data - visualization so it is hard to drawn any real conclusions from his - opinion. - * [Realtime Flight Tracking with Pandas and Bokeh](https://www.geodose.com/2019/01/realtime-flight-tracking-pandas-bokeh-python.html) provides a great example of combining [pandas](/pandas.html) for structuring data with Bokeh for visualization. diff --git a/content/pages/03-data/21-matplotlib.markdown b/content/pages/03-data/21-matplotlib.markdown index 14f4d2f64..9c60d3740 100644 --- a/content/pages/03-data/21-matplotlib.markdown +++ b/content/pages/03-data/21-matplotlib.markdown @@ -21,10 +21,6 @@ toolkits. is an awesome getting started tutorial that breaks through the confusing beginner steps so you can quick start using the plotting library. -* [Web Scraping With Python: Scrapy, SQL, Matplotlib To Gain Web Data Insights](http://www.scrapingauthority.com/python-scrapy-mysql-and-matplotlib-to-gain-web-data-insights/) - is a long and comprehensive tutorial that walks through obtaining, - cleaning and visualizing data. - * [Matplotlib Cheat Sheet: Plotting in Python](https://www.datacamp.com/community/blog/python-matplotlib-cheat-sheet) contains some handy snippets of code to perform common plotting operations in Matplotlib. diff --git a/content/pages/03-data/25-oracle.markdown b/content/pages/03-data/25-oracle.markdown new file mode 100644 index 000000000..bf6b3cdc0 --- /dev/null +++ b/content/pages/03-data/25-oracle.markdown @@ -0,0 +1,165 @@ +title: Oracle +category: page +slug: Oracle +sortorder: 0325 +toc: False +sidebartitle: Oracle +meta: Oracle Database is an enterprise relational database management system. + + +[Oracle Database](http://www.oracle.com/) is an enterprise +[relational database](/databases.html). It can run transaction processing, +data warehousing, and multi-model database workloads such as machine +learning, spatial, and graph analysis. Recent versions of Oracle Database +also added support for JSON and blockchain use cases, and the software +can be run in on-premise, cloud or hybrid environments. + +Oracle logo. + + +## How does Oracle fit with Python? +The Python community and Oracle have a long history. The excellent Python Database API-compliant "cx_Oracle" interface for Oracle Database was first created by the user community in 1998 and is now being enhanced and maintained by Oracle. The [cx_Oracle](https://oracle.github.io/python-cx_Oracle/) module also underpins the [Oracle Machine Learning for Python](https://www.youtube.com/watch?v=P861m__PEMQ) engine. Oracle's high-performance GraalVM framework supports an implementation of Python called [GraalPython](https://github.com/oracle/graalpython). + + +## Why is Oracle Database a great choice? +Oracle Database is cross-platform, supporting multiple hardware platforms and various operating systems. Developers and companies of all sizes rely on its proven industry-leading performance, scalability, reliability, and security. +As data volumes rise exponentially, new data types and data models are required to support modern applications. Oracle Database supports the following data types at no extra cost: + +* [JSON](https://docs.oracle.com/en/database/oracle/oracle-database/19/adjsn/index.html) +* [Blockchain](https://docs.oracle.com/en/database/oracle/oracle-database/21/nfcon/details-oracle-blockchain-table-282449857.html) +* [XML](https://www.oracle.com/database/technologies/appdev/xmldb.html) +* [Object](https://docs.oracle.com/database/121/ADOBJ/adobjint.htm#ADOBJ00101) +* [Graph](https://www.oracle.com/database/graph/) +* [Spatial](https://www.oracle.com/database/spatial/) +* [Time Series](https://docs.oracle.com/en/database/oracle/oracle-database/19/dmcon/time-series.html) +* Relational + +With support for scale-out database clusters, sharded distributed systems, and disaster recovery with continuous application availability, there is no shortage of features to guarantee the Database continues to run uninterrupted 24/7. + +Oracle makes its enterprise-class database readily available to developers with its free on-premises edition Oracle Database XE or on the Oracle public cloud with an Always Free Cloud account. In addition, Oracle Autonomous Database is a popular choice for developers as no database management or tuning is required, leaving developers to do what they do best – writing code for their applications. + + +## Connecting to Oracle Database with Python +As with any database, applications require a connector or driver to connect to the Oracle Database. The Python DB API-compliant [cx_Oracle](https://github.com/oracle/python-cx_Oracle) interface provides developers access to standard and advanced Oracle Database features, such as SQL execution and document storage APIs. It also gives users access to network traffic encryption capabilities and Oracle's leading high availability features. + +[Code examples](https://oracle.github.io/python-cx_Oracle/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html) and free workshops such as the introductory [Python and Oracle for Developers Workshop](https://apexapps.oracle.com/pls/apex/dbpm/r/livelabs/view-workshop?wid=766) and a full-stack development workshop using [Python with SQLAlchemy to Oracle Database](https://apexapps.oracle.com/pls/apex/dbpm/r/livelabs/view-workshop?wid=911&clear=180&session=16650643444916) are available. + +cx Oracle driver. + +You can use many Python frameworks and [object-relational mappers (ORMs)](/object-relational-mappers-orms.html) with Oracle Database. ORMs abstract the tables and objects in a relational database to objects that Python developers can manipulate and operate on. [SQLAlchemy](/sqlalchemy.html) and Django are popular ORMs. SQLAlchemy is used by Pandas, which is very popular with Oracle users. +The table below shows the relationship between web framework, ORM, driver, and the Oracle Database. + +Examples of how varying Python ORMs can work with Oracle and the cx Oracle connector. + +Learn more about +[Python ORMs on that dedicated topic page](/object-relational-mappers-orms.html). + +ORMs provide a familiar programming model for Python developers, but sometimes you want that extra performance and operate closer to SQL objects. Oracle cx_Oracle offers several [functions](https://oracle.github.io/python-cx_Oracle/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html#binding) to deliver that performance. These functions include fetching data, binding data, executing PL/SQL, operating on LOBs, JSON documents, message passing with Oracle Advanced Queuing, and more. + + +## Oracle and Data Safety +According to Gartner, Oracle has one of the [highest data safety ratings](https://www.gartner.com/reviews/market/cloud-database-management-systems/vendor/oracle/product/oracle-database) in the industry, with a wide range of features for data protection and high availability. These features include: + +* [Database encryption](https://www.oracle.com/database/technologies/security/advanced-security.html) + +* [Access control to rows](https://www.oracle.com/database/technologies/security/label-security.html) in a table + +* [Database vault](https://www.oracle.com/database/technologies/security/db-vault.html) to restrict privileges and access + +* [Data redaction, subsetting, and masking](https://www.oracle.com/database/technologies/security/data-masking-subsetting.html) + +* All in one data security service in the Oracle Cloud with [Data Safe](https://www.oracle.com/database/technologies/security/data-safe.html) + +* Oracle also provides free tools such as the [Database Assessment Tool (DBSAT)](https://www.oracle.com/database/technologies/security/dbsat.html) to help you identify and remedy potential vulnerabilities. + +Oracle also provides numerous data recovery features, including: + +* Backup capabilities with [RMAN](https://www.oracle.com/database/technologies/high-availability/rman.html) + +* Restore point features with [Database Flashback](https://www.oracle.com/database/technologies/high-availability/flashback.html) + +* [Application continuity](https://www.oracle.com/database/technologies/high-availability/app-continuity.html) in the event of database failover to a standby + +For an overview of Oracle’s security and high availability architecture, see the following white papers: + +* [Maximum Availability Architecture](https://www.oracle.com/a/tech/docs/maa-onpremises-overview.pdf) (MAA) + +* [Maximum Security Architecture](https://blogs.oracle.com/cloudsecurity/post/oracles-maximum-security-architecture-for-database-security) (MSA) + + +## Python Specific Oracle Database resources +Many quick starts, tutorials, and workshops exist specifically for Python developers using Oracle Database. Below are some of the best ones to start with. + + +###Getting Started +If you are looking for a fast way to get started with Python and Oracle Database, check out these two quick start tutorials. These tutorials walk you through installing and setting up the environment you need to connect Python to Oracle Database. + +* [Quick Start: Developing Python Applications for Oracle Database](https://www.oracle.com/database/technologies/appdev/python/quickstartpythononprem.html) + +* [Quick Start: Developing Python Applications for Oracle Autonomous Database](https://www.oracle.com/database/technologies/appdev/python/quickstartpythononprem.html) + +Once you have done one of these, then continue with the popular [Python and Oracle Database Tutorial: Scripting for the Future](https://oracle.github.io/python-cx_Oracle/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html) to dive deeper to master the Python cx_Oracle interface and see how to build great Oracle Database applications. + + +###Using Different Frameworks with Oracle +* [How to Run SQL Queries with Pandas](https://www.oracle.com/news/connect/run-sql-data-queries-with-pandas.html) is a good blog using Pandas for quick and easy data manipulation in Python. + +* [Using Oracle with Pandas in OCI Data Science Notebooks](https://docs.oracle.com/en-us/iaas/tools/ads-sdk/latest/user_guide/loading_data/efficient_use_of_oracle_rdbms_with_ads.html) dives deeper into using Pandas with large datasets in data science applications. + +* [Using SQLAlchemy with Oracle Database](https://docs.sqlalchemy.org/en/14/dialects/oracle.html) provides an excellent toolkit for Python developers using SQLAlchemy as their ORM. + +* [Using Django with Python and Oracle Database](https://www.oracle.com/webfolder/technetwork/tutorials/obe/db/oow10/python_django/python_django.htm) is a tutorial from Oracle and shows the Django Framework with Python to an Oracle Database. + +* [Connecting Pony ORM to the Database](https://docs.ponyorm.org/database.html) is a friendly guide on using Pony with databases. + +* [How to use Python Flask with Oracle Database](https://blogs.oracle.com/opal/post/how-to-use-python-flask-with-oracle-database). + +* [Part 1: Docker for Oracle Database Applications in Node.js and Python](https://blogs.oracle.com/opal/post/part-1-docker-for-oracle-database-applications-in-nodejs-and-python). + +* [Part 2: Docker for Oracle Database Applications in Node.js and Python](https://blogs.oracle.com/opal/post/part-2-docker-for-oracle-database-applications-in-nodejs-and-python). + +* [Faster JSON with Python cx_Oracle and Oracle Database 21’s new OSON storage format](https://blogs.oracle.com/opal/post/faster-json-with-python-cx_oracle-81-and-oracle-database-21s-new-oson-storage-format). + + +###Workshops +The following hands-on, free workshops provide step-by-step instructions and walkthroughs in a live environment. + +* [Use Python with Oracle Database 19c](https://apexapps.oracle.com/pls/apex/dbpm/r/livelabs/view-workshop?wid=635&clear=180&session=3484600041895) is an Oracle LiveLabs workshop that shows how to write Python code to connect to and read data from an Oracle Database, including JSON data. + +* [Python and Oracle for Developers](https://apexapps.oracle.com/pls/apex/dbpm/r/livelabs/workshop-attendee-2?p210_workshop_id=766&p210_type=2&session=3484600041895) is an Oracle LiveLabs workshop that explores the features of the Python cx_Oracle interface for Oracle Database, including efficient techniques for connection management and statement handling. + +* [Full Stack Development using Python and deployment via OKE](https://apexapps.oracle.com/pls/apex/dbpm/r/livelabs/view-workshop?wid=911&clear=180&session=3484600041895) is an Oracle LiveLabs workshop that explores how to build and deploy a simple cloud-native application using the most common frameworks and the Oracle Cloud Infrastructure services. + + +## Cloud Development with Oracle Database +The following resources are good starting points for those looking to build applications in the Oracle Cloud and deploy applications in Docker containers and Kubernetes. + +* [The Complete Guide To Getting Up And Running With Docker And Kubernetes On The Oracle Cloud](https://blogs.oracle.com/developers/post/the-complete-guide-to-getting-up-and-running-with-docker-and-kubernetes-on-the-oracle-cloud). + +* [Oracle Cloud Blog](https://www.oc-blog.com/) has lots of interesting information on different aspects of Oracle Cloud. + +For developers looking to focus on application development in the Oracle Cloud and not have to worry about managing the Oracle Database, the Autonomous Database is a good choice. All management, including patching and upgrades, scalability, and security, are entirely autonomous. The following resources offer you a glimpse of its capabilities. + +* [Julien Dontcheff’s Database Blog](https://juliandontcheff.wordpress.com/category/autonomous/) is a good collection of technical posts with the Autonomous Database. + +* [SQL Maria](https://sqlmaria.com/category/autonomous-database/) also has some excellent posts on all things Oracle Database including Autonomous. + +* [An Introduction to Autonomous Database](https://questoraclecommunity.org/learn/blogs/oracles-autonomous-database-an-introduction/) gives you a good overview. + +* [Autonomous Database for researchers](https://blogs.oracle.com/research/post/a-roadmap-of-oracle-autonomous-database-benefits-for-research) is a good blog with details on some autonomous features. + + +##General Oracle Database Resources +Here are some Oracle tutorials and resources not specific to Python that can help you take advantage of the Oracle Database features. + +* [Oracle Technical Architecture](https://www.oracle.com/webfolder/technetwork/tutorials/architecture-diagrams/18/technical-architecture/database-technical-architecture.html) is from Oracle and has nice visuals and short paragraphs on the architecture of the Oracle Database. + +* [Oracle Database Internals](https://databaseinternalmechanism.com/oracle-database-internals/) is an excellent post explaining the architecture of the Oracle Database. + +* This [Oracle Performance Tuning](https://blog.quest.com/oracle-performance-tuning-a-5-step-approach-to-optimized-performance/) blog has a 5-step approach to tuning Oracle. + +* [Oracle RAC](https://databaseinternalmechanism.com/oracle-rac/) is another good post on the concepts of RAC, Oracle’s Real Application Cluster software for database high availability. + +* The [Oracle Database Security](https://www.oracle.com/database/technologies/security.html) web page has lots of information on Oracle’s solutions for security called “defense in depth.” + +* This is a good post on the [Top 5 Reasons to choose Oracle](https://www.dbta.com/Editorial/News-Flashes/Top-5-Reasons-to-Use-an-Oracle-Database-144191.aspx) for a production database. diff --git a/content/pages/04-web-development/00-web-development.markdown b/content/pages/04-web-development/00-web-development.markdown index 2c5bc5e60..919cc6c94 100644 --- a/content/pages/04-web-development/00-web-development.markdown +++ b/content/pages/04-web-development/00-web-development.markdown @@ -21,6 +21,7 @@ in [1989](http://home.cern/topics/birth-web). Web development is the concept that encompasses all the activities involved with websites and web applications. + ## How does Python fit into web development? Python can be used to build server-side web applications. While a [web framework](/web-frameworks.html) is not required to build web apps, @@ -70,29 +71,20 @@ world. [data bases](/databases.html), [task queues](/task-queues.html), [caching](/caching.html) and several other critical concepts. -* The [Evolution of the Web](http://www.evolutionoftheweb.com/) visualizes - how web browsers and related technologies have changed over time as well as - the overall growth of the Internet in the amount of data transferred. Note - that the visualization unfortunately stops around the beginning of 2013 but - it's a good way to explore what happened in the first 24 years. +* [What happens when?](https://github.com/alex/what-happens-when) is an + incredibly detailed answer to the questions "What happens when you + type google.com into your browser's address box and press enter?" that + seems straightforward on the surface until you really dig in. * [How browsers work](https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/) provides an overview with solid detail on how browsers take the HTML, CSS, JavaScript, images and other files as input and render webpages as output. It is well worth your time to know this stuff as a web developer. -* [Web app checklist](http://dhilipsiva.com/webapp-checklist/) presents - good practices that developers building and [deploying](/deployment.html) - web applications should follow. Don't worry about having every single - one of these recommendations implemented before getting your site - live, but it is worthwhile to review the list to make sure there is not - something obvious you can handle in a few minutes that will improve - your site's security, performance or usability. - -* [Web application development is different and better](http://radar.oreilly.com/2014/01/web-application-development-is-different-and-better.html) - provides some context for how web development has evolved from writing - static HTML files into the complex JavaScript client-side applications - produced today. +* [The history of the URL](https://blog.cloudflare.com/the-history-of-the-url/) + explains how the growth of ARPANET to hundreds of nodes eventually led to + the creation of the URL. This is a great read that provides historical + context for why things are the way they are with the web. * [The Browser Hacker's Guide to Instantly Loading Everything](https://www.youtube.com/watch?v=7vUs5yOuv-o) is a spectacular technical talk given by Addy Osmani at JSConf EU 2017 diff --git a/content/pages/04-web-development/01-web-frameworks.markdown b/content/pages/04-web-development/01-web-frameworks.markdown index 6b52e3680..2adde9c83 100644 --- a/content/pages/04-web-development/01-web-frameworks.markdown +++ b/content/pages/04-web-development/01-web-frameworks.markdown @@ -90,15 +90,15 @@ but it'll make most developers' lives easier in many cases. ### Comparing web frameworks +[Talk Python to Me had a podcast episode](https://talkpython.fm/episodes/show/149/4-python-web-frameworks-compared) +with a detailed comparison of the [Django](/django.html), +[Flask](/flask.html), Tornado and [Pyramid](/pyramid.html) frameworks. + Are you curious about how the code in a Django project is structured compared with Flask? Check out [this Django web application tutorial](https://www.twilio.com/docs/sms/tutorials/appointment-reminders-python-django) and then view [the same application built with Flask](https://www.twilio.com/docs/sms/tutorials/appointment-reminders-python-flask). -[Talk Python to Me had a podcast episode](https://talkpython.fm/episodes/show/149/4-python-web-frameworks-compared) -with a detailed comparison of the [Django](/django.html), -[Flask](/flask.html), Tornado and [Pyramid](/pyramid.html) frameworks. - There is also a repository called [compare-python-web-frameworks](https://github.com/mattmakai/compare-python-web-frameworks) where the same web application is being coded with varying Python web @@ -112,6 +112,18 @@ frameworks, templating engines and and the many other pieces that combine to make web frameworks useful to web developers. +* [12 requests per second](https://suade.org/dev/12-requests-per-second-with-python/) + examines how the traditionally synchronous web framework + [Flask](/flask.html) compares to an async framework like + [Sanic](/sanic.html) in an artificial, simple benchmark. The + results make it look like Sanic is far faster than Flask, but + once you add even a basic amount of functionality to a + project, including [databasel](/databases.html) queries + and templating, the results even out. Miguel Grinberg + also has a great read with broader results in this + article asking readers to + [Ignore All Web Performance Benchmarks, Including This One](https://blog.miguelgrinberg.com/post/ignore-all-web-performance-benchmarks-including-this-one). + * When you are learning how to use one or more web frameworks it's helpful to have an idea of what the code under the covers is doing. This post on building a @@ -150,10 +162,6 @@ frameworks, templating engines and I agree although I've found sessions and database ORMs to be a helpful part of a framework when done well. -* "[What is a web framework?](http://www.jeffknupp.com/blog/2014/03/03/what-is-a-web-framework/)" - is an in-depth explanation of what web frameworks are and their relation - to web servers. - * [Django vs Flask vs Pyramid: Choosing a Python Web Framework](https://www.airpair.com/python/posts/django-flask-pyramid) contains background information and code comparisons for similar web applications built in these three big Python frameworks. diff --git a/content/pages/04-web-development/02-django.markdown b/content/pages/04-web-development/02-django.markdown index 263a6daef..3061d2eee 100644 --- a/content/pages/04-web-development/02-django.markdown +++ b/content/pages/04-web-development/02-django.markdown @@ -21,7 +21,7 @@ For example, [template engine](/django-templates.html), an [object-relational mapper](/object-relational-mappers-orms.html) (ORM), and [database schema migrations](https://docs.djangoproject.com/en/dev/topics/migrations/) -(as of version 1.7) are all included with the [Django framework](https://pypi.org/project/Django/). +are all included with the [Django framework](https://pypi.org/project/Django/). Compare that included functionality to the Flask framework which requires a separate library such as [Flask-Login](https://flask-login.readthedocs.org/en/latest/) @@ -50,11 +50,6 @@ groups such as [Django District](http://www.meetup.com/django-district/), [San Francisco Django](http://www.meetup.com/The-San-Francisco-Django-Meetup-Group/) so new developers can get help when they are stuck. -There's some debate on whether -[learning Python by using Django is a bad idea](http://www.jeffknupp.com/blog/2012/12/11/learning-python-via-django-considered-harmful/). -However, that criticism is invalid if you take the time to learn the Python -syntax and language semantics first before diving into web development. - ## Django books and tutorials There are a slew of free or low cost resources out there for Django. Make @@ -126,7 +121,7 @@ These books and tutorials assume that you know the basics of building Django and want to go further to become much more knowledgeable about the framework. -* [2 Scoops of Django](https://www.twoscoopspress.com/collections/django/products/two-scoops-of-django-1-11) +* [2 Scoops of Django](https://www.feldroy.com/books/two-scoops-of-django-3-x) by Daniel Greenfeld and Audrey Roy is well worth the price of admission if you're serious about learning how to correctly develop Django websites. @@ -135,22 +130,35 @@ the framework. order to build and deploy a RESTful API powered by Python, Django, and Django REST Framework. +* [User Interaction With Forms](https://www.mattlayman.com/understand-django/user-interaction-forms/) + explains general web form input, how Django handles forms via POST requests, + different types of input such as CharFields, DateFields and EmailFields, + and validating that input. + * This 3-part Django project optimization guide covers a wide range of advanced topics such as [Profiling and Django settings](https://dizballanze.com/django-project-optimization-part-1/), [working with databases](https://dizballanze.com/django-project-optimization-part-2/) and [caching](https://dizballanze.com/django-project-optimization-part-3/). -* This tutorial shows how to create - [a Django web app that can make phone calls and send text messages for automated surveys](https://www.twilio.com/docs/tutorials/walkthrough/automated-survey/python/django). - The code is a really good example of a full Django project and is also - available - [open source on GitHub](https://github.com/TwilioDevEd/automated-survey-django). +* [Caching in Django](https://testdriven.io/blog/django-caching/) is a detailed + look at the configuration required for caching and how to measure the + performance improvements once you have it in place. + +* [Mental Models for Class Based Views](https://djangodeconstructed.com/2020/01/03/mental-models-for-class-based-views/) + provides some comparison points between class based views (CBVs) and + function based views and the author's opinions for how you can better + understand CBVs. * Working with time zones is necessary for every web application. This [blog post on pytz and Django](http://tommikaikkonen.github.io/timezones/) is a great start for figuring out what you need to know. +* [A Guide to ASGI in Django 3.0 and its Performance](https://arunrocks.com/a-guide-to-asgi-in-django-30-and-its-performance/) + covers the new Asynchronous Server Gateway Interface (ASGI) that was + introduced in Django 3.0 and explains some of the nuances and gotchas + that you should consider if you decide to use it for your web apps. + * [REST APIs with Django: Build powerful web APIs with Python and Django](https://www.amazon.com/dp/198302998X) by [William S. Vincent](https://wsvincent.com/) is the book for you if you are just moving beyond the basics of Django and looking to get @@ -226,6 +234,7 @@ the framework. address can be used as the primary user identifier instead of a username for authentication. + ## Django Channels Channels are a new mechanism in Django 1.9 provided as a standalone app. They may be incorporated into the core framework in 2.0+. Channels provide @@ -252,6 +261,11 @@ based on [WebSockets](/websockets.html). is a good post to read for figuring out how to use [Gulp](http://gulpjs.com/) for handling front end tools in development and production Django sites. +* [Django Testing Cheat Sheet](https://www.valentinog.com/blog/testing-django/) + covers many common scenarios for Django applications such as testing + POST requests, request headers, authentication, and large numbers of + model fields in the [Django ORM](/django-orm.html). + * [Getting Started with Django Testing](http://howchoo.com/g/mjkwmtu5zdl/getting-started-with-django-testing) will help you stop procrastinating on testing your Django projects if you're uncertain where to begin. @@ -296,33 +310,6 @@ to handle these files properly. shows how to configure Django to load and serve up static and media files, public and private, via an Amazon S3 bucket. -## Open source Django example projects -* [Browser calls with Django and Twilio](https://www.twilio.com/docs/howto/walkthrough/browser-calls/python/django) - shows how to build a web app with Django and - [Twilio Client](https://www.twilio.com/client) to turn a user's web - browser into a full-fledged phone. Pretty awesome! - -* [Txt 2 React](https://github.com/mattmakai/txt2react) is a full Django web - app that allows audiences to text in during a presentation with feedback - or questions. - -* [Openduty](https://github.com/ustream/openduty) is a website status checking - and alert system similar to PagerDuty. - -* [Courtside](https://github.com/myusuf3/courtside) is a pick up sports web - application written and maintained by the author of PyCoder's Weekly. - -* These two Django Interactive Voice Response (IVR) system web application - repositories [part 1](https://github.com/phalt/twilio-django-part-1) and - [part 2](https://github.com/phalt/twilio-django-part-2) show you how to - build a really cool Django application. There's also an accompanying - [blog post](https://www.twilio.com/blog/2014/07/build-an-ivr-system-with-twilio-and-django.html) - with detailed explanations of each step. - -* [Taiga](https://github.com/taigaio/taiga-back) is a project management - tool built with Django as the backend and AngularJS as the front end. - - ## Django project templates Project templates, not to be confused with a [template engine](/template-engines.html), generate boilerplate code for @@ -330,7 +317,7 @@ a base Django project plus optional libraries that are often used when developing web applications. * [Caktus Group's Django project template](https://github.com/caktus/django-project-template) - is Django 1.6+ ready. + is Django 2.2+ ready. * [Cookiecutter Django](https://github.com/pydanny/cookiecutter-django) is a project template from Daniel Greenfeld, for use with Audrey Roy's @@ -345,25 +332,35 @@ developing web applications. template from Mozilla that is compatible with cookiecutter. -## Django learning checklist -1. [Install Django](https://docs.djangoproject.com/en/dev/topics/install/) on - your local development machine. +## Open source Django example projects +Reading open source code can be useful when you are trying to figure +out how to build your own projects. This is a short list of some +real-world example applications, and many more can be found on the +[Django example projects and code](/django-code-examples.html) page. + +* [Openduty](https://github.com/ustream/openduty) is a website status checking + and alert system similar to PagerDuty. + +* [Courtside](https://github.com/myusuf3/courtside) is a pick up sports web + application written and maintained by the author of PyCoder's Weekly. -1. Work through the initial - ["polls" tutorial](https://docs.djangoproject.com/en/dev/intro/tutorial01/). - -1. Build a few more simple applications using the tutorial resources found - in the "Django resources" section. +* These two Django Interactive Voice Response (IVR) system web application + repositories [part 1](https://github.com/phalt/twilio-django-part-1) and + [part 2](https://github.com/phalt/twilio-django-part-2) show you how to + build a really cool Django application. There's also an accompanying + [blog post](https://www.twilio.com/blog/2014/07/build-an-ivr-system-with-twilio-and-django.html) + with detailed explanations of each step. -1. Start coding your own Django project with help from the - [official documentation](https://docs.djangoproject.com/en/dev/) and - resource links below. You'll make plenty of mistakes which is critical - on your path to learning the right way to build applications. +* [Taiga](https://github.com/taigaio/taiga-back) is a project management + tool built with Django as the backend and AngularJS as the front end. -1. Read [2 Scoops of Django](http://www.amazon.com/Two-Scoops-Django-Best-Practices/dp/0981467342) - to understand Django good practices and learn better ways of building - Django web applications. +* [Chowist](https://github.com/huangsam/chowist) is a web application + that replicates core features of Yelp and adds a couple more bells + and whistles. -1. Move on to the [deployment section](/deployment.html) to get your Django - project on the web. +## Open source code to learn Django +There are many open source projects that rely on Django. +One of the best ways to learn how to use this framework is to read +how other projects use it in real-world code. This section lists +these code examples by class and method in Django's code base. diff --git a/content/pages/04-web-development/03-flask.markdown b/content/pages/04-web-development/03-flask.markdown index 29bc0212a..fd7625f0e 100644 --- a/content/pages/04-web-development/03-flask.markdown +++ b/content/pages/04-web-development/03-flask.markdown @@ -181,6 +181,11 @@ combined with the example real-world projects listed in the next section. [Docker](/docker.html). It shows how to [deploy](/deployment.html) it to an Amazon EC2 instance then scale the services on Amazon EC2 Container Service (ECS). +* [Build a Video Chat Application with Python, JavaScript and Twilio Programmable Video](https://www.twilio.com/blog/build-video-chat-application-python-javascript-twilio-programmable-video) + shows how to use [Twilio](/twilio.html) + [Programmable Video](https://www.twilio.com/video) to build cross-platform + (web, iOS and Android) video into Flask applications. + * [Why and how to handle exceptions in Python Flask](https://opensource.com/article/17/3/python-flask-exceptions) has some great example code and reasons why you should code defensively by anticipating and handling the unhappy path exceptions in your Flask @@ -200,9 +205,6 @@ combined with the example real-world projects listed in the next section. is a killer Flask tutorial with all the code needed to create a web app that can dial phones and receive inbound calls. -* Jeff Knupp provides some solid advice on how to - [productionize a Flask app](http://www.jeffknupp.com/blog/2014/01/29/productionizing-a-flask-application/). - * If you're looking for a fun tutorial with Flask and WebSockets, check out my blog post on creating [Choose Your Own Adventure Presentations with Reveal.js, Python and WebSockets](https://www.twilio.com/blog/2014/11/choose-your-own-adventure-presentations-with-reveal-js-python-and-websockets.html). @@ -293,7 +295,7 @@ about how to working on your codebase. * [Bean Counter](https://github.com/BouncyNudibranch/bean-counter) is an open source Flask app for tracking coffee. -* [FlaskBB](http://flaskbb.org/) is a Flask app for a discussion forum. +* [FlaskBB](https://flaskbb.org/) is a Flask app for a discussion forum. * [psdash](https://github.com/Jahaja/psdash) is an app built with Flask and psutils to display information about the computer it is running on. @@ -332,20 +334,8 @@ ways to structure your code. in the JavaScript world. -### Flask framework learning checklist -1. [Install Flask](http://flask.pocoo.org/docs/installation/) on - your local development machine. - -1. Work through the 18-part Flask tutorial listed first under "Flask - resources" above. - -1. Read through - [Flask Extensions Registry](http://flask.pocoo.org/extensions/) to find - out what extensions you'll need to build your project. - -1. Start coding your Flask app based on what you learned from the 18 part - Flask tutorial plus open source example applications found below. - -1. Move on to the [deployment section](/deployment.html) to get your initial - Flask project on the web. - +## Open source code for learning Flask +There are many open source projects that rely on Flask to operate. +One of the best ways to learn how to use this framework is to read +how other projects use it in real-world code. This section lists +these code examples by class and method in Flask. diff --git a/content/pages/04-web-development/04-bottle.markdown b/content/pages/04-web-development/04-bottle.markdown index 1f40db51c..01e543da4 100644 --- a/content/pages/04-web-development/04-bottle.markdown +++ b/content/pages/04-web-development/04-bottle.markdown @@ -29,7 +29,7 @@ Bottle is awesome for a few web development situations: Prototyping simple ideas is often easier with Bottle than a more opinionated web framework like [Django](/django.html) because Django projects start with a significant amount of boilerplate code. The -[Model-View-Template](https://docs.djangoproject.com/en/1.9/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names) +[Model-View-Template](https://docs.djangoproject.com/en/stable/intro/tutorial03/) structure for Django apps within projects makes maintaining projects easier, but it can be cumbersome on starter projects where you're just playing with random ideas so you aren't worried about your diff --git a/content/pages/04-web-development/11-template-engines.markdown b/content/pages/04-web-development/11-template-engines.markdown index f8b7bac06..551a70bfb 100644 --- a/content/pages/04-web-development/11-template-engines.markdown +++ b/content/pages/04-web-development/11-template-engines.markdown @@ -161,6 +161,10 @@ know how they work to aid your debugging. The following resources examine existing template engine design as well as how to build your own engine when that's necessary for your projects. +* [Writing a Jinja-inspired template library in Python](https://notes.eatonphil.com/writing-a-template-library-in-python.html) + walks through how to create your own a simplified version of the + [Jinja](/jinja2.html) template engine as a learning exercise. + * [How a template engine works](https://fengsp.github.io/blog/2016/8/how-a-template-engine-works/) uses the template module in Tornado as an example to step through how a template engine produces output, from parsing the incoming string to diff --git a/content/pages/04-web-development/12-jinja2.markdown b/content/pages/04-web-development/12-jinja2.markdown index 23137b27d..75feb4fdc 100644 --- a/content/pages/04-web-development/12-jinja2.markdown +++ b/content/pages/04-web-development/12-jinja2.markdown @@ -8,17 +8,17 @@ meta: Jinja2 is a template engine written in Python for outputting formats such Jinja, also commonly referred to as -"[Jinja2](http://jinja.pocoo.org/docs/dev/)" to specify the newest +"[Jinja2](https://jinja.palletsprojects.com/en/3.0.x/templates/)" to specify the newest release version, is a Python [template engine](/template-engines.html) used to create HTML, XML or other markup formats that are returned to the user via an HTTP response. -Logo for the Jinja template engine project. +Logo for the Jinja template engine project. ## Why is Jinja2 useful? Jinja2 is useful because it has consistent template tag syntax and the project is cleanly extracted as -[an independent open source project](https://github.com/mitsuhiko/jinja2) so +[an independent open source project](https://github.com/pallets/jinja) so it can be used as a dependency by other code libraries.
Jinja2 is an implementation of the template engines concept. Learn more in the web development chapter or view the table of contents for all topics.
@@ -31,9 +31,8 @@ end a developer can code whatever she wants. ## Jinja2 origin and development The first recorded public released of Jinja2 was in -[2008 with 2.0rc1](http://jinja.pocoo.org/docs/dev/changelog/#version-2-0rc1). -Since then the engine has seen numerous updates and remains in active -development. +2008 with 2.0rc1. Since then the engine has seen numerous updates and +remains under active development. Jinja2 engine certainly wasn't the first template engine. In fact, Jinja2's syntax is inspired by Django's built-in template engine, which was released @@ -72,7 +71,7 @@ open source project author from having to reinvent a new templating style. the template engine. * The official - [Jinja2 template designer documentation](http://jinja.pocoo.org/docs/dev/templates/) + [Jinja2 templates documentation](https://flask.palletsprojects.com/en/2.0.x/tutorial/templates/) is exceptionally useful both as a reference as well as a full read-through to understand how to properly work with template tags. diff --git a/content/pages/04-web-development/15-web-design.markdown b/content/pages/04-web-development/15-web-design.markdown index b02e8b4ab..58e9cc31f 100644 --- a/content/pages/04-web-development/15-web-design.markdown +++ b/content/pages/04-web-development/15-web-design.markdown @@ -21,6 +21,27 @@ Creating web pages with their own style and interactivity so users can easily accomplish their tasks is a major part of building modern web applications. +## Getting started if you have no "eye" for design +Design can feel like something "creative" people understand intuitively, +but like all skills design is something that can be learned. Some people +are faster learners in design just like some folks are quicker in +picking up programming. But anyone can learn how to be a better designer +by learning the basic principles and practicing them. + +One of the best mental models for basic design is C.R.A.P., which helped me +grasp why some designs look good while others do not. CRAP is an acronym +for: + + * Contrast: noticeable differences from one element to another + * Repetition: elements' consistency + * Alignment: order among all elements + * Proximity: placement between elements and how they are organized + +These basic principles all you to start breaking down the problem into +digestible pieces that you can work on rather than feeling like you +"just don't have an eye for design". + + ## Designing for various screen sizes Separating the content from the rules for how to display the content allows devices to render the output differently based on factors such as screen size @@ -50,7 +71,7 @@ this short list as my absolute favorites that help developers become page elements. * [Resilient web design](https://resilientwebdesign.com/) is an incredible - online book that teaches how to create websitess that are accessible to + online book that teaches how to create websites that are accessible to every reader and look great while doing it. * [Design 101 for Developers](https://academy.realm.io/posts/christopher-downer-design-101-for-developers/) @@ -62,14 +83,19 @@ this short list as my absolute favorites that help developers become design principles for building user experiences. Highly recommended even if just to see how the information is presented. +* [Building your color palette](https://refactoringui.com/previews/building-your-color-palette/) + explains why color pickers are not useful for most user interfaces + and how you should actually go about selecting your color palette + for a real world application. + * [How I Work with Color](https://medium.com/@JustinMezzell/how-i-work-with-color-8439c98ae5ed) is a fantastic article from a professional designer on how he thinks about color and uses it for certain effects in his designs. -* The [Bootstrapping Design](http://bootstrappingdesign.com/) book is one of - the clearest and concise resources for learning design that I've ever read. - Highly recommended especially if you feel you have no design skills but - need to learn them. +* [Building dark mode on Stack Overflow](https://stackoverflow.blog/2020/03/31/building-dark-mode-on-stack-overflow/) + explains the thought process and work that the team at Stack Overflow + had to do with colors, styling and the code implementation so they + could offer a dark mode design to their users. * [A short history of body copy sizes on the Web](https://fvsch.com/body-copy-sizes/) provides a useful examination of how originally the web's typography @@ -92,6 +118,14 @@ this short list as my absolute favorites that help developers become examples and further details for the four principles, which are contrast, consistency, Occam's Razor and space. +* [Gallery of web design history](https://www.webdesignmuseum.org/gallery) is + a collection of websites from between 1991 and 2006 that show the evolution + of what the web looked like before the modern + [CSS](/cascading-style-sheets.html) era. This is a great resource to see + how websites evolved, such as + [Microsoft in 1996](https://www.webdesignmuseum.org/gallery/microsoft-1996) + and [YouTube in 2005](https://www.webdesignmuseum.org/gallery/youtube-2005). + * [The Average Web Page (Data from Analyzing 8 Million Websites)](https://css-tricks.com/average-web-page-data-analyzing-8-million-websites/) shows the most frequently used HTML elements, metadata, text content and other statistics from a large scale analysis of the web. @@ -99,6 +133,11 @@ this short list as my absolute favorites that help developers become * [How to design delightful dark themes](https://blog.superhuman.com/how-to-design-delightful-dark-themes-7b3da644ff1f) explains some subtle tactics to make dark themes work well for users. +* [Setting height and width on images is important again](https://www.smashingmagazine.com/2020/03/setting-height-width-images-important-again/) + describes how browser layout and resizing settings could affect your + images so manually setting the size is more useful than it has + been in the past few years. + * [Kuler](https://kuler.adobe.com/create/color-wheel/) is a complementary color picker by Adobe that helps choose colors for your designs. @@ -108,6 +147,10 @@ this short list as my absolute favorites that help developers become [blog post series on building a browser engine](http://limpet.net/mbrubeck/2014/08/08/toy-layout-engine-1.html) that will show you how to build a simple rendering engine. +* [How to Use C.R.A.P. Design Principles for Better UX](https://vwo.com/blog/crap-design-principles/) + has a good summary of what contrast, repetition, alignment and + proximity means for designing user interfaces. + * [Defining Colors in CSS](https://pineco.de/defining-colors-in-css/) presents how to define color in your [Cascading Style Sheets (CSS)](/cascading-style-sheets.html) and breaks diff --git a/content/pages/04-web-development/16-html.markdown b/content/pages/04-web-development/16-html.markdown index 38f4bde17..6db9c57b0 100644 --- a/content/pages/04-web-development/16-html.markdown +++ b/content/pages/04-web-development/16-html.markdown @@ -41,3 +41,13 @@ and is used to display website and web application content. remains because there is not enough optimization juice to squeeze from changing the implementation compared to the backwards-breaking changes in rendering existing sites. + +* [A Complete Guide to Links and Buttons](https://css-tricks.com/a-complete-guide-to-links-and-buttons/) + extensively covers what might be thought of as a simple topic: the + `a` and `button` elements in HTML, along with their many attributes + and quirks. + +* [HTML: the inaccessible parts](https://daverupert.com/2020/02/html-the-inaccessible-parts/) + explains how even basic HTML elements can cause accessibility issues + for screen readers and other devices that help people with impairments + to use the web. diff --git a/content/pages/04-web-development/17-css.markdown b/content/pages/04-web-development/17-css.markdown index 273d04119..d50968d09 100644 --- a/content/pages/04-web-development/17-css.markdown +++ b/content/pages/04-web-development/17-css.markdown @@ -119,6 +119,14 @@ web application's design. provides advice on how to write simpler, easier-to-maintain CSS code to reduce your need to rely on CSS preprocessors and build pipelines. +* [How to Detect Unused CSS or JavaScript](https://javascript.plainenglish.io/detect-unused-css-or-javascript-in-your-code-8d200ef07e50) + explains how to use [Chrome DevTools](https://developer.chrome.com/docs/devtools/) + to analyze a page's CSS and identify parts that are not used. Note that + even though a specific page does not use that CSS (or JS), there might + be another page that uses the same CSS files and *does* use that "unused" + code, so test your pages before and after making the changes to ensure + you did not inadvertently break something else! + * [CSS refresher notes](https://github.com/vasanthk/css-refresher-notes) is incredibly helpful if you've learned CSS in bits and pieces along the way and you now want to fill in the gaps in your knowledge. @@ -149,10 +157,6 @@ web application's design. * [Google's Web Fundamentals class](https://developers.google.com/web/fundamentals/) shows how to create responsive designs and performant websites. -* [Tailoring CSS for performance](http://programming.oreilly.com/2014/04/tailoring-css-for-performance.html) - is an interesting read since many developers do not consider the - implications of CSS complexity in browser rendering time. - * [Can I Use...](http://caniuse.com/) is a compatibility table that shows which versions of browsers implement specific CSS features. @@ -173,15 +177,18 @@ web application's design. fix this situation with `display` as well as other less visible properties such as floats and `auto` width. -* [30 seconds of CSS](https://30-seconds.github.io/30-seconds-of-css/) - provides short useful code snippets for you to learn from and use for - building your own web applications. - -* [CSS: The bad bits](https://www.joeforshaw.com/blog/css-the-bad-bits-and-how-to-avoid-them) - examines global scope, implicit percentage styling rules and the z-index - which can be difficult to use and require some restraint to ensure they - do not cause issues for the rest of your stylesheet rules as you create - and maintain your frontend. +* [A brief history of CSS until 2016](https://www.w3.org/Style/CSS20/history.html) + explains how CSS originated at CERN in 1994 as a solution to the + problem of HTML not having reasonable styling features + (in-line `style` attributes on elements don't count). + +* [Old CSS, New CSS](https://eev.ee/blog/2020/02/01/old-css-new-css/) tells + the wonderful and painful story of web design in the early days of the + Web, when inline styling was required, HTML CAPS were mandatory, and + most websites wished they had design styles like the amazing + [Space Jam](https://www.spacejam.com/) pages. Oh also, lots and lots of + talk about tables, because that was the only way to position anything + back in the day. * [Improving Your CSS with Parker](https://csswizardry.com/2016/06/improving-your-css-with-parker/) shows how to use the static CSS analysis tool diff --git a/content/pages/04-web-development/20-css-frameworks.markdown b/content/pages/04-web-development/20-css-frameworks.markdown index 9772a3eb9..de0dbe3b2 100644 --- a/content/pages/04-web-development/20-css-frameworks.markdown +++ b/content/pages/04-web-development/20-css-frameworks.markdown @@ -12,14 +12,16 @@ a code library that abstracts common web designs and makes the designs easier for a developer to implement in their web apps. -### CSS frameworks +### CSS framework implementations * [Bootstrap](/bootstrap-css.html) * [Foundation](/foundation-css.html) -* Materialize +* [Screen](https://screencss.com/) -* Concise +* [Materialize](https://materializecss.com/) + +* [Concise](https://concisecss.com/) ### CSS framework resources diff --git a/content/pages/04-web-development/21-bootstrap.markdown b/content/pages/04-web-development/21-bootstrap.markdown index 8ca1c917f..97c4db1fa 100644 --- a/content/pages/04-web-development/21-bootstrap.markdown +++ b/content/pages/04-web-development/21-bootstrap.markdown @@ -47,6 +47,9 @@ specific situation. is an awesome tutorial that goes through many of the main Bootstrap elements such as icons, navigation bars and "jumbotron"-style webpages. +* [Bootstrap 5 tutorial](https://www.youtube.com/watch?v=c9B4TPnak1A) covers + the alpha version of the fifth major revision for Bootstrap. + * [Bootstrap 4: What's New?](https://medium.com/wdstack/bootstrap-4-whats-new-visual-guide-c84dd81d8387) shows a slew of comparisons for how user interface elements have changed design over the past several Bootstrap major version iterations. diff --git a/content/pages/04-web-development/23-javascript.markdown b/content/pages/04-web-development/23-javascript.markdown index d23bc1692..8440dcc4f 100644 --- a/content/pages/04-web-development/23-javascript.markdown +++ b/content/pages/04-web-development/23-javascript.markdown @@ -46,6 +46,10 @@ JavaScript is an implementation of [the ECMAScript specification](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/JavaScript_Overview) which is defined by the [Ecma International Standards Body](http://www.ecma-international.org/default.htm). +Read this paper on +[the first 20 years of JavaScript](https://zenodo.org/record/3710954) +by Brendan Eich, the original creator of the programming language, and +Allen Wirfs-Brock for more context on the language's evolution. ### JavaScript resources @@ -61,6 +65,12 @@ which is defined by the * [A re-introduction to JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) by Mozilla walks through the basic syntax and operators. +* [The Cost of Javascript Frameworks](https://timkadlec.com/remembers/2020-04-21-the-cost-of-javascript-frameworks/) + presents a balanced view of how JavaScript libraries and frameworks impact + web performance on both desktop and mobile. The author acknowledges that + these libraries are useful for developers but in extreme cases there are + significant downsides to including so much JavaScript in pages. + * [The State of JavaScript report](https://stateofjs.com/) contains a wealth of data on what libraries developers are using in the JavaScript ecosystem. There are also reports from previous years which show how the @@ -86,7 +96,13 @@ which is defined by the tools are that you can use and some comparisons when deciding between Angular and React. -* [Developing a Single Page App with Flask and Vue.js](https://testdriven.io/developing-a-single-page-app-with-flask-and-vuejs) step-by-step walkthrough of how to set up a basic CRUD app with Vue and Flask. +* [Developing a Single Page App with Flask and Vue.js](https://testdriven.io/developing-a-single-page-app-with-flask-and-vuejs) + is a step-by-step walkthrough of how to set up a basic CRUD app with + [Vue.js](/vuejs.html) and [Flask](/flask.html). + +* [A Guide to Console Commands](https://css-tricks.com/a-guide-to-console-commands/) + shows off what JavaScript commands you can use in your browser's console, + which is a typical debugging pattern for JavaScript development. * [is-website-vulnerable](https://github.com/lirantal/is-website-vulnerable) is an open source tool that identifies security vulnerabilities based on @@ -114,6 +130,15 @@ which is defined by the * [Learn JS data](http://learnjsdata.com/) teaches how to manipulate data using JavaScript in a browser or on the server using Node.js. +* [A Beginner's Guide to JavaScript's Prototype](https://ui.dev/beginners-guide-to-javascript-prototype/) + explains the fundamentals of JavaScript's object system, which is + a prototype-based model and different from many other common + programming languages' object models. + +* [Understanding Data Types in JavaScript](https://www.digitalocean.com/community/tutorials/understanding-data-types-in-javascript) + examines JavaScript's dynamic data type model and how it manifests + in the way numbers, string, Booleans and arrays are used. + ### JavaScript learning checklist 1. Create a simple HTML file with basic elements in it. Use the diff --git a/content/pages/04-web-development/24-react.markdown b/content/pages/04-web-development/24-react.markdown index 18ca6555b..518d5e929 100644 --- a/content/pages/04-web-development/24-react.markdown +++ b/content/pages/04-web-development/24-react.markdown @@ -35,6 +35,27 @@ tack on React to build your client-side user interfaces. quickly fall out of date while this one tends to stick to the basics that are relevant to beginners. +* [9 things every React.js beginner should know](https://camjackson.net/post/9-things-every-reactjs-beginner-should-know) + is not a tutorial but instead the author gives some strong opinions for + what beginners should know as they start learning React. + +* [React Bootstrap](https://react-bootstrap.github.io/) + ([source code](https://github.com/react-bootstrap/react-bootstrap) replaces + the existing Bootstrap JavaScript with React components that do not + rely on jQuery. + + +## Python+React tutorials +* [How to set up Django with React](https://mattsegal.dev/django-react.html) + presents one developer's opinionated way of combining a + [Django](/django.html)-powered back end with React on the front end, + including how to serve up static assets. + +* [Django REST with React (Django 2.0 and a sprinkle of testing)](https://www.valentinog.com/blog/tutorial-api-django-rest-react/) + combines a [Django](/django.html) plus + [Django REST Framework (DRF)](/django-rest-framework-drf.html) backend + with React on the front end and shows how to stich it all together. + * This Modern Django 4-part tutorial series is well-done, has [freely available source code](https://github.com/v1k45/ponynote) and includes: @@ -44,10 +65,6 @@ tack on React to build your client-side user interfaces. 3. [Creating an API and integrating with React](http://v1k45.com/blog/modern-django-part-3-creating-an-api-and-integrating-with-react/) 4. [Adding authentication to React SPA using DRF](http://v1k45.com/blog/modern-django-part-4-adding-authentication-to-react-spa-using-drf/) -* [Django REST with React (Django 2.0 and a sprinkle of testing)](https://www.valentinog.com/blog/tutorial-api-django-rest-react/) - combines a [Django](/django.html) plus - [Django REST Framework (DRF)](/django-rest-framework-drf.html) backend - with React on the front end and shows how to stich it all together. * [Build a Simple CRUD App with Python, Flask, and React](https://developer.okta.com/blog/2018/12/20/crud-app-with-python-flask-react) shows how to combine a [Flask](/flask.html) backend with React. @@ -56,15 +73,6 @@ tack on React to build your client-side user interfaces. is a Git repository with a code tutorial and instructions for how to follow along, as well as exercises to ensure you are tested as you go. -* [9 things every React.js beginner should know](https://camjackson.net/post/9-things-every-reactjs-beginner-should-know) - is not a tutorial but instead the author gives some strong opinions for - what beginners should know as they start learning React. - -* [React Bootstrap](https://react-bootstrap.github.io/) - ([source code](https://github.com/react-bootstrap/react-bootstrap) replaces - the existing Bootstrap JavaScript with React components that do not - rely on jQuery. - ### Other React resources * [React interview questions](https://tylermcginnis.com/react-interview-questions/) diff --git a/content/pages/04-web-development/25-vuejs.markdown b/content/pages/04-web-development/25-vuejs.markdown index 73c979499..934f720b0 100644 --- a/content/pages/04-web-development/25-vuejs.markdown +++ b/content/pages/04-web-development/25-vuejs.markdown @@ -34,6 +34,11 @@ rich apps that run in web browsers. ### Vue.js resources +* [Building web apps with Vue and Django](https://dafoster.net/articles/2021/02/16/building-web-apps-with-vue-and-django-the-ultimate-guide/) + covers architectural decisions such as whether to use one or + two servers and then explains how to go down the one server + route with a [Django](/django.html) back end. + * [A friendly introduction to Vue.js](https://appendto.com/2016/11/a-friendly-introduction-to-vue-js/) contains the code and brief explanations of what it's doing so you can learn to create your first Vue app. @@ -43,6 +48,11 @@ rich apps that run in web browsers. coding you need to do to build a legitimate Vue.js application that uses a [Flask](/flask.html) API on the backend. +* [Building a SaaS using Django and Vue.js](https://www.youtube.com/playlist?list=PLpyspNLjzwBnGesxJOt_0r4xTWR80j7Y3) + shows how to create a software-as-a-service application with a + [Django](/django.html) back end and Vue on the front end via a + series of videos that are each between 10-15 minutes in length. + * [Learn Vue by Building and Deploying a CRUD App](https://testdriven.io/courses/learn-vue/?utm_source=fsp) is an awesome course that walks through the Vue basics and building a whole application and deploying it to diff --git a/content/pages/04-web-development/27-task-queues.markdown b/content/pages/04-web-development/27-task-queues.markdown index 073759f6e..70ec128c2 100644 --- a/content/pages/04-web-development/27-task-queues.markdown +++ b/content/pages/04-web-development/27-task-queues.markdown @@ -100,13 +100,6 @@ when scaling out a large deployment of distributed task queues. ## Open source examples that use task queues -* Take a look at the code in this open source - [Flask application](https://www.twilio.com/docs/howto/walkthrough/appointment-reminders/python/flask) - and - [this Django application](https://www.twilio.com/docs/howto/walkthrough/appointment-reminders/python/django) - for examples of how to use and deploy Celery with a Redis broker to - send text messages with these frameworks. - * [flask-celery-example](https://github.com/thrisp/flask-celery-example) is a simple Flask application with Celery as a task queue and Redis as the broker. @@ -128,10 +121,6 @@ when scaling out a large deployment of distributed task queues. is a detailed comparison of Amazon SQS, MongoDB, RabbitMQ, HornetQ and Kafka's designs and performance. -* [Queues.io](http://queues.io/) is a collection of task queue systems with - short summaries for each one. The task queues are not all compatible with - Python but ones that work with it are tagged with the "Python" keyword. - * [Why Task Queues](http://www.slideshare.net/bryanhelmig/task-queues-comorichweb-12962619) is a presentation for what task queues are and why they are needed. @@ -187,10 +176,6 @@ when scaling out a large deployment of distributed task queues. is a straightforward tutorial for setting up the Celery task queue for Django web applications using the Redis broker on the back end. -* [Three quick tips from two years with Celery](https://library.launchkit.io/three-quick-tips-from-two-years-with-celery-c05ff9d7f9eb) - provides some solid advice on retry delays, the -Ofair flag and global - task timeouts for Celery. - * [Asynchronous Tasks with Flask and Redis Queue](https://testdriven.io/asynchronous-tasks-with-flask-and-redis-queue) looks at how to configure Redis Queue to handle long-running tasks in a Flask app. diff --git a/content/pages/04-web-development/28-celery.markdown b/content/pages/04-web-development/28-celery.markdown index 1ae8eeee0..6746997d1 100644 --- a/content/pages/04-web-development/28-celery.markdown +++ b/content/pages/04-web-development/28-celery.markdown @@ -7,11 +7,11 @@ sidebartitle: Celery meta: Celery is a task queue for executing work outside a Python web application HTTP request-response cycle. -[Celery](http://www.celeryproject.org/) is a [task queue](/task-queues.html) +[Celery](https://docs.celeryproject.org/) is a [task queue](/task-queues.html) implementation for [Python web applications](/web-development.html) used to asynchronously execute work outside the HTTP request-response cycle. -Celery task queue project logo. +Celery task queue project logo.
Celery is an implementation of the task queue concept. Learn more in the web development chapter or view the table of contents for all topics.
@@ -74,6 +74,10 @@ then dive into these specific Celery tutorials. is a different author's follow up to the above best practices post that builds upon some of his own learnings from 3+ years using Celery. +* [Common Issues Using Celery (And Other Task Queues)](https://adamj.eu/tech/2020/02/03/common-celery-issues-on-django-projects/) + contains good advice about mistakes to avoid in your task configurations, + such as database transaction usage and retrying failed tasks. + * [Asynchronous Processing in Web Applications Part One](http://blog.thecodepath.com/2012/11/15/asynchronous-processing-in-web-applications-part-1-a-database-is-not-a-queue/) and [Part Two](http://blog.thecodepath.com/2013/01/06/asynchronous-processing-in-web-applications-part-2-developers-need-to-understand-message-queues/) are great reads for understanding the difference between a task queue and @@ -159,10 +163,6 @@ web framework of your choice. is a detailed walkthrough for setting up Celery with Django (although Celery can also be used without a problem with other frameworks). -* [Introducing Celery for Python+Django](http://www.linuxforu.com/2013/12/introducing-celery-pythondjango/) - provides an introduction to the Celery task queue with Django as the - intended framework for building a web application. - * [Asynchronous Tasks with Falcon and Celery](https://testdriven.io/asynchronous-tasks-with-falcon-and-celery) configures Celery with the [Falcon](/falcon.html) framework, which is less commonly-used in web tutorials. @@ -172,6 +172,10 @@ web framework of your choice. for transient states in your application that are not covered by the default Celery configuration. +* [Asynchronous Tasks with Django and Celery](https://testdriven.io/blog/django-and-celery/) + looks at how to configure Celery to handle long-running tasks in a + Django app. + ### Celery deployment resources Celery and its broker run separately from your web and WSGI servers so it @@ -179,19 +183,7 @@ adds some additional complexity to your [deployments](/deployment.html). The following resources walk you through how to handle deployments and get the right configuration settings in place. -* The "Django in Production" series by - [Rob Golding](https://twitter.com/robgolding63) contains a post - specifically on [Background Tasks](http://www.robgolding.com/blog/2011/11/27/django-in-production-part-2---background-tasks/). - * [How to run celery as a daemon?](https://pythad.github.io/articles/2016-12/how-to-run-celery-as-a-daemon-in-production) is a short post with the minimal code for running the Celery daemon and Celerybeat as system services on Linux. -* [Celery in Production](http://www.caktusgroup.com/blog/2014/09/29/celery-production/) - on the Caktus Group blog contains good practices from their experience - using Celery with RabbitMQ, monitoring tools and other aspects not often - discussed in existing documentation. - -* [Three quick tips from two years with Celery](https://library.launchkit.io/three-quick-tips-from-two-years-with-celery-c05ff9d7f9eb) - provides some solid advice on retry delays, the `-Ofair` flag and global - task timeouts for Celery. diff --git a/content/pages/04-web-development/29-rq-redis-queue.markdown b/content/pages/04-web-development/29-rq-redis-queue.markdown index 55979bf3c..b9fe01a39 100644 --- a/content/pages/04-web-development/29-rq-redis-queue.markdown +++ b/content/pages/04-web-development/29-rq-redis-queue.markdown @@ -19,7 +19,7 @@ track of tasks in the queue that need to be executed. ### RQ resources * [Asynchronous Tasks in Python with Redis Queue](https://www.twilio.com/blog/asynchronous-tasks-in-python-with-redis-queue) is a quickstart-style tutorial that shows how to use RQ to fetch data - from the + from the [Mars Rover web API](https://data.nasa.gov/Space-Science/Mars-Rover-Photos-API/929k-jizu) and process URLs for each of the photos taken by NASA's Mars rover. There is also a follow-up post on @@ -30,6 +30,10 @@ track of tasks in the queue that need to be executed. * The [RQ intro post](http://nvie.com/posts/introducing-rq/) contains information on design decisions and how to use RQ in your projects. +* [Build a Ghostwriting App for Scary Halloween Stories with OpenAI's GPT-3 Engine and Task Queues in Python](https://www.twilio.com/blog/ghost-writer-spooky-task-queues-python-openai-gpt3) + is a fun tutorial that uses RQ with OpenAI's [GPT-3](/gpt-3.html) API + randomly write original stories inspired by creepy Halloween tales. + * [International Space Station notifications with Python and Redis Queue (RQ)](https://www.twilio.com/blog/2015/11/international-space-station-notifications-with-python-redis-queue-and-twilio-copilot.html) shows how to combine the RQ task queue library with Flask to send text message notifications every time a condition is met - in this blog diff --git a/content/pages/04-web-development/31-static-site-generator.markdown b/content/pages/04-web-development/31-static-site-generator.markdown index 7b07bc047..d7f3c0983 100644 --- a/content/pages/04-web-development/31-static-site-generator.markdown +++ b/content/pages/04-web-development/31-static-site-generator.markdown @@ -206,12 +206,6 @@ point a domain name to your site as well as provide HTTPS support. These guides walk through various ways of handling the static site deployment. -* [Static site hosting with S3 and Cloudflare](https://wsvincent.com/static-site-hosting-with-s3-and-cloudflare/) - shows how to set up an S3 bucket with Cloudflare in front as a CDN that - serves the content with HTTPS. You should be able to accomplish roughly - the same situation with Amazon Cloudfront, but as a Cloudflare user I - like their service for these static site configurations. - * Google Cloud provides a tutorial on how to use them to [host your static site](https://cloud.google.com/storage/docs/hosting-static-website). Note that you cannot currently use HTTPS on Google Storage servers, which is a @@ -221,7 +215,7 @@ deployment. making static site deployments and redeployments to Amazon Web Services easier. -* [Deploying a Static Blog with Continuous Integration](https://www.loxodrome.io/post/hugo-on-ci/) +* [Deploying a Static Blog with Continuous Integration](https://www.jameslmilner.com/post/hugo-on-ci/) uses a Hugo (a Golang-based static site generator) generated site as an example but the instructions can easily be used to deploy a Python-based static site generator output as well. diff --git a/content/pages/04-web-development/32-pelican.markdown b/content/pages/04-web-development/32-pelican.markdown index 94f9e36f6..c1b0c0810 100644 --- a/content/pages/04-web-development/32-pelican.markdown +++ b/content/pages/04-web-development/32-pelican.markdown @@ -18,7 +18,7 @@ Pelican's under the [AGPL 3 license](https://www.gnu.org/licenses/why-affero-gpl.html). -Pelican static website generator logo. +Pelican static website generator logo.
Pelican is an implementation of the static site generators concept. Learn how the parts fit together in the web development chapter or view all topics.
@@ -76,10 +76,6 @@ to hosting services such as Amazon S3 and GitHub Pages. take in new input markup formats, modify the generator process and add handy features such as a custom table of contents. -* [Pelican Sitemap and Pagination](http://www.vcheng.org/2014/02/22/pelican-sitemap-pagination/) - explains how to generate a `sitemap.xml` file for your static site that - includes all pages instead of just auto-included top-level pages. - * [Getting started with Pelican and GitHub pages](http://www.mattmakai.com/introduction-to-pelican.html) is a tutorial I wrote to use the Full Stack Python source code to create and deploy your first static site. diff --git a/content/pages/04-web-development/35-testing.markdown b/content/pages/04-web-development/35-testing.markdown index a69c8f126..7594935d2 100644 --- a/content/pages/04-web-development/35-testing.markdown +++ b/content/pages/04-web-development/35-testing.markdown @@ -101,6 +101,12 @@ test runners, coverage reports and related libraries. * [A beginner's guide to Python testing](https://miguelgfierro.com/blog/2018/a-beginners-guide-to-python-testing/) covers test-driven development for unit, integration and smoke tests. +* [Testing a Twilio Interactive Voice Response (IVR) System With Python and pytest](https://www.twilio.com/blog/testing-twilio-ivr-system-python-pytest) + is an incredibly in-depth tutorial on testing a Python-powered IVR + using pytest. There is also a tutorial on + [how to build the IVR before this testing tutorial](https://www.twilio.com/blog/building-interactive-voice-response-ivr-system-python-django-twilio), + although you can just clone it to jump into the testing walkthrough. + * Still confused about the difference between unit, functional and integration tests? Check out this [top answer on Stack Overflow](http://stackoverflow.com/questions/4904096/whats-the-difference-between-unit-functional-acceptance-and-integration-test) @@ -170,10 +176,10 @@ use mocks in your test cases. provides a whole code example based on a blog project that shows how to use `mock` when testing. -* [Python Mocking 101: Fake It Before You Make It](https://blog.fugue.co/2016-02-11-python-mocking-101.html) +* [Python Mocking 101: Fake It Before You Make It](https://www.fugue.co/blog/2016-02-11-python-mocking-101) explains what mocking is and is not, and shows how to use the `patch` function to accomplish it in your project. - [Revisiting Unit Testing and Mocking in Python](https://blog.fugue.co/2017-07-18-revisiting-unit-testing-and-mocking-in-python.html) + [Revisiting Unit Testing and Mocking in Python](https://www.fugue.co/blog/2017-07-18-revisiting-unit-testing-and-mocking-in-python.html) is a follow-up post that expands upon using the `patch` function along with dependency injection. @@ -185,12 +191,6 @@ use mocks in your test cases. examines when mocks are necessary and when they are not as useful so you can avoid them in your test cases. -* [Mocking Redis & Expiration in Python](http://malexandre.fr/2017/10/08/mocking-redis--expiration-in-python/) - is a specific scenario where you would want to test your - [Redis](/redis.html)-dependent code but prefer to mock it rather than - ensure an installation and connection are present whenever you run - your tests. - * [Better tests for Redis integrations with redislite](https://www.obeythetestinggoat.com/better-tests-for-redis-integrations-with-redislite.html) is a great example of how using the right mocking library can clean up existing hacky testing code and make it more straightforward for diff --git a/content/pages/04-web-development/36-unit-testing.markdown b/content/pages/04-web-development/36-unit-testing.markdown index 86bebc128..9002c90d6 100644 --- a/content/pages/04-web-development/36-unit-testing.markdown +++ b/content/pages/04-web-development/36-unit-testing.markdown @@ -70,10 +70,6 @@ Python-specific applications. is a detailed tutorial for using the nose test runner for ensuring a Flask application is working properly. -* [Understanding unit testing](https://jeffknupp.com/blog/2013/12/09/improve-your-python-understanding-unit-testing/) - explains why testing is important and shows how to do it effectively in - your applications. - * [Unit testing with Python](http://www.drdobbs.com/testing/unit-testing-with-python/240165163) provides a high-level overview of testing and has diagrams to demonstrate what's going on in the testing cycle. diff --git a/content/pages/04-web-development/37-integration-testing.markdown b/content/pages/04-web-development/37-integration-testing.markdown index 72d844b82..8594b4492 100644 --- a/content/pages/04-web-development/37-integration-testing.markdown +++ b/content/pages/04-web-development/37-integration-testing.markdown @@ -36,9 +36,6 @@ during development so they can be addressed immediately. gives an example of a system that needs integration tests and shows how context managers can be used to address the problem. -* Pytest has a page on [integration good practices](http://doc.pytest.org/en/latest/goodpractices.html) - that you'll likely want to follow when testing your application. - * [Integration testing, or how to sleep well at night](http://enterprisecraftsmanship.com/2015/07/13/integration-testing-or-how-to-sleep-well-at-nights/) explains what integration tests are and gives an example. The example is coded in Java but still relevant when you're learning about integration diff --git a/content/pages/04-web-development/38-debugging.markdown b/content/pages/04-web-development/38-debugging.markdown index 88f4999e1..8cf576d27 100644 --- a/content/pages/04-web-development/38-debugging.markdown +++ b/content/pages/04-web-development/38-debugging.markdown @@ -19,6 +19,31 @@ There are bugs in every modest sized or larger application. Every developer has to learn how to debug code in order to write programs that work as correctly as time and budget allow. +In addition to fixing bugs, debugging is an important skill for improving +the efficiency of an application by optimizing performance and improving +the logic. Debugging is a complex skill that takes time and practice +for a developer to gain as a capability. + + +## What are some common debugging techniques? +Some common debugging techniques include: + +* Printing out or displaying values of variables and state + at certain times during the execution of an application + +* Changing the state of a program to make it do different + things. This is called altering the "path" of the program + +* Stepping through the execution of a program line by line + +* Breakpoints + +* Trace Points + +* Stopping the program at certain events + +* Viewing the output of a program in a debugger window + ### Debugging tools There are many debugging tools, some of which are built into @@ -112,10 +137,6 @@ give solid programming language-agnostic debugging advice. * [The art of debugging](https://remysharp.com/2015/10/14/the-art-of-debugging) provides a whirlwind overview for how to fix issues in your code. -* [How to debug JavaScript errors](https://rollbar.com/guides/how-to-debug-javascript/) - introduces some key debugging tools such as source maps that make - identifying errors on the client side much easier during development. - * [Linux debugging tools you'll love](https://jvns.ca/debugging-zine.pdf) is an awesome comic that covers the Linux ecosystem for debugging. diff --git a/content/pages/04-web-development/39-code-metrics.markdown b/content/pages/04-web-development/39-code-metrics.markdown index 6f1eb3df0..1ce96176f 100644 --- a/content/pages/04-web-development/39-code-metrics.markdown +++ b/content/pages/04-web-development/39-code-metrics.markdown @@ -48,7 +48,7 @@ system are occurring. * [Black](https://github.com/ambv/black) is a Python code formatter with strong, uncompromising assumptions about how your code must be formatted. -* [dlint](https://github.com/duo-labs/dlint) is a linter for secure coding +* [dlint](https://github.com/dlint-py) is a linter for secure coding practices. * [pylintdb](https://github.com/nedbat/pylintdb) puts pylint results into @@ -151,10 +151,6 @@ diminishing returns. covers Pylint, PyFlakes and mypy with a short description of the advantages and disadvantage for each one. -* [Dynamic tracing a Pony + Python program with DTrace](https://blog.wallaroolabs.com/2017/12/dynamic-tracing-a-pony---python-program-with-dtrace/) - shows how to use dynamic tracing programs to analyze code - at runtime. - * This [Stack Overflow question on Python static code analysis tools](http://stackoverflow.com/questions/1428872/pylint-pychecker-or-pyflakes) contains comparison discussions of PyLint, PyChecker and PyFlakes. @@ -169,3 +165,7 @@ diminishing returns. * [Intro to Black – The Uncompromising Python Code Formatter](http://www.blog.pythonlibrary.org/2019/07/16/intro-to-black-the-uncompromising-python-code-formatter/) contains some introductory examples for using Black and shows how to use it on your source files. + +* [Python static analysis tools](https://luminousmen.com/post/python-static-analysis-tools) + is a quick overview of the features for Black, Pylint, Pyflakes, Mypy, + Bandit and Prospector. diff --git a/content/pages/04-web-development/40-networking.markdown b/content/pages/04-web-development/40-networking.markdown index 15ab8fce9..7e690cdba 100644 --- a/content/pages/04-web-development/40-networking.markdown +++ b/content/pages/04-web-development/40-networking.markdown @@ -13,6 +13,19 @@ web applications. ### Resources about networking +The "Let's code a TCP/IP stack" series along with its +[open source code](https://github.com/saminiir/level-ip) gives a ton of +context on how TCP/IP works while providing the code for implementing the +foundational pieces. You will likely need to pair this with a more theoretical +reference tutorial such as [RFC 1180](https://tools.ietf.org/html/rfc1180) +to have a more complete understanding of the protocol: + +1. [Ethernet & ARP](http://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/) +1. [IPv4 & ICMPv4](http://www.saminiir.com/lets-code-tcp-ip-stack-2-ipv4-icmpv4/) +1. [TCP Basics & Handshake](http://www.saminiir.com/lets-code-tcp-ip-stack-3-tcp-handshake/) +1. [TCP Data Flow & Socket API](http://www.saminiir.com/lets-code-tcp-ip-stack-4-tcp-data-flow-socket-api/) +1. [TCP Retransmission](http://www.saminiir.com/lets-code-tcp-ip-stack-5-tcp-retransmission/) + * [Monitoring and Tuning the Linux Networking Stack: Receiving Data](https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/) along with [Monitoring and Tuning the Linux Networking Stack: Sending Data](https://blog.packagecloud.io/eng/2017/02/06/monitoring-tuning-linux-networking-stack-sending-data/) @@ -38,3 +51,7 @@ web applications. explains how Dropbox uses edge-of-the-network resources closer to the end user to optimize performance of their service. +* [On the shoulders of giants: recent changes in Internet traffic](https://blog.cloudflare.com/on-the-shoulders-of-giants-recent-changes-in-internet-traffic/) + examines how the COVID-19 pandemic of 2020 changed the times during the + day and locations of how the majority of internet traffic was routed + and consumed. diff --git a/content/pages/04-web-development/41-https.markdown b/content/pages/04-web-development/41-https.markdown index ffe55e7c9..3bbb8239a 100644 --- a/content/pages/04-web-development/41-https.markdown +++ b/content/pages/04-web-development/41-https.markdown @@ -64,7 +64,3 @@ client web browser. cover the high-level information on the latest approved version of Transport Security Layer (TLS) 1.3. -* [How https works](https://www.sudhakar.online/programming/2015/08/09/https.html) - is a fun cartoon illustration that demonstrates the basic concepts of - a secure HTTP connection. - diff --git a/content/pages/04-web-development/42-websockets.markdown b/content/pages/04-web-development/42-websockets.markdown index fb8293c46..2a902f79c 100644 --- a/content/pages/04-web-development/42-websockets.markdown +++ b/content/pages/04-web-development/42-websockets.markdown @@ -7,10 +7,10 @@ sidebartitle: WebSockets meta: WebSockets are a protocol for full-duplex web communications. Learn about WebSockets on Full Stack Python. -A WebSocket is a [standard protocol](http://tools.ietf.org/html/rfc6455) for -two-way data transfer between a client and server. The WebSockets protocol -does not run over HTTP, instead it is a separate implementation on top of -[TCP](http://en.wikipedia.org/wiki/Transmission_Control_Protocol). +A WebSocket is a [standard protocol](https://datatracker.ietf.org/doc/html/rfc6455) +for two-way data transfer between a client and server. The WebSockets +protocol does not run over HTTP, instead it is a separate implementation +on top of [TCP](http://en.wikipedia.org/wiki/Transmission_Control_Protocol). ## Why use WebSockets? @@ -173,12 +173,6 @@ own project. that demos sending server generated events as well as input from users via a text box input on a form. -* The [realtime codenames game](https://github.com/joshporter1/codenames) - source code is a full-featured example for using WebSockets via - Flask-SocketIO. There is also a - [multi-part tutorial](https://secdevops.ai/weekend-project-part-1-creating-a-real-time-web-based-application-using-flask-vue-and-socket-b71c73f37df7) - that walks through the code. - * The [python-websockets-example](https://github.com/mattmakai/python-websockets-example) contains code to create a simple web application that provides WebSockets @@ -192,13 +186,6 @@ own project. Flask web app implementation that allows the audience to interact with WebSockets as I built out the application. -* [Creating a Real-time Web-based Application using Flask, Vue, and Socket.io: part 1](https://secdevops.ai/weekend-project-part-1-creating-a-real-time-web-based-application-using-flask-vue-and-socket-b71c73f37df7), - [part 2](https://secdevops.ai/weekend-project-part-2-turning-flask-into-a-real-time-websocket-server-using-flask-socketio-ab6b45f1d896) - and - [part 3](https://secdevops.ai/weekend-project-part-3-centralizing-state-management-with-vuex-5f4387ebc144) - are a complete front-to-backend WebSockets, Python and JavaScript front - end framework example with open source code. - * [Real-time in Python](http://mrjoes.github.io/2013/06/21/python-realtime.html) provides Python-specific context for how the server push updates were implemented in the past and how Python's tools have evolved to perform @@ -206,9 +193,7 @@ own project. * [websockets](https://github.com/aaugustin/websockets) is a WebSockets implementation for Python 3.3+ written with the - [asyncio](https://docs.python.org/3.4/library/asyncio.html) module (or with - [Tulip](https://code.google.com/p/tulip/) if you're working with - Python 3.3). + [asyncio](https://docs.python.org/3.9/library/asyncio.html) module. * [Speeding up Websockets 60X](https://www.willmcgugan.com/blog/tech/post/speeding-up-websockets-60x/) is a cool experiment in coding loops different ways to eek out more @@ -217,10 +202,6 @@ own project. of how tweaking and tuning can produce outsized returns in some applications. -* The [Choose Your Own Adventure Presentations](https://www.twilio.com/blog/2014/11/choose-your-own-adventure-presentations-with-reveal-js-python-and-websockets.html) - tutorial uses WebSockets via gevent on the server and socketio.js for - pushing vote count updates from the server to the client. - * [Adding Real Time to Django Applications](http://crossbar.io/docs/Adding-Real-Time-to-Django-Applications/) shows how to use Django and Crossbar.io to implement a publish/subscribe feature in the application. diff --git a/content/pages/04-web-development/43-webrtc.markdown b/content/pages/04-web-development/43-webrtc.markdown index 46fe12109..e34ac044a 100644 --- a/content/pages/04-web-development/43-webrtc.markdown +++ b/content/pages/04-web-development/43-webrtc.markdown @@ -18,10 +18,13 @@ browser) and server (usually a [web server](/web-servers.html)). explains what you do and do not need to know as prerequisites for building with WebRTC along with some sources for learning. -* [A real world guide to WebRTC](https://deepstreamhub.com/tutorials/protocols/webrtc-intro/) - goes through WebRTC fundamentals such as data channels, audio and video, - screen sharing and file transfers with the JavaScript code provided - for each concept. +* This post titled + [WebRTC: a working example](http://pfertyk.me/2020/03/webrtc-a-working-example/) + and the + [companion open source repository](https://github.com/pfertyk/webrtc-working-example) + provides a simple working example of WebRTC technology, without any 3rd party + dependencies. It allows 2 web browsers to exchange audio and video streams by + using the `aiohttp` and `python-socketio` modules. * The [Introduction to WebRTC video series](https://www.youtube.com/watch?v=ujpIAWmK2Vo) @@ -30,10 +33,6 @@ browser) and server (usually a [web server](/web-servers.html)). at points but overall has a ton of good information that gives a solid overview of the technology. -* [Building a Snapchat-like app with WebRTC in the browser](https://tokbox.com/blog/building-a-snapchat-like-app-with-webrtc-in-the-browser/) - walks through the front end JavaScript for building a photo filter - application using the WebRTC browser APIs. - * [WebRTC issues and how to debug them](https://blog.codeship.com/webrtc-issues-and-how-to-debug-them/) explains the various ways that implementations can go wrong and where to start looking when you run into errors. diff --git a/content/pages/04-web-development/44-web-apis.markdown b/content/pages/04-web-development/44-web-apis.markdown index a0e1eea19..77ce68888 100644 --- a/content/pages/04-web-development/44-web-apis.markdown +++ b/content/pages/04-web-development/44-web-apis.markdown @@ -43,7 +43,7 @@ Webhooks are important because they enable two-way communication initiation for APIs. Webhook flexibility comes in from their definition by the API user instead of the API itself. -For example, in the [Twilio API](https://www.twilio.com/api) when a text +For example, in the [Twilio API](https://www.twilio.com/docs/api) when a text message is sent to a Twilio phone number Twilio sends an HTTP POST request webhook to the URL specified by the user. The URL is defined in a text box on the number's page on Twilio as shown below. @@ -91,11 +91,6 @@ on the number's page on Twilio as shown below. provides context for why JSON-based web services are more common today than SOAP which was popular in the early 2000s. -* [API tools for every occasion](https://medium.com/@orliesaurus/api-tools-for-every-occasion-10-api-tools-released-in-2015-i-can-t-live-without-d5947d9ca9c3) - provides a list of 10 tools that are really helpful when working with APIs - that are new in 2015. - - ## APIs learning checklist 1. Learn the API concepts of machine-to-machine communication with JSON and diff --git a/content/pages/04-web-development/45-microservices.markdown b/content/pages/04-web-development/45-microservices.markdown index d8754b0a6..0b06889e6 100644 --- a/content/pages/04-web-development/45-microservices.markdown +++ b/content/pages/04-web-development/45-microservices.markdown @@ -40,22 +40,6 @@ ease further development and deployment. This approach is called the article is one of the best in-depth explanations for what microservices are and why to consider them as an architectural pattern. -* [Why microservices?](http://dev.otto.de/2016/03/20/why-microservices/) - presents some of the advantages, such as the dramatically increased number - of deployments per day, that a well-done microservices architecture can - provide in the right situation. Many organizational environments won't - allow this level of flexibility but if yours is one that will, it's worth - considering these points. - -* [On monoliths and microservices](http://dev.otto.de/2015/09/30/on-monoliths-and-microservices/) - provides some advice on using microservices in a fairly early stage of - a software project's lifecycle. - -* [Why Microservices?](https://dev.otto.de/2016/03/20/why-microservices/) - presents advantages microservices can bring to an existing monolithic - application where it is clear what needs to be broken down into smaller - components to make it easier to iterate and maintain. - * [Developing a RESTful microservice in Python](http://www.skybert.net/python/developing-a-restful-micro-service-in-python/) is a good story of how an aging Java project was replaced with a microservice built with Python and Flask. @@ -91,12 +75,17 @@ ease further development and deployment. This approach is called the text go into how reality gets messy and how to embrace the constraints inherent in distributed systems. -* In the [Microservices with Docker, Flask, and React](http://testdriven.io/) - course, you will learn how to quickly spin up a reproducible development - environment with Docker to manage a number of microservices. Once the app - is up and running locally, you'll learn how to deploy it to an Amazon EC2 - instance. Finally, we'll look at scaling the services on Amazon EC2 - Container Service (ECS). +* In the + [Microservices with Docker, Flask, and React](https://testdriven.io/bundle/microservices-with-docker-flask-and-react/?utm_source=fsp) + course bundle, you will learn how to quickly spin up a reproducible + development environment with Docker to manage a number of microservices. + Once the app is up and running locally, you'll learn how to deploy it to + an Amazon EC2 instance. Finally, we'll look at scaling the services on + Amazon EC2 Container Service (ECS). + +* [Should I use microservices?](https://www.oreilly.com/ideas/should-i-use-microservices) + contains a high-level perspective on why or why not use microservices + as an architectural choice. * Zuul is open source proxy for combining multiple microservices into a unified API call. Check out this post on @@ -123,3 +112,7 @@ ease further development and deployment. This approach is called the * [The Hardest Part About Microservices: Your Data](http://blog.christianposta.com/microservices/the-hardest-part-about-microservices-data/) presents a data-centric view on how to structure and transport data in a microservices architecture. + +* [Deleting data distributed throughout your microservices architecture](https://blog.twitter.com/engineering/en_us/topics/infrastructure/2020/deleting-data-distributed-throughout-your-microservices-architecture.html) + examines how Twitter handles issues with discoverability, access and erasure + in their microservices-heavy production environment. diff --git a/content/pages/04-web-development/46-webhooks.markdown b/content/pages/04-web-development/46-webhooks.markdown index a50c9f558..6583c526d 100644 --- a/content/pages/04-web-development/46-webhooks.markdown +++ b/content/pages/04-web-development/46-webhooks.markdown @@ -23,9 +23,21 @@ otherwise independent web applications. ### Webhook resources -* [Should you build a webhooks API?](https://brandur.org/webhooks) +* [Building Webhooks Into Your Application: Guidelines and Best Practices](https://workos.com/blog/building-webhooks-into-your-application-guidelines-and-best-practices) + is an extensive high-level guide that defines what webhooks are, why you + will want to build them if you need to proactively notify other applications + of events, and what security considerations you need to have when + creating them. + +* [What's a webhook?](https://sendgrid.com/blog/whats-webhook/) is a high-level + explanation of this concept that also contains some basic security + considerations when using them. -* [Webhooks do’s and dont’s: what we learned after integrating +100 APIs](https://restful.io/webhooks-dos-and-dont-s-what-we-learned-after-integrating-100-apis-d567405a3671) +* [Webhooks for Beginners - Full Course](https://www.youtube.com/watch?v=41NOoEz3Tzc) + is an entire free video course that shows both how to use and implement + webhooks into applications. + +* [Should you build a webhooks API?](https://brandur.org/webhooks) * [Why Are Webhooks Better Than Serverless Extensibility?](https://developer.okta.com/blog/2017/10/11/why-are-webhooks-better-than-serverless-extensibility) diff --git a/content/pages/04-web-development/47-bots.markdown b/content/pages/04-web-development/47-bots.markdown index 82ba58758..46d487720 100644 --- a/content/pages/04-web-development/47-bots.markdown +++ b/content/pages/04-web-development/47-bots.markdown @@ -53,7 +53,7 @@ often also called "chatbots", "assistants" or "agents." * [Making a Reddit + Facebook Messenger Bot](https://pythontips.com/2017/04/13/making-a-reddit-facebook-messenger-bot/) builds a bot for two platforms and shows how to deploy it to Heroku. -* [Build a Slack Bot that Mimics Your Colleagues with Python](http://hirelofty.com/blog/how-build-slack-bot-mimics-your-colleague/) +* [Build a Slack Bot that Mimics Your Colleagues with Python](https://hirelofty.com/blog/software-development/how-build-slack-bot-mimics-your-colleague/) is a humorous post that uses the [markovify](https://github.com/jsvine/markovify) Markov Chains library to generate responses that are similar to ones other Slack users have said. diff --git a/content/pages/04-web-development/48-api-creation.markdown b/content/pages/04-web-development/48-api-creation.markdown index 9125e39fa..aa49c5aa1 100644 --- a/content/pages/04-web-development/48-api-creation.markdown +++ b/content/pages/04-web-development/48-api-creation.markdown @@ -26,9 +26,6 @@ applications through machine-to-machine communication. [own GitHub organization](https://github.com/flask-restful/flask-restful) so engineers from outside the company could be core contributors. -* [Flask API](http://www.flaskapi.org/) is another common library for - exposing APIs from Flask web applications. - * [Sandman](http://www.github.com/jeffknupp/sandman) is a widely used tool to automatically generate a RESTful API service from a legacy database without writing a line of code (though it's easily extensible through code). @@ -133,12 +130,8 @@ equivalent of browser testing in the web application world. compatibility and a whole slew of other great advice for developers and API designers. -* [Self-descriptive, isn't. Don't assume anything.](http://www.bizcoder.com/self-descriptive-isn-t-don-t-assume-anything) - is an appeal that metadata makes a difference in whether APIs are descriptive - or not. - * [Designing the Artsy API](http://artsy.github.io/blog/2014/09/12/designing-the-public-artsy-api/) - has their recommendations list for building an API based on their recent + has their recommendations list for building an API based on their experiences. * Hacker News had a discussion on @@ -149,9 +142,10 @@ equivalent of browser testing in the web application world. is free and contains a wealth of practical advice for what design decisions to make for your web API. -* [1-to-1 Relationships and Subresources in REST APIs](http://developers.lyst.com/2015/02/20/1-to-1-relationships-and-subresources-in-rest-apis/) - tells the story of design decisions that were made during an API's creation - and why those choices were made. +* [Documenting APIs: A guide for technical writers and engineers](https://idratherbewriting.com/learnapidoc/) + is a guide that covers good practices for thinking like a developer who + will use your API, as well as what the documentation for endpoints + and other important pieces should look like. * [How many status codes does your API need?](https://blogs.dropbox.com/developers/2015/04/how-many-http-status-codes-should-your-api-use/) gives an answer from a Dropbox API developer as to their decision making @@ -201,16 +195,19 @@ equivalent of browser testing in the web application world. second as well as the number of concurrent open connections can help keep your API alive during times of heavy traffic. +* [Writing HTTP files to test HTTP APIs](https://renato.athaydes.com/posts/writing-http-files-for-testing.html) + shows how to perform automated testing of APIs using HTTP file formats + provided by + [VS Code REST Client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) + and the + [JetBrains HTTP Client Editor](https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html). + * Serialization is common for transforming objects into web API JSON results. One company found the serialization performance of Django REST framework was lacking so they created [Serpy](https://github.com/clarkduvall/serpy) and [wrote a blog post with the results of its performance](https://engineering.betterworks.com/2015/09/04/ditching-django-rest-framework-serializers-for-serpy/). -* [Designing a Web API](http://restlet.com/company/blog/2015/03/16/api-design-designing-a-web-api/) - gives a detailed walkthrough of concepts and design decisions you need - to make when building an API. - * Microsoft's [REST API Guidelines](https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md) are a detailed set of considerations for when you are building your own @@ -223,6 +220,11 @@ equivalent of browser testing in the web application world. * [Building better API docs](https://engineering.gosquared.com/building-better-api-docs) shows how Square used Swagger with React to create more helpful docs. +* [Best Practices For Creating Useful API Documentation](https://nordicapis.com/best-practices-for-creating-useful-api-documentation/) + covers standard but important topics such as knowing your audience, + ensuring your documentation covers the error codes, and providing + a changelog as well as terms of service. + ## Django REST Framework resources * This multi-part series on diff --git a/content/pages/04-web-development/50-django-rest-framework-drf.markdown b/content/pages/04-web-development/50-django-rest-framework-drf.markdown index 5824966bc..8e37986e0 100644 --- a/content/pages/04-web-development/50-django-rest-framework-drf.markdown +++ b/content/pages/04-web-development/50-django-rest-framework-drf.markdown @@ -60,10 +60,6 @@ typically abbreviated "DRF", is a Python library for building web * [Optimizing slow Django REST Framework performance](https://ses4j.github.io/2015/11/23/optimizing-slow-django-rest-framework-performance/) -* [TLT: Serializing Authenticated User Data With Django REST Framework](http://gregblogs.com/tlt-serializing-authenticated-user-data-with-django-rest-framework/) - -* [Building an API with Django REST Framework and Class-Based Views](https://codeburst.io/building-an-api-with-django-rest-framework-and-class-based-views-75b369b30396) - * [Simple Nested API Using Django REST Framework](https://blog.apptension.com/2017/09/13/rest-api-using-django-rest-framework/) * [Building APIs with Django and Django Rest Framework](https://books.agiliq.com/projects/django-api-polls-tutorial/en/latest/) diff --git a/content/pages/04-web-development/51-api-integration.markdown b/content/pages/04-web-development/51-api-integration.markdown index ecf006c20..ee646bfa9 100644 --- a/content/pages/04-web-development/51-api-integration.markdown +++ b/content/pages/04-web-development/51-api-integration.markdown @@ -26,7 +26,7 @@ across many implementation areas. add them to applications with a bunch of useful code examples. * Some developers prefer to use - [Requests](http://docs.python-requests.org/en/latest/) instead of an API's + [Requests](https://requests.readthedocs.io/en/master/) instead of an API's helper library. In that case check out this [tutorial on using requests to access web APIs](http://engineering.hackerearth.com/2014/08/21/python-requests-module/). @@ -43,6 +43,12 @@ across many implementation areas. [18F's API-All-the-X list](http://18f.github.io/API-All-the-X/). The list is updated whenever a new API comes online. +* [The Only Type of API Services I'll Use](https://www.rdegges.com/2020/the-only-type-of-api-services-ill-use/) + explains how alignment between usage and pricing is crucial to a solid, + long-lasting API experience. Other models such as tiered usage and + enterprise upsells typically lead to terrible developer experiences and + should generally be avoided when building applications with APIs. + * John Sheehan's "[Zen and the Art of API Maintenance](https://speakerdeck.com/johnsheehan/zen-and-the-art-of-api-maintenance)" slides are relevant for API integration. @@ -57,9 +63,6 @@ across many implementation areas. is a nice tutorial for easily re-executing failed HTTP requests with the Requests library. -* My DjangoCon 2013 talk dove into - "[Making Django Play Nice With Third Party Services](http://www.youtube.com/watch?v=iGP8DQIqxXs)." - * If you're looking for a fun project that uses two web APIs within a Django application, try out this tutorial to [Build your own Pokédex with Django, MMS and PokéAPI](https://www.twilio.com/blog/2014/11/build-your-own-pokedex-with-django-mms-and-pokeapi.html). @@ -92,7 +95,7 @@ across many implementation areas. requests and responses. 1. Evaluate whether to use a helper library or work with - [Requests](http://docs.python-requests.org/en/latest/). Helper libraries + [Requests](https://requests.readthedocs.io/en/master/). Helper libraries are usually easier to get started with while Requests gives you more control over the HTTP calls. diff --git a/content/pages/04-web-development/52-twilio.markdown b/content/pages/04-web-development/52-twilio.markdown index 8322563b1..e038e3907 100644 --- a/content/pages/04-web-development/52-twilio.markdown +++ b/content/pages/04-web-development/52-twilio.markdown @@ -77,10 +77,6 @@ for fellow developers. [Twilio SMS API via some Python code](https://www.twilio.com/docs/quickstart/python/sms) to send a text message with the results. -* IBM's Bluemix blog contains a nice tutorial on building an - [IoT Python app with a Raspberry Pi and Bluemix](https://developer.ibm.com/bluemix/2015/04/02/tutorial-using-a-raspberry-pi-python-iot-twilio-bluemix/) - that uses Twilio to interact with the Raspberry Pi. - * The [Python tag on the Twilio blog](https://www.twilio.com/blog/tag/python) provides walkthroughs for [Django](https://www.twilio.com/blog/2015/12/city-chat-with-python-django-and-twilio-ip-messaging.html), @@ -88,6 +84,14 @@ for fellow developers. and [Bottle](https://www.twilio.com/blog/2016/08/getting-started-python-bottle-twilio-sms-mms.html) apps to learn from while building your own projects. +* [Serverless Phone Number Validation with AWS Lambda, Python and Twilio](https://www.twilio.com/blog/serverless-phone-number-validation-aws-lambda-python-twilio) + walks through using the Python runtime on [AWS Lambda](/aws-lambda.html) + and Twilio's APIs for validating phone number information. + +* [Receive Flask Error Alerts by Email with Twilio SendGrid](https://www.twilio.com/blog/receive-flask-error-alerts-email-twilio-sendgrid) + shows how to use Twilio to add email error reports to [Flask](/flask.html) + web applications. + * [Google Cloud recommends developers use Twilio](https://cloud.google.com/appengine/docs/standard/python/sms/twilio) for communications in their apps and provides a short walkthrough for Python developers. @@ -95,7 +99,13 @@ for fellow developers. * [SMS Tracking Notifications](https://www.easypost.com/sms-tracking-tutorial) is a fun tutorial that combines two APIs together - Twilio and [Easypost](https://www.easypost.com) to track packages sent through the - Easypost service. + Easypost service. There is also another tutorial on + [shipment notifications specifically for Flask](https://www.twilio.com/blog/build-shipment-notification-service-python-flask-twilio-easypost). + +* [Build a Video Chat Application with Python, JavaScript and Twilio Programmable Video](https://www.twilio.com/blog/build-video-chat-application-python-javascript-twilio-programmable-video) + shows how to use [Flask](/flask.html) and the + [Twilio Programmable Video API](https://www.twilio.com/docs/video) to + build cross-platform video into new and existing applications. * This video titled "[We're No Strangers to VoIP: Building the National Rick Astley Hotline)](https://www.youtube.com/watch?v=LgKshQoGh64)" diff --git a/content/pages/04-web-development/53-stripe.markdown b/content/pages/04-web-development/53-stripe.markdown index 03b01c986..82aba71f0 100644 --- a/content/pages/04-web-development/53-stripe.markdown +++ b/content/pages/04-web-development/53-stripe.markdown @@ -18,8 +18,10 @@ for processing payments. ### Stripe tutorials -* [Switching from Braintree to Stripe](https://www.deekit.com/braintree-to-stripe/) - covers one development team's experience with moving payment providers. +* [How to Create a Subscription SaaS Application with Django and Stripe](https://www.saaspegasus.com/guides/django-stripe-integrate/) + shows how to build a [Django](/django.html) application with models for + the subscription data in the [Django ORM](/django-orm.html) and create + a pricing page. * [Dirt Cheap Recurring Payments with Stripe and AWS Lambda](http://normal-extensions.com/2017/05/05/simple-recurring/) explains how to use the Stripe API with [AWS Lambda](/aws-lambda.html) @@ -38,6 +40,11 @@ for processing payments. ### Resources about Stripe +* [Stripe’s payments APIs: the first ten years](https://stripe.com/blog/payment-api-design) + has a ton of great context about how Stripe's payments API has evolved, + its architecture, how they expanded it over time, and generally a bunch + of solid storytelling behind how it has been built. + * [How Stripe Designs Beautiful Websites](https://leerob.io/blog/how-stripe-designs-beautiful-websites) explains the process for how Stripe creates their gorgeous design that makes people want to use the service and explore what else they can diff --git a/content/pages/04-web-development/54-slack.markdown b/content/pages/04-web-development/54-slack.markdown index 15931fae1..e9e251609 100644 --- a/content/pages/04-web-development/54-slack.markdown +++ b/content/pages/04-web-development/54-slack.markdown @@ -70,6 +70,10 @@ for programmatically interacting with its messaging service. Slack-provided library for working with the Slack API and [WebSockets](/websockets.html) connection. +* [slackify](https://github.com/Ambro17/slackify) is a lightweight + framework for building bots and the quickstart walks you through + how to create a simple example bot. + * [slack-starterbot](https://github.com/mattmakai/slack-starterbot) * [slack-api-python-examples](https://github.com/mattmakai/slack-api-python-examples) diff --git a/content/pages/04-web-development/56-web-app-security.markdown b/content/pages/04-web-development/56-web-app-security.markdown index 7cf2fd0c0..992091dbf 100644 --- a/content/pages/04-web-development/56-web-app-security.markdown +++ b/content/pages/04-web-development/56-web-app-security.markdown @@ -14,8 +14,6 @@ request forgery and usage of public-private keypairs. ### Security tools -* [Bro](http://www.bro.org/) is a network security and traffic monitor. - * [lynis](https://cisofy.com/lynis/) ([source code](https://github.com/CISOfy/lynis)) is a security audit tool that can run as a shell script on a Linux system to find out @@ -107,7 +105,12 @@ resources can also give you a good overview of how HTTPS works. [cheat sheets for security](https://www.owasp.org/index.php/Cheat_Sheets) topics. -* [The SaaS CTO Security Checklist](https://cto-security-checklist.sqreen.io/) +* [Stanford's CS253 class](https://web.stanford.edu/class/cs253/) is available + for free online, including lecture slides, videos and course materials to + learn about web browser internals, session attacks, fingerprinting, HTTPS + and many other fundamental topics. + +* [The SaaS CTO Security Checklist Redux](https://www.goldfiglabs.com/guide/saas-cto-security-checklist/) is an awesome list of steps for securing your infrastructure and employees as well as what stage and size company it is recommended that you put those procedures in place. @@ -127,11 +130,6 @@ resources can also give you a good overview of how HTTPS works. * The [/r/netsec](http://www.reddit.com/r/netsec/) subreddit is one place to go to learn more about network and application security. -* [Hacking Tools Repository](http://gexos.github.io/Hacking-Tools-Repository/) - is a great list of password cracking, scanning, sniffing and other security - penetration testing tools. - - * The EFF has a well written overview on [what makes a good security audit](https://www.eff.org/deeplinks/2014/11/what-makes-good-security-audit). It's broad but contains some of their behind the scenes thinking on important considerations with security audits. @@ -155,10 +153,6 @@ resources can also give you a good overview of how HTTPS works. important technique to use to keep your database passwords and other secrets more secure if the hashed strings are leaked. -* [An in-depth analysis of SSH attacks on Amazon EC2](http://getprismatic.com/story/1409447605839) - shows how important it is to secure your web servers, especially when they are - hosted in IP address ranges that are commonly scanned by malicious actors. - * [Cloud Security Auditing: Challenges and Emerging Approaches](http://www.infoq.com/articles/cloud-security-auditing-challenges-and-emerging-approaches) is a high-level overview of some of security auditing problems that come with cloud deployments. diff --git a/content/pages/04-web-development/57-sql-injection.markdown b/content/pages/04-web-development/57-sql-injection.markdown index 8536fdb73..084f699e8 100644 --- a/content/pages/04-web-development/57-sql-injection.markdown +++ b/content/pages/04-web-development/57-sql-injection.markdown @@ -24,3 +24,8 @@ can affect both [relational databases](/databases.html) and * [Securing your site like it's 1999](https://24ways.org/2018/securing-your-site-like-its-1999/) covers a bunch of common web application vulnerabilities including SQL injection. + +* [Automating Blind Sql Injection](https://bad-jubies.github.io/Blind-SQLi-1/) + shows how to use Python to execute SQL injection on the example + [Damn Vulnerable Web Application](https://github.com/digininja/DVWA) + project. diff --git a/content/pages/05-deployment/00-deployment.markdown b/content/pages/05-deployment/00-deployment.markdown index b5ecc4025..48ad4e8c1 100644 --- a/content/pages/05-deployment/00-deployment.markdown +++ b/content/pages/05-deployment/00-deployment.markdown @@ -51,7 +51,7 @@ guide as they are considered advanced deployment techniques. * [teletraan](https://github.com/pinterest/teletraan) is the deploy system used by the development teams at Pinterest, a huge Python shop! -* [pants](https://www.pantsbuild.org/index.html) is a build system originally +* [pants](https://www.pantsbuild.org/) is a build system originally created at Twitter and now split out as its own sustainable open source project. @@ -112,14 +112,6 @@ guide as they are considered advanced deployment techniques. defines delivery versus deployment and walks through a continuous deployment workflow. -* [Automation for the People](https://gist.github.com/classam/9e07a36aa63624ca2dda75a1367a53c6) - provides an awesome overview of one developer's story for how he gradually - learned about deployment automation. The story follows my own journey in - many ways, from starting with brittle [Bash](/bourne-again-shell-bash.html) - scripts, moving to Fabric and then on to [Ansible](/ansible.html) for - higher-level [configuration management](/configuration-management.html) - and continuous deployment pipelines. - * [5 ways to deploy your Python application in 2017](https://www.youtube.com/watch?v=vGphzPLemZE) is a talk from [PyCon US 2017](https://www.youtube.com/channel/UCrJhliKNQ8g0qoE_zvL8eVg/videos) @@ -140,14 +132,6 @@ guide as they are considered advanced deployment techniques. is an awesome in-depth read covering topics ranging from git branching to database migrations. -* In [this free video by Neal Ford](http://player.oreilly.com/videos/9781491908181?toc_id=210188), - he talks about engineering practices for continuous delivery. He explains - the difference between - [continuous integration](/continuous-integration.html), - continuous deployment and continuous delivery. Highly recommended for an - overview of deployment concepts and as an introduction to the other videos - on those subjects in that series. - * [TestDriven.io](https://testdriven.io/) shows how to deploy a [microservices](/microservices.html) architecture that uses [Docker](/docker.html), [Flask](/flask.html), and React with diff --git a/content/pages/05-deployment/02-servers.markdown b/content/pages/05-deployment/02-servers.markdown index 90bb07951..f66f68977 100644 --- a/content/pages/05-deployment/02-servers.markdown +++ b/content/pages/05-deployment/02-servers.markdown @@ -128,8 +128,8 @@ provides a unified API for many cloud service providers. * [Amazon Web Services has official documentation](http://aws.amazon.com/python/) for running Python web applications. -* [boto](https://github.com/boto/boto) is an extensive and well-tested -Python library for working with Amazon Web Services. +* [boto3](https://github.com/boto/boto3) is an extensive and well-tested + Python library for working with Amazon Web Services. * [Poseidon](https://github.com/changhiskhan/poseidon) is a Python commandline interface for managing Digital Ocean droplets (servers). diff --git a/content/pages/05-deployment/03-static-content.markdown b/content/pages/05-deployment/03-static-content.markdown index 8c6e88262..f5a118f54 100644 --- a/content/pages/05-deployment/03-static-content.markdown +++ b/content/pages/05-deployment/03-static-content.markdown @@ -21,9 +21,9 @@ Django framework calls these two categories *assets* and *media*. ## Content delivery networks A content delivery network (CDN) is a third party that stores and serves static files. [Amazon CloudFront](http://aws.amazon.com/cloudfront/), -[Akamai](http://www.akamai.com/), and -[Rackspace Cloud Files](http://www.rackspace.com/cloud/public/files/) -are examples of CDNs. The purpose of a CDN is to remove the load of static +[CloudFlare](https://www.cloudflare.com/) and [Fastly](https://www.fastly.com/), +are examples of CDN services. The purpose of +a CDN is to remove the load of static file requests from web servers that are handling dynamic web content. For example, if you have an nginx server that handles both static files and acts as a front for a Green Unicorn WSGI server on a 512 megabyte diff --git a/content/pages/05-deployment/04-cdns.markdown b/content/pages/05-deployment/04-cdns.markdown index 027f064d6..bd4e516fe 100644 --- a/content/pages/05-deployment/04-cdns.markdown +++ b/content/pages/05-deployment/04-cdns.markdown @@ -12,9 +12,9 @@ servers to improve web app loading speed. ### CDN resources -* [Mastering HTTP Caching](https://blog.fortrabbit.com/mastering-http-caching) - is a fantastic post that goes into great technical detail on how CDNs and - caching work. +* [The 5 hour CDN](https://fly.io/blog/the-5-hour-content-delivery-network/) + explains the basics of what CDNs are and how they are a combination of + many standard web server components, but used globally and at scale. * [MaxCDN vs CloudFlare vs Amazon CloudFront vs Akamai Edge vs Fastly](https://www.codeinwp.com/blog/maxcdn-vs-cloudflare-vs-cloudfront-vs-akamai-edge-vs-fastly/) compares and contrasts the most popular CDN services based on features, @@ -29,10 +29,6 @@ servers to improve web app loading speed. [django-storages](https://django-storages.readthedocs.io/en/latest/) library to deploy static assets for a [Django](/django.html) application to a CDN. -* [Building your own CDN for Fun and Profit](https://pasztor.at/blog/building-your-own-cdn) - is a great high-level overview of how CDNs work and shows you how to - create your own, albeit simplified CDN. - * [Do not let your CDN betray you: Use Subresource Integrity](https://hacks.mozilla.org/2015/09/subresource-integrity-in-firefox-43/) describes the security implications for CDNs with unexpectedly modified content and how Subresource Integrity in modern web browsers can mitigate diff --git a/content/pages/05-deployment/09-paas.markdown b/content/pages/05-deployment/09-paas.markdown index 9416e971f..c89a37439 100644 --- a/content/pages/05-deployment/09-paas.markdown +++ b/content/pages/05-deployment/09-paas.markdown @@ -69,11 +69,6 @@ of controlling and modifying the project for your own applications, but prevents you from offloading the responsibility of keeping servers running to someone else. -* [Kel](http://www.kelproject.com/) uses Kubernetes as a foundation - for a custom self-hosted PaaS. Note that it was created by Eldarion, - which had one of the first Python-specific PaaS offerings on the - market around the time that Heroku was launched. - * [Dokku](http://dokku.viewdocs.io/dokku/) builds on Docker and has hooks for plugins to extend the small core of the project and customize deployments for your applications. @@ -82,7 +77,6 @@ running to someone else. designed to run on top of AWS services. - ## Platform-as-a-service resources * [The differences between IaaS, PaaS and SaaS](https://www.engineyard.com/blog/the-differences-between-iaas-paas-and-saas-and-when-to-use-each) explains the abstract layer differences among "X-as-a-service" offering @@ -156,11 +150,6 @@ running to someone else. on Google Cloud and posits what they may be paying to run their service. -* [PaaS (false) economics](https://blog.drie.co/paas-false-economics-13f72d87b485) - gives some quick back-of-the-envelope calculations on why running your - applications on a PaaS is obviously going to appear more expensive if you - do not take the cost of your own software engineers into the equation. - * Two blog posts on using AWS Autoscaling in [Automatic replacement of Autoscaling nodes with equivalent spot instances](https://mcristi.wordpress.com/2016/04/21/my-approach-at-making-aws-ec2-affordable-automatic-replacement-of-autoscaling-nodes-with-equivalent-spot-instances/) and [Autoscaling nodes: seeing it in action](https://mcristi.wordpress.com/2016/04/27/automatic-replacement-of-autoscaling-nodes-with-equivalent-spot-instances-seeing-it-in-action/) diff --git a/content/pages/05-deployment/10-heroku.markdown b/content/pages/05-deployment/10-heroku.markdown index 63aad7441..06c1d7bcb 100644 --- a/content/pages/05-deployment/10-heroku.markdown +++ b/content/pages/05-deployment/10-heroku.markdown @@ -21,7 +21,14 @@ easily [deploy](/deployment.html) Python applications. [MySQL](/mysql.html) to [PostgreSQL](/postgresql.html) if necessary as well as how to properly handle your settings files. -* Heroku's +* [How to deploy Django project to Heroku using Docker](https://www.accordbox.com/blog/deploy-django-project-heroku-using-docker/) + explains that although [Buildpacks](https://devcenter.heroku.com/articles/buildpacks) + are the most common way to deploy to Heroku, packaing your app in a + [Docker](/docker.html) container is also a viable approach. It walks through + the steps needed to deploy a [Django](/django.html) app in the remainder + of the article. + +* Heroku's [official Python documentation](https://devcenter.heroku.com/articles/getting-started-with-python) is fantastic and walks through deploying WSGI applications in short order. diff --git a/content/pages/05-deployment/19-nginx.markdown b/content/pages/05-deployment/19-nginx.markdown index d7f393ab6..3f17e6524 100644 --- a/content/pages/05-deployment/19-nginx.markdown +++ b/content/pages/05-deployment/19-nginx.markdown @@ -63,21 +63,18 @@ to make sure you are avoiding the most common security errors that plague HTTP(S) configurations. * [HTTPS with Let's Encrypt and nginx](https://botleg.com/stories/https-with-lets-encrypt-and-nginx/) - walks throough installing a free SSL certificate from Let's Encrypt + walks through installing a free SSL certificate from Let's Encrypt to secure HTTP connects to your nginx server via HTTPS. -* The tools [Nginx Config](https://nginxconfig.io/) and - [Cipherlist](https://cipherli.st/) generate strong encryption configurations - and ciphers for Nginx. +* The [Nginx Config](https://nginxconfig.io/) tool can generate strong + encryption configurations and ciphers for Nginx. * [Gixy](https://github.com/yandex/gixy) is a static analyzer for your Nginx configuration and can tell you issues with how you are setup. * [Strong SSL Security on Nginx](https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html) shows how to mitigate high profile SSL attacks like - [Logjam](https://weakdh.org/), - [Heartbleed](http://heartbleed.com/) - and [FREAK](https://freakattack.com/). + [Logjam](https://weakdh.org/) and [Heartbleed](http://heartbleed.com/). ## Specific Nginx resources @@ -104,7 +101,7 @@ several years. * [Test-driving web server configuration](https://gdstechnology.blog.gov.uk/2015/03/25/test-driving-web-server-configuration/) tells a good story for how to iteratively apply configuration changes, such - as routing traffic to [Piwik](http://piwik.org/) for + as routing traffic to [Matoma](https://matomo.org/) for [web analytics](/web-analytics.html), reverse proxying to backend application servers and terminately TLS connections appropriately. It is impressive to read a well-written softare development article like @@ -119,10 +116,6 @@ several years. as well as the Pagespeed module that Google released for both Nginx and the [Apache HTTP Server](/apache-http-server.html). -* [Nginx for Developers: An Introduction](http://carrot.is/coding/nginx_introduction) - provides the first steps to getting an initial Nginx configuration up and - running. - * [A faster Web server: ripping out Apache for Nginx](http://arstechnica.com/business/2011/11/a-faster-web-server-ripping-out-apache-for-nginx/) explains how Nginx can be used instead of Apache in some cases for better performance. @@ -155,7 +148,3 @@ several years. from your traffic logs when using them for web traffic analytics. -### Nginx release summaries -* [nginx-1.13.0](http://mailman.nginx.org/pipermail/nginx-announce/2017/000195.html) - - diff --git a/content/pages/05-deployment/20-caddy.markdown b/content/pages/05-deployment/20-caddy.markdown index 1b27e6d11..56ca43167 100644 --- a/content/pages/05-deployment/20-caddy.markdown +++ b/content/pages/05-deployment/20-caddy.markdown @@ -15,7 +15,8 @@ and design emphasize HTTPS-everywhere along with the HTTP/2 protocol. ## How can Caddy be used with Python deployments? Caddy can be used both for testing during local development or as part of a production deployment as an HTTP server and a reverse proxy with -the [proxy directive](https://caddyserver.com/docs/proxy). +the +[reverse_proxy directive](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy).
Caddy is an implementation of the web server concept. Learn how these pieces fit together in the deployment chapter or view the table of contents for all topics.
diff --git a/content/pages/05-deployment/22-wsgi-servers.markdown b/content/pages/05-deployment/22-wsgi-servers.markdown index 7a92941c8..036bdbe54 100644 --- a/content/pages/05-deployment/22-wsgi-servers.markdown +++ b/content/pages/05-deployment/22-wsgi-servers.markdown @@ -146,7 +146,7 @@ configuration. For real SSL and non-SSL templates, take a look at the [Underwear web server templates](https://github.com/mattmakai/underwear/tree/master/underwear/roles/web/templates) on GitHub. -## WSGI servers +## WSGI server implementations There is a comprehensive list of WSGI servers on the [WSGI Read the Docs](http://wsgi.readthedocs.org/en/latest/servers.html) page. The following are WSGI servers based on community recommendations. @@ -177,9 +177,9 @@ The following are WSGI servers based on community recommendations. is a good read to understand basic information about various WSGI server implementations. -* A thorough and informative post for LAMP-stack hosting choices is - presented in the - "[complete single server Django stack tutorial](http://www.apreche.net/complete-single-server-django-stack-tutorial/)." +* [What is WSGI and Why Do You Need Gunicorn and Nginx in Django](https://apirobot.me/posts/what-is-wsgi-and-why-do-you-need-gunicorn-and-nginx-in-django) + explains the breakdown between a [web server](/web-servers.html) + and a WSGI server in an application deployment environment. * The Python community made a long effort to [transition from mod\_python](http://blog.dscpl.com.au/2010/05/modpython-project-soon-to-be-officially.html) diff --git a/content/pages/05-deployment/23-gunicorn.markdown b/content/pages/05-deployment/23-gunicorn.markdown index f7098a1b4..1973ab6ff 100644 --- a/content/pages/05-deployment/23-gunicorn.markdown +++ b/content/pages/05-deployment/23-gunicorn.markdown @@ -49,7 +49,7 @@ file with the following contents: It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see - https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ + https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ """ import os @@ -115,11 +115,15 @@ perform the request handling. Each worker is independent of the controller. screenshots along the way with what to expect while you are configuring the deployment server. -* The [Django](https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/gunicorn/) +* The [Django](https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/gunicorn/) and [Flask](http://flask.pocoo.org/docs/latest/deploying/wsgi-standalone/) documentation each contain instructions for deploying the respective frameworks with Gunicorn. +* [Dockerizing Django with Postgres, Gunicorn, and Traefik](https://testdriven.io/blog/django-docker-traefik/) + is a more advanced tutorial with a complete project deployment + that uses Gunicorn within [Docker](/docker.html). + * [Set up Django, Nginx and Gunicorn in a Virtualenv controled by Supervisor](https://gist.github.com/Atem18/4696071) is a GitHub Gist with some great explanations for why we're setting up virtualenv and what to watch out for while you're doing the deployment. diff --git a/content/pages/05-deployment/24-uwsgi.markdown b/content/pages/05-deployment/24-uwsgi.markdown index 5c3a8e3af..7561de3da 100644 --- a/content/pages/05-deployment/24-uwsgi.markdown +++ b/content/pages/05-deployment/24-uwsgi.markdown @@ -7,7 +7,6 @@ sidebartitle: uWSGI meta: uWSGI is a Python WSGI server implementation typically used for running Python web applications. -# uWSGI [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) ([source code](https://github.com/unbit/uwsgi)), pronounced "mu wiz gee", is a [Web Server Gateway Interface (WSGI) server](/wsgi-servers.html) @@ -17,6 +16,11 @@ implementation that is typically used to run Python web applications. ### uWSGI resources +* [Configuring uWSGI for Production Deployment](https://www.techatbloomberg.com/blog/configuring-uwsgi-production-deployment/) + explains how Bloomberg uses uWSGI as a production WSGI server + for some of their Python projects and how to set it up for your + own applications. + * The official [Django](/django.html) framework docs on [how to use Django with uWSGI](https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/uwsgi/) along with the corresponding official @@ -38,7 +42,3 @@ implementation that is typically used to run Python web applications. is awesome because it shows you how to code a quick WSGI application without using a framework then builds up an example with deploying a traditional Django web app. - -* [Deployment Notes for Pylons, Nginx, and uWSGI](http://tonylandis.com/python/deployment-howt-pylons-nginx-and-uwsgi/) - gives the code and instructions for setting up a Pylons application - with uWSGI. diff --git a/content/pages/05-deployment/27-continuous-integration.markdown b/content/pages/05-deployment/27-continuous-integration.markdown index 835f5589a..ea620e337 100644 --- a/content/pages/05-deployment/27-continuous-integration.markdown +++ b/content/pages/05-deployment/27-continuous-integration.markdown @@ -127,11 +127,6 @@ programming language agnostic. Learn more via the following resources or on uses well done drawings to show how continuous integration and delivery works for testing and managing data. -* [The real difference between CI and CD](https://fire.ci/blog/the-difference-between-ci-and-cd/) - explains what advantages CI provides, what constraints it operates under - (such as total build time) to work well, and how that is different from - the related but distinct concept of continuous delivery. - * [6 top continuous integration tools](https://opensource.com/business/15/7/six-continuous-integration-tools) gives a high level overview of six CI tools from a programming language agnostic perspective. diff --git a/content/pages/05-deployment/28-jenkins.markdown b/content/pages/05-deployment/28-jenkins.markdown index 46a711870..63c64d57c 100644 --- a/content/pages/05-deployment/28-jenkins.markdown +++ b/content/pages/05-deployment/28-jenkins.markdown @@ -35,20 +35,11 @@ used to automate building, [testing](/testing.html) and is another solid tutorial that also shows how to send email notifications as part of the build process. -* If you're running into difficulty adding an SSH key to your Jenkins system - account so you can connect to another server or Git repository - [this blog post on connecting Jenkins with Git](http://dcycleproject.org/blog/51/connecting-jenkins-and-git) - to get the steps to solve that problem. - * [Running Jenkins in Docker Containers](http://www.catosplace.net/blog/2015/02/11/running-jenkins-in-docker-containers/) is a short tutorial showing how to use the official [Jenkins container](https://registry.hub.docker.com/_/jenkins/) on the Docker hub. -* [Securing Jenkins](https://wiki.jenkins.io/display/JENKINS/Securing+Jenkins) - is the landing page for Jenkins security. If you're deploying your own - instance, you'll need to lock it down against unauthorized users. - * [Updating the GOV.UK Continuous Integration environment](https://gdstechnology.blog.gov.uk/2017/02/10/updating-the-gov-uk-continuous-integration-environment/) describes the configuration improvements one infrastructure team made to Jenkins, where they enabled @@ -77,7 +68,3 @@ used to automate building, [testing](/testing.html) and * [Automated API testing with Jenkins](https://assertible.com/blog/automated-api-testing-with-jenkins) walks through how to use Jenkins to tests your [API](/application-programming-interfaces.html) upon each deployment. - -* [Continuous Delivery with Jenkins and Rollbar](https://rollbar.com/blog/continuous-delivery-with-jenkins/) - is a tutorial on using Jenkins for continuous integration paired with - [Rollbar](/rollbar.html) for tracking deployments and errors. diff --git a/content/pages/05-deployment/29-gocd.markdown b/content/pages/05-deployment/29-gocd.markdown index 3a4f48e21..3bffa4e41 100644 --- a/content/pages/05-deployment/29-gocd.markdown +++ b/content/pages/05-deployment/29-gocd.markdown @@ -8,7 +8,7 @@ meta: GoCD is a continuous integration (CI) server often used to automatically b [GoCD](https://www.gocd.org/) is a -[continuous integration (CI)](/continuous-integation.html) +[continuous integration (CI)](/continuous-integration.html) server often used to automatically build, [test](/testing.html) and [deploy](/deployment.html) Python applications. diff --git a/content/pages/05-deployment/32-configuration-management.markdown b/content/pages/05-deployment/32-configuration-management.markdown index 252df484e..23f4b07ba 100644 --- a/content/pages/05-deployment/32-configuration-management.markdown +++ b/content/pages/05-deployment/32-configuration-management.markdown @@ -32,10 +32,6 @@ operations, such as querying the database from the Django manage.py shell. is an openly biased but detailed post on why to choose SaltStack over Ansible in certain situations. -* [Ansible vs. Shell Scripts](https://valdhaus.co/writings/ansible-vs-shell-scripts/) - provides some perspective on why using a configuration management tool is a - better choice than venerable but brittle shell scripts. - * [Ansible vs. Chef](http://tjheeta.github.io/2015/04/15/ansible-vs-chef/) is a comparsion of Ansible with the Chef configuration management tool. @@ -59,17 +55,6 @@ management and application deployment tool built in Python. is a fantastically detailed introduction on using Ansible to set up servers. -* [Ansible Text Message Notifications with Twilio SMS](https://www.twilio.com/blog/2014/05/ansible-text-messages-notifications-with-twilio-sms.html) - is my blog post with a detailed example for using the Twilio module in - core Ansible 1.6+. - -* [Python for Configuration Management with Ansible slides](http://www.insom.me.uk/post/pycon-talk.html) -from PyCon UK 2013 - -* [First Steps with Ansible](http://labs.qandidate.com/blog/2013/11/15/first-steps-with-ansible/) - -* [Red Badger on Ansible](http://red-badger.com/blog/2013/06/29/ansible/) - * [Getting Started with Ansible](http://lowendbox.com/blog/getting-started-with-ansible/) * [An introduction to Ansible](https://davidwinter.me/introduction-to-ansible/) @@ -89,8 +74,6 @@ from PyCon UK 2013 * [Idempotence, convergence, and other silly fancy words we often use](https://groups.google.com/forum/#!msg/Ansible-project/WpRblldA2PQ/lYDpFjBXDlsJ) -* [Testing with Jenkins, Docker and Ansible](http://blog.mist.io/post/82383668190/move-fast-and-dont-break-things-testing-with) - ## Application dependencies learning checklist 1. Learn about configuration management in the context of deployment diff --git a/content/pages/05-deployment/33-ansible.markdown b/content/pages/05-deployment/33-ansible.markdown index a64409f26..bbdff142a 100644 --- a/content/pages/05-deployment/33-ansible.markdown +++ b/content/pages/05-deployment/33-ansible.markdown @@ -38,9 +38,6 @@ be able to structure your playbooks: configures macOS with various applications and developer tools such as [Docker](/docker.html), Homebrew and [Sublime Text](/sublime-text.html). -* [ansible-nginx-haproxy-elasticsearch](https://github.com/gp187/ansible-nginx-haproxy-elasticsearch) - sets up a server with [Nginx](/nginx.html), HAProxy and ElasticSearch. - ### Specific Ansible topics * [An Ansible2 Tutorial](https://serversforhackers.com/c/an-ansible2-tutorial) @@ -63,10 +60,6 @@ be able to structure your playbooks: * [DevOps from Scratch, Part 1: Vagrant & Ansible](https://www.kevinlondon.com/2016/09/19/devops-from-scratch-pt-1.html) -* [Ansible: Post-Install Setup](https://valdhaus.co/writings/ansible-post-install/) - -* [How To Use Vault to Protect Sensitive Ansible Data on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-use-vault-to-protect-sensitive-ansible-data-on-ubuntu-16-04) - * [How to use Ansible Variables and Vaults](https://www.expressvpn.com/blog/ansible-variables-vaults/) * [CI for Ansible playbooks which require Ansible Vault protected variables](https://www.jeffgeerling.com/blog/2017/ci-ansible-playbooks-which-require-ansible-vault-protected-variables) diff --git a/content/pages/05-deployment/34-salt.markdown b/content/pages/05-deployment/34-salt.markdown index 5a11baaea..8f1e90a6c 100644 --- a/content/pages/05-deployment/34-salt.markdown +++ b/content/pages/05-deployment/34-salt.markdown @@ -17,6 +17,10 @@ meta: Salt is configuration management tool used for application deployment and ### Salt resources +* [What's new in Salt 3000 Neon](https://salt.tips/whats-new-in-salt-neon/) + covers the latest release and the significant number of new features + and fixes contained within it. + * [Introduction to Salt](https://docs.saltstack.com/en/latest/topics/) gives a 30 second summary of what the tool can do for you then provides a collection of links to other resources that plug you into the Salt diff --git a/content/pages/05-deployment/35-containers.markdown b/content/pages/05-deployment/35-containers.markdown index 76fb8b62c..5ec0a850e 100644 --- a/content/pages/05-deployment/35-containers.markdown +++ b/content/pages/05-deployment/35-containers.markdown @@ -55,6 +55,11 @@ useful. on building jails and other process isolation abstractions into operating systems. +* [Linux containers in a few lines of code](https://zserge.com/posts/containers/) + shows how containers work by providing some code to run a busybox + Docker image but without using docker. It then explains what's + happening under the hood as you run basic commands such as `/bin/sh`. + * [A Practical Introduction to Container Terminology](https://developers.redhat.com/blog/2018/02/22/container-terminology-practical-introduction/) has both some solid introductory information on containers as well as a good description of terms such as container host, registry server, @@ -65,6 +70,12 @@ useful. explains how Linux features such as `cgroups`, `chroot` and namespaces are used by container implementations. +* [Container networking is simple](https://iximiuz.com/en/posts/container-networking-is-simple/) + shows that container networking is nothing more than a simple combination + of the well-known Linux facilities such as network namespaces, virtual + Ethernet devices (veth), virtual network switches (bridge) and + IP routing and network address translation (NAT). + * [Running containers without Docker](https://jvns.ca/blog/2016/10/26/running-container-without-docker/) reviews a migration path for an organization that already has a bunch of infrastructure but sees advantages in using containers. However, the @@ -72,6 +83,11 @@ useful. eventually plan to use Docker, Kubernetes or other container tools and orchestration layer. +* [Datadog's 2020 Container Report](https://www.datadoghq.com/container-report/) + contains some interesting statistics about container usage across + their customer base, such as [Kubernetes](/kubernetes.html) adoption + and container deployments by cloud platform. + * [mocker](https://github.com/tonybaloney/mocker) is a Docker imitation open source project written in all Python which is intended for learning purposes. @@ -110,6 +126,13 @@ Container security is a hot topic because there are so many ways of screwing it up, just like any infrastructure that runs your applications. These resources explain security considerations specific to containers. +* [A Practical Introduction to Container Security](https://cloudberry.engineering/article/practical-introduction-container-security/) + examines security at build time for projects and how to + minimize the risk of supply chain attack. It then goes into + infrastructure and runtime security where you need to understand + different attack vectors and minimize malicious attempts against + your containers during these phases.. + * [Building Container Images Securely on Kubernetes](https://blog.jessfraz.com/post/building-container-images-securely-on-kubernetes/) discusses some of the issues with building containers and why the author created [img](https://github.com/genuinetools/img) as a tool diff --git a/content/pages/05-deployment/36-docker.markdown b/content/pages/05-deployment/36-docker.markdown index ed7052dee..f133b70f0 100644 --- a/content/pages/05-deployment/36-docker.markdown +++ b/content/pages/05-deployment/36-docker.markdown @@ -36,6 +36,10 @@ on Amazon Web Services, Google Compute Engine, Linode, Rackspace or elsewhere. ## Docker resources +* [Beginners guide to Docker](https://www.learncloudnative.com/blog/2020-04-29-beginners-guide-to-docker/) + explains what it is, the difference between containers and virtual machines, + and then provides a hands-on walkthrough command-driven tutorial. + * [What is Docker and When to Use It](https://www.ctl.io/developers/blog/post/what-is-docker-and-when-to-use-it/) clearly delineates what Docker is and what it isn't. This is a good article for when you're first wrapping your head around Docker conceptually. @@ -44,20 +48,10 @@ on Amazon Web Services, Google Compute Engine, Linode, Rackspace or elsewhere. repository and tutorial that shows you how to recreate a simplified version of Docker to better understand what it's doing under the hood. -* [Andrew Baker](https://github.com/atbaker) presented a fantastic tutorial - at [PyOhio](http://andrewtorkbaker.com/pyohio-docker-101-tutorial) on - [beginner and advanced Docker usage](https://github.com/atbaker/docker-tutorial). - Andrew also wrote the article - [what containers can do for you](http://radar.oreilly.com/2015/01/what-containers-can-do-for-you.html). - * [Docker curriculum](http://prakhar.me/docker-curriculum/) is a detailed tutorial created by a developer to show the exact steps for deploying an application that relies on [Elasticsearch](https://www.elastic.co/). -* [How To Install and Use Docker on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04) - provides a walkthrough for Ubuntu 16.04 for installing and beginning to - use Docker for development. - * [It Really is the Future](http://blog.circleci.com/it-really-is-the-future/) discusses Docker and containers in the context of whether it's all just a bunch of hype or if this is a real trend for infrastructure automation. @@ -83,10 +77,6 @@ on Amazon Web Services, Google Compute Engine, Linode, Rackspace or elsewhere. is a short tutorial for creating a Docker container with a specific configuration. -* [10 things to avoid in Docker containers](http://developerblog.redhat.com/2016/02/24/10-things-to-avoid-in-docker-containers/) - provides a lot of "don'ts" that you'll want to consider before bumping - up against the limitations of how containers should be used. - * [Docker Internals](http://docker-saigon.github.io/post/Docker-Internals/) presents Linux containers and how Docker uses them as its base for how the project works. This article is a great way to bridge what you know about Docker with a more diff --git a/content/pages/05-deployment/37-kubernetes.markdown b/content/pages/05-deployment/37-kubernetes.markdown index 20f8578f8..96e69ef62 100644 --- a/content/pages/05-deployment/37-kubernetes.markdown +++ b/content/pages/05-deployment/37-kubernetes.markdown @@ -30,11 +30,11 @@ applications. * [Kompose](http://kompose.io/index) ([source code](https://github.com/kubernetes/kompose)) - translate Docker Compose files into Kubernetes configuration resources. + translates Docker Compose files into Kubernetes configuration resources. -* [skaffold](https://skaffold.dev/). [Using Kubernetes for local development](https://nemethgergely.com/using-kubernetes-for-local-development/index.html) - is a good starting place for more information on getting started with - Skaffold. +* [skaffold](https://skaffold.dev/) + ([source code](https://github.com/GoogleContainerTools/skaffold)) makes + it easier to develop locally with Kubernetes. * [kubethanos](https://github.com/berkay-dincer/kubethanos) is a tool to kill half of your Kubernetes pods at random, to test the resilience of your @@ -80,6 +80,18 @@ applications. is stuffed full of great design advice that is now available as people having been using Kubernetes for a couple of years. +* ["Let’s use Kubernetes!" Now you have 8 problems](https://pythonspeed.com/articles/dont-need-kubernetes/) + is a counter-argument for why you should be cautious about introducing + the significant complexity overhead of Kubernetes (or any related tools) + into your environment unless you really need the advantages that they can + provide. Each developer, team and organization should perform an explicit + cost-benefit analysis to make sure the tool's scability, reliability + and related functionality will outweigh the downsides. + +* [How Zalando manages 140+ Kubernetes clusters](https://srcco.de/posts/how-zalando-manages-140-kubernetes-clusters.html) + covers the architecture, monitoring and workflow of a team that has + to run a decent number of clusters for their development teams. + ### Kubernetes tutorials * [Kubernetes The Hard Way](https://github.com/kelseyhightower/kubernetes-the-hard-way) @@ -96,6 +108,10 @@ applications. is a Git README tutorial with clear steps for how to get started running a Kubernetes cluster. +* [Anatomy of my Kubernetes Cluster](https://ttt.io/anatomy-of-my-kubernetes-cluster) + shows how one developer created their own Raspberry Pi cluster that could + run Kubernetes to learn more about how it works. + * [The cult of Kubernetes](https://christine.website/blog/the-cult-of-kubernetes-2019-09-07) is a hilarious rant that also manages to teach the reader a lot about how to avoid some big issues the author ran into while working with Kubernetes for @@ -122,6 +138,6 @@ applications. uses Helm to make it easier to deploy the example [Django](/django.html) web app with a [PostgreSQL](/postgresql.html) backend. -* [How Zolando manages 140+ Kubernetes clusters](https://srcco.de/posts/how-zalando-manages-140-kubernetes-clusters.html) - covers the architecture, monitoring and workflow of a team that has - to run a decent number of clusters for their development teams. +* [K8s YAML Alternative: Python](https://www.phillipsj.net/posts/k8s-yaml-alternative-python/) + shows how you can use Python scripts instead of YAML to configure + your Kubernetes clusters. diff --git a/content/pages/05-deployment/38-serverless.markdown b/content/pages/05-deployment/38-serverless.markdown index 306caa320..a5236c280 100644 --- a/content/pages/05-deployment/38-serverless.markdown +++ b/content/pages/05-deployment/38-serverless.markdown @@ -45,9 +45,8 @@ These implementations are under significant active development and not all of them have Python support. * [AWS Lambda](/aws-lambda.html) is the current leader among serverless - compute implementations. It has support for both - [Python 2.7](/blog/aws-lambda-python-2-7.html) and - [Python 3.6/3.7](/blog/aws-lambda-python-3-6.html). + compute implementations. It has support for + [Python 3.x](/blog/aws-lambda-python-3-6.html). * Azure Functions has second-class citizen support for Python. It's supposed to be possible but @@ -59,14 +58,11 @@ and not all of them have Python support. [Apache OpenWhisk](https://github.com/openwhisk/openwhisk) open source project. -* [Google Cloud Functions](/google-cloud-functions.html) currently - only supports JavaScript code execution. +* [Google Cloud Functions](/google-cloud-functions.html) has + [native Python 3.x runtimes](https://cloud.google.com/functions/docs/concepts/python-runtime). -* Webtask.io also only supports JavaScript but there is a cool - *prototype* project named [webtask-pytask](https://github.com/tehsis/webtask-pytask) - to run Python code in the browser via webtask. This demo is definitely not - for production code use but awesome to see what the programming community - can put together using existing code and services. +* [Webtask.io](https://webtask.io/) started as a JavaScript service but + now also has a Python runtime as well. ### Serverless frameworks @@ -83,8 +79,7 @@ include: which is a useful but generically-named library that focuses on deployment and operations for serverless applications. -* [Zappa](https://www.zappa.io/) - ([source code](https://github.com/Miserlou/Zappa)) +* [Zappa](https://github.com/Miserlou/Zappa) provides code and tools to make it much easier to build on AWS Lambda and AWS API Gateway than rolling your own on the bare services. @@ -92,8 +87,6 @@ include: ([source code](https://github.com/aws/chalice)) is built by the AWS team specifically for Python applications. -* [Apex](http://apex.run/) ([source code](https://github.com/apex/apex)) - ### General serverless resources Serverless concepts and implementations are still in their early @@ -101,6 +94,12 @@ iterations so there are many ideas and good practices yet to be discovered. These resources are the first attempts at figuring out how to structure and operate serverless applications. +* [What's Serverless?](https://technically.substack.com/p/whats-serverless) + is an accessible "first read" for both developers and non-technical + audiences alike. It breaks down the differences between what most + developers consider serverless and infrastructure-as-a-service (IaaS) + offerings. + * [Serverless software](https://talkpython.fm/episodes/show/118/serverless-software) covers a range of topics under serverless and how deployments have changed as new options such as [PaaS](/platform-as-a-service.html) @@ -183,37 +182,18 @@ have varying degrees of support for Python. AWS Lambda has production-ready support for Python 2 and 3.7, while Azure and Google Cloud have "beta" support with unclear production-worthiness. The following resources are some comparison articles to help you in your decision-making -process for which platform to learn. - -* [Serverless at scale](https://blog.binaris.com/serverless-at-scale/) - compares the "Big 3" AWS, Azure and Google Cloud in serverless performance. - The author provides some nice data around average response times and - outliers. - -* [Serverless hosting comparison](https://headmelted.com/serverless-showdown-4a771ca561d2) - is a broad overview of documentation, community, pricing and other - notes for the major platforms as well as IBM OpenWhisk and - the [Fission.io](https://fission.io/) project. - -* [Microsoft Azure Functions vs. Google Cloud Functions vs. AWS Lambda](https://cloudacademy.com/blog/microsoft-azure-functions-vs-google-cloud-functions-fight-for-serverless-cloud-domination-continues/) - presents an overview of Azure Functions and how they compare to - Google Cloud Functions and AWS Lambda. +process for which platform to learn. +[Microsoft Azure Functions vs. Google Cloud Functions vs. AWS Lambda](https://cloudacademy.com/blog/microsoft-azure-functions-vs-google-cloud-functions-fight-for-serverless-cloud-domination-continues/) +presents an overview of Azure Functions and how they compare to +Google Cloud Functions and AWS Lambda. ### Serverless vendor lock-in? There is some concern by organizations and developers about vendor lock-in on serverless platforms. It is unclear if portability is worse for serverless than other infrastructure-as-a-service pieces, but still worth -thinking about ahead of time. These resources provide additional -perspectives on lock-in and using multiple cloud providers. - -* [On Serverless, Multi-Cloud, and Vendor Lock In](https://blog.symphonia.io/on-serverless-multi-cloud-and-vendor-lock-in-da930b3993f) - is an opinion piece that for *most* cases the additional work of - going multi-cloud is not worth the tradeoffs, therefore at this time - it's better to go for a single vendor such as AWS or Azure and optimize - on that platform. - -* [Why vendor lock-in with serverless isn’t what you think it is](https://medium.com/@PaulDJohnston/why-vendor-lock-in-with-serverless-isnt-what-you-think-it-is-d6be40fa9ca9) - recommends using a single vendor for now and stop worrying about - hedging your bets because it typically makes your infrastructure - significantly more complex. +thinking about ahead of time. +[Why vendor lock-in with serverless isn’t what you think it is](https://medium.com/@PaulDJohnston/why-vendor-lock-in-with-serverless-isnt-what-you-think-it-is-d6be40fa9ca9) +is a piece on this topic that recommends using a single vendor for +now and for organizations to stop worrying about hedging their bets +because it typically makes infrastructure significantly more complex. diff --git a/content/pages/05-deployment/39-aws-lambda.markdown b/content/pages/05-deployment/39-aws-lambda.markdown index ab177e024..80efa5ef7 100644 --- a/content/pages/05-deployment/39-aws-lambda.markdown +++ b/content/pages/05-deployment/39-aws-lambda.markdown @@ -38,8 +38,7 @@ has support for both Python 2.7, 3.6 and 3.7. * [Zappa](https://github.com/Miserlou/Zappa) is a serverless framework for deploying Python web applications. It's a really slick project and used even by internal AWS developers for their own application - deployments. Be sure to [read the Zappa blog](https://blog.zappa.io/) - as well for walkthroughs and new feature announcements. + deployments. * [How to Setup a Serverless URL Shortener With API Gateway Lambda and DynamoDB on AWS](https://blog.ruanbekker.com/blog/2018/11/30/how-to-setup-a-serverless-url-shortener-with-api-gateway-lambda-and-dynamodb-on-aws/) builds a non-trivial URL shortener application as an example Python @@ -53,10 +52,6 @@ has support for both Python 2.7, 3.6 and 3.7. provides a screen capture of one developer deploying their application to Lambda. -* [Automated SQL Injection Testing of Serverless Functions On a Shoestring Budget (and Some Good Music)](https://www.puresec.io/blog/automated-sql-injection-testing-of-serverless-functions-on-a-shoestring-budget-and-some-good-music) - is an awesome operational security post that uses Python to test - for SQL injection vulnerabilities in serverless functions on AWS Lambda. - * [Building Scikit-Learn For AWS Lambda](https://serverlesscode.com/post/scikitlearn-with-amazon-linux-container/) follows up on the [Using Scikit-Learn In AWS Lambda](https://serverlesscode.com/post/deploy-scikitlearn-on-lamba/) @@ -70,20 +65,12 @@ has support for both Python 2.7, 3.6 and 3.7. * [Code Evaluation With AWS Lambda and API Gateway](https://realpython.com/blog/python/code-evaluation-with-aws-lambda-and-api-gateway/) shows how to develop a code evaluation API, to execute arbitrary code, with AWS Lambda and API Gateway. -* [Crawling thousands of products using AWS Lambda](https://engineering.21buttons.com/crawling-thousands-of-products-using-aws-lambda-80332e259de1) - gives a real-world example of where using Python, Selenium and - [headless Chrome](https://developers.google.com/web/updates/2017/04/headless-chrome) - on AWS Lambda could crawl thousands of pages to collect data - with each crawler running within its own Lambda Function. - -* [Going Serverless with AWS Lambda and API Gateway](http://blog.ryankelly.us/2016/08/07/going-serverless-with-aws-lambda-and-api-gateway.html) - ### General AWS Lambda resources -* [AWS Lambda Serverless Reference Architectures](http://www.allthingsdistributed.com/2016/06/aws-lambda-serverless-reference-architectures.html) - provides blueprints with diagrams of common architecture patterns that - developers use for their mobile backend, file processing, stream - processing and web application projects. +* [Getting started with serverless on AWS](https://emshea.com/post/serverless-getting-started) + is a wonderful tutorials, example projects and additional resources + guide created by a developer who used all of these bits to learn + AWS services herself. * [Security Overview of AWS Lambda](https://d1.awsstatic.com/whitepapers/Overview-AWS-Lambda-Security.pdf) (PDF file) covers their "Shared Responsibility Model" for security and diff --git a/content/pages/05-deployment/40-azure-functions.markdown b/content/pages/05-deployment/40-azure-functions.markdown index 4cb8243e1..7f718f64a 100644 --- a/content/pages/05-deployment/40-azure-functions.markdown +++ b/content/pages/05-deployment/40-azure-functions.markdown @@ -44,6 +44,3 @@ in other Azure services. what is confusing to newcomers that hopefully will be addressed as Microsoft continues to work on their Azure platform. -* [Azure in Plain English](https://www.expeditedssl.com/azure-in-plain-english) - covers all of the Azure services and explains them because their - default names are often too vague to understand their purpose. diff --git a/content/pages/06-devops/00-devops.markdown b/content/pages/06-devops/00-devops.markdown index 47ec79be1..f6053c2e4 100644 --- a/content/pages/06-devops/00-devops.markdown +++ b/content/pages/06-devops/00-devops.markdown @@ -35,8 +35,8 @@ tools and services for DevOps environments. which when used properly can enable continuous software delivery. * For an Atlassian-centric perspective on tooling, take a look at - this post on how to - [choose the right DevOps tools](http://blogs.atlassian.com/2016/03/how-to-choose-devops-tools/) + this guide on how to + [choose the right DevOps tools](https://www.atlassian.com/devops/devops-tools) which is biased towards their tools but still has some good insight such as using automated testing to provide immediate awareness of defects that require fixing. @@ -47,10 +47,10 @@ The following resources give advice and approaches for building the right teams, culture, processes and tools into software development organizations. * [DevOps vs. Platform Engineering](https://alexgaynor.net/2015/mar/06/devops-vs-platform-engineering/) - considers DevOps an ad hoc approach to developing software while building - a platform is a strict contract. I see this as "DevOps is a process", - while a "platform is code". Running code is better than any organizational - process. + considers DevOps to be an ad hoc approach to developing software while + building a platform is a strict contract. I see this as "DevOps is a + process", while a "platform is code". Running code is better than any + organizational process. * The open source [PagerDuty Incident Response guide](https://response.pagerduty.com/) is the @@ -58,6 +58,12 @@ teams, culture, processes and tools into software development organizations. their services running and putting them out for other developers to consume. Highly recommended. +* [Introduction to DevOps and Software Delivery Performance](https://www.stridenyc.com/blog/devops-and-software-delivery-performance) + explains the four key delivery metrics of Delivery Lead Time, + Deployment Frequency, Time to Restore Service, and Change Fail Rate, + and then gives a high-level overview of technical, process and + cultural capabilities that impact these metrics. + * [Operations for software developers for beginners](https://jvns.ca/blog/2016/10/15/operations-for-software-developers-for-beginners/) gives advice to developers who have never done operations work and been on call for outages before in their career. The advantage of DevOps @@ -82,10 +88,6 @@ teams, culture, processes and tools into software development organizations. your pager goes off, ownership and how startups can be different from large companies with their incident responses. -* [Bing: Continuous Delivery](http://stories.visualstudio.com/bing-continuous-delivery/) - is an impressive visual story that explains the practices for how their - team delivers updates to the search engine. - * [Why are we racing to DevOps?](http://www.cio.com/article/3015237/application-development/why-are-we-racing-to-devops.html) is a very high level summary of the benefits of DevOps to IT organizations. It's not specific to Python and doesn't dive into the details, but it's diff --git a/content/pages/06-devops/01-monitoring.markdown b/content/pages/06-devops/01-monitoring.markdown index 95efe2cf4..50021eecf 100644 --- a/content/pages/06-devops/01-monitoring.markdown +++ b/content/pages/06-devops/01-monitoring.markdown @@ -112,7 +112,7 @@ Application Performance Monitoring (APM) * [New Relic](http://newrelic.com/) provides application and database monitoring as well as plug ins for capturing and analyzing data about - other devleoper tools in your stack, such as [Twilio](/twilio.html). + other developer tools in your stack, such as [Twilio](/twilio.html). * [Opbeat](https://opbeat.com) Built for django. Opbeat combines performance metrics, release tracking, and error logging into a single simple service. * [Scout](https://scoutapp.com/python-monitoring) monitors the performance of Django and Flask apps, auto-instrumenting views, SQL queries, templates, and more. @@ -146,11 +146,6 @@ Incident Management * [The Virtues of Monitoring](http://www.paperplanes.de/2011/1/5/the_virtues_of_monitoring.html) -* [Effortless Monitoring with collectd, Graphite, and Docker](http://blog.docker.io/2013/07/effortless-monitoring-with-collectd-graphite-and-docker/) - -* [Practical Guide to StatsD/Graphite Monitoring](http://matt.aimonetti.net/posts/2013/06/26/practical-guide-to-graphite-monitoring/) - is a detailed guide with code examples for monitoring infrastructure. - * Bit.ly describes the "[10 Things They Forgot to Monitor](http://word.bitly.com/post/74839060954/ten-things-to-monitor)" beyond the standard metrics such as disk & memory usage. diff --git a/content/pages/06-devops/03-prometheus.markdown b/content/pages/06-devops/03-prometheus.markdown index 54eeddc20..7974550b9 100644 --- a/content/pages/06-devops/03-prometheus.markdown +++ b/content/pages/06-devops/03-prometheus.markdown @@ -16,6 +16,11 @@ and report on Python [web applications](/web-development.html). ### Prometheus resources +* [Prometheus-Basics](https://github.com/yolossn/Prometheus-Basics) + is a newbie's introduction to this tool. It covers what Prometheus + is, the tool's architecture, types of metrics and contains a + walkthrough of how to get it configured. + * This primer on [Prometheus](https://www.kartar.net/2017/10/prometheus/) walks through installation, configuration and metrics collection. diff --git a/content/pages/06-devops/06-web-app-performance.markdown b/content/pages/06-devops/06-web-app-performance.markdown index cba1f4c0d..8a954546f 100644 --- a/content/pages/06-devops/06-web-app-performance.markdown +++ b/content/pages/06-devops/06-web-app-performance.markdown @@ -49,10 +49,6 @@ database queries, page size and many other factors. is a 20 minute code-first demo that shows how to get a realistic estimate for how many requests per second your web application will be able to handle. -* [How to Interpret Site Performance Tests](https://fly.io/articles/how-to-understand-performance-tests/) - covers the difference between client, page and connection speed tests - as well as a bit on caching performance. - * [Practical scaling techniques for websites](https://hackernoon.com/practical-scaling-techniques-for-web-sites-554a38dbd492) examines how to improve your website performance with asynchronous [task queues](/task-queues.html), [database](/databases.html) optimization @@ -67,7 +63,21 @@ database queries, page size and many other factors. provides a list with a crazy number of scaling and performance optimization resources and tools by category. +* [Every Web Performance Test Tool](https://www.swyx.io/writing/webperf-tests/) + provides a nice list of tools and provides short summaries of what each + one can help with in identifying performance problems. + * [The Infrastructure Behind Twitter: Scale](https://blog.twitter.com/engineering/en_us/topics/infrastructure/2017/the-infrastructure-behind-twitter-scale.html) examines the evolution from having to buy your own hardware from vendors to run a service to the current days of being able to rely on cloud providers for some or all workloads regardless of scale. + +* [Scaling to 100k users](https://alexpareto.com/scalability/systems/2020/02/03/scaling-100k.html) + covers the architecture scaling techniques commonly used to move up + in serving users by orders of magnitude, for example from 100 to 1000. + +* [Web Performance Recipes with Puppeteer](https://addyosmani.com/blog/puppeteer-recipes/) + digs into tracing through page rendering to measure performance and + how to extract performance metrics from the + [Lighthouse](https://developers.google.com/web/tools/lighthouse/) tool + for further analysis. diff --git a/content/pages/06-devops/11-caching.markdown b/content/pages/06-devops/11-caching.markdown index 5a8e94abf..c8aebbbf1 100644 --- a/content/pages/06-devops/11-caching.markdown +++ b/content/pages/06-devops/11-caching.markdown @@ -45,19 +45,10 @@ A cache can be created for multiple layers of the stack. reading even though the author is describing his Microsoft code as the impetus for writing the content. -* While caching is a useful technique in many situations, it's important - to also note that there are - [downsides to caching](https://msol.io/blog/tech/2015/09/05/youre-probably-wrong-about-caching/) - that many developers fail to take into consideration. - * [Caching at Reddit](https://redditblog.com/2017/1/17/caching-at-reddit/) covers monitoring, tuning and scaling for the very high scale [Reddit.com](https://www.reddit.com/) website. -* [Mastering HTTP caching](https://blog.fortrabbit.com/mastering-http-caching) - provides more advanced advice on caching dynamic as well as static - content via CDNs and other configurations. - ## Caching learning checklist diff --git a/content/pages/06-devops/14-logging.markdown b/content/pages/06-devops/14-logging.markdown index 3fa5b0e30..9738d98fc 100644 --- a/content/pages/06-devops/14-logging.markdown +++ b/content/pages/06-devops/14-logging.markdown @@ -55,8 +55,9 @@ certain threshold. There are libraries for most major languages, including python. Saves data in Elasticache. -* [Logstash](http://logstash.net/) Similar to Graylog2, logstash offers - features to programmatically configure log data workflows. +* [Logstash](https://www.elastic.co/guide/en/logstash/current/index.html). + Similar to Graylog2, logstash offers features to programmatically + configure log data workflows. * [Scribe](https://github.com/facebook/scribe) A project written by Facebook to aggregate logs. It's designed to run on multiple servers and scale with @@ -112,7 +113,7 @@ certain threshold. * [Good logging practice in Python](http://victorlin.me/posts/2012/08/26/good-logging-practice-in-python) shows how to use the standard library to log data from your application. Definitely worth a read as most applications do not log nearly enough - output to help debuggin when things go wrong, or to determine if something + output to help debugging when things go wrong, or to determine if something is going wrong. * [Structured Logging: The Best Friend You’ll Want When Things Go Wrong](https://engineering.grab.com/structured-logging) diff --git a/content/pages/06-devops/18-web-analytics.markdown b/content/pages/06-devops/18-web-analytics.markdown index c51330f04..6430b1057 100644 --- a/content/pages/06-devops/18-web-analytics.markdown +++ b/content/pages/06-devops/18-web-analytics.markdown @@ -38,9 +38,13 @@ application before taking some action, such as purchasing your service. ## Open source web analytics projects -* [Piwik](http://piwik.org/) is a web analytics platform you can host yourself. - Piwik is a solid choice if you cannot use Google Analytics or want to - customize your own web analytics platform. +* [Matoma](https://matomo.org/) (formerly Piwik), is a web analytics + platform that you can host yourself. Matoma is a solid choice if you + cannot use Google Analytics or want to customize your own web analytics + software. + +* [Shynet](https://github.com/milesmcc/shynet) is a lightweight, privacy-friendly + cookie-free web analytics application written in Python. * [Open Web Analytics](http://www.openwebanalytics.com/) is another self-hosted platform that integrates through a JavaScript snippet that @@ -59,10 +63,6 @@ application before taking some action, such as purchasing your service. collected into the server side or client side code. MixPanel captures that data and provides metrics and visualizations based on the data. -* [KISSmetrics](https://www.kissmetrics.com/)' analytics provides context - for who is visiting a website and what actions they are taking while on - the site. - * [Heap](https://heapanalytics.com/) is a recently founded analytics service with a free introductory tier to get started. @@ -110,10 +110,6 @@ application before taking some action, such as purchasing your service. is not for everyone but it is really useful if you want to avoid the Google data trap. -* This beginner's guide to - [math and stats behind web analytics](http://www.seotakeaways.com/beginners-guide-maths-stats-web-analytics/) - provides some context for understanding and reasoning about web traffic. - * [An Analytics Primer for Developers](https://hacks.mozilla.org/2015/03/an-analytics-primer-for-developers/) by Mozilla explains what to track, choosing an analytics platform and how to serve up the analytics JavaScript asynchronously. @@ -143,8 +139,8 @@ application before taking some action, such as purchasing your service. ## Web analytics learning checklist -1. Add Google Analytics or Piwik to your application. Both are free and while - Piwik is not as powerful as Google Analytics you can self-host the +1. Add Google Analytics or Matoma to your application. Both are free and while + Matoma is not as powerful as Google Analytics you can self-host the application which is the only option in many environments. 1. Think critically about the factors that will make your application diff --git a/content/pages/10-working/00-gpt-3.markdown b/content/pages/10-working/00-gpt-3.markdown new file mode 100644 index 000000000..04e1726a5 --- /dev/null +++ b/content/pages/10-working/00-gpt-3.markdown @@ -0,0 +1,171 @@ +title: GPT-3 +category: page +slug: gpt-3 +sortorder: 1001 +toc: False +sidebartitle: GPT-3 +meta: GPT-3 is a trained neural network with 175 billion parameters that allows it to be significantly better at text generation than previous models. + + +[GPT-3](https://arxiv.org/abs/2005.14165) is a neural network +trained by the [OpenAI](https://openai.com/) organization with +significantly more parameters than previous generation models. + +There are several variations of GPT-3, which range from 125 to 175 billion +parameters. The different variations allow the model to better respond to +different types of input, such as a question & answer format, long-form +writing, human language translations (e.g. English to French). The large +numbers of parameters make GPT-3 significantly better at natural +language processing and text generation than the prior model, +[GPT-2](https://openai.com/blog/gpt-2-1-5b-release/), which only had +1.5 billion parameters. + +OpenAI logo. + +GPT-3 can only currently be access by an +[API provided by OpenAI](https://openai.com/blog/openai-api/), which is +in private beta. + + +## What's so special about GPT-3? +The GPT-3 model can generate texts of up to 50,000 characters, with no +supervision. It can even generate creative Shakespearean-style fiction +stories in addition to fact-based writing. This is the first time that a +neural network model has been able to generate texts at an acceptable +quality that makes it difficult, if not impossible, for a typical +person to whether the output was written by a human or GPT-3. + + +## How does GPT-3 work? +To generate output, GPT-3 has a very large vocabulary, which it can +combine to generate sentences. These words are sorted +into different categories (nouns, verbs, adjectives, etc.), and for each +category, there is a “production rule”, which can be used to generate a +sentence. The production rules can be modified with different parameters. + +A few examples: + +* noun + verb = subject + verb +* noun + verb + adjective = subject + verb + adjective +* verb + noun = subject + verb +* noun + verb + noun = subject + verb + noun +* noun + noun = subject + noun +* noun + verb + noun + noun = subject + verb + noun + noun + +In addition, GPT-3 is able to understand negations, as well as the use +of tenses, which allows the model to generate sentences in the past, +present and future. + + +## Does GPT-3 matter to Python developers? +GPT-3 is not that useful right now for programmers other than as an +experiment. If you get access to [OpenAI's API](https://openai.com/blog/openai-api/) +then Python is an easy language to use for interacting with it and +you could use its text generation as inputs into your applications. +Although there have been some initial impressive experiments in +generating code for +[the layout of the Google homepage](https://twitter.com/sharifshameem/status/1283322990625607681), +[JSX output](https://twitter.com/sharifshameem/status/1282676454690451457), +and [other technical demos](https://twitter.com/__MLT__/status/1287357881675853825), +the +[model will otherwise not (yet) put any developers out of a job](https://www.youtube.com/watch?v=Yg3C38P5EkA) +who are coding real-world applications. + + +## How was GPT-3 trained? +At a high level, training the GPT-3 neural network consists of two steps. + +The first step requires creating the vocabulary, the different +categories and the production rules. This is done by feeding +GPT-3 with books. For each word, the model must predict the category +to which the word belongs, and then, a production rule must be created. + +The second step consists of creating a vocabulary and production rules +for each category. This is done by feeding the model with sentences. +For each sentence, the model must predict the category to which each +word belongs, and then, a production rule must be created. + +The result of the training is a vocabulary, and production rules for each +category. + +The model also has a few tricks that allow it to improve its ability to +generate texts. For example, it is able to guess the beginning of a word +by observing the context of the word. It can also predict the next word +by looking at the last word of a sentence. It is also able to predict the +length of a sentence. + +While those two steps and the related tricks may sound simple in theory, +in practice they require massive amounts of computation. Training +175 billion parameters in mid-2020 cost in the ballpark of +[$4.6 million dollars](https://lambdalabs.com/blog/demystifying-gpt-3/#:~:text=But%20to%20put%20things%20into,for%20a%20single%20training%20run.), +although some other estimates calculated it could take up +to $12 million depending on how the hardware was provisioned. + + +## GPT-3 resources +These resources range from broad philosophy of what GPT-3 means +for machine learning to specific technical details for how the model +is trained. + +* [The Ultimate Guide to OpenAI's GPT-3 Language Model](https://www.twilio.com/blog/ultimate-guide-openai-gpt-3-language-model) + is a detailed tutorial on how to use OpenAI's playground user interface, + what the parameters do, and how to convert what you have done in + the playground into a Python script that calls their API. + +* [OpenAI's GPT-3 Language Model: A Technical Overview](https://lambdalabs.com/blog/demystifying-gpt-3/) + and + [GPT-3: A Hitchhiker's Guide](https://lambdalabs.com/blog/gpt-3/) + are two long-format guides that analyze how GPT-3's technical + specifications fit in the larger machine learning ecosystem, quotes by + researchers on its usage, and some initial resources to get a + better understanding of what this model is capable of performing. + +* [What Is GPT-3: How It Works and Why You Should Care](https://www.twilio.com/blog/what-is-gpt-3) + presents a high-level accessible overview of GPT-3, how it compares + to other language models, and resources to learn more. + +* [How GPT3 Works - Visualizations and Animations](https://jalammar.github.io/how-gpt3-works-visualizations-animations/) + contains some wonderful animated visuals to show how the model is + trained and what happens in various scenarios such as text output + and code generation. + +* [GPT 3 Demo and Explanation](https://www.youtube.com/watch?v=8psgEDhT1MM) + is a video that gives a brief overview of GPT-3 and shows a bunch + of live demos for what has so far been created with this technology. + +* [Tempering expectations for GPT-3](https://minimaxir.com/2020/07/gpt3-expectations/) + points out that many of the good examples on social media have been + cherry picked to impress readers. + +* [Why GPT-3 matters](https://leogao.dev/2020/05/29/GPT-3-A-Brief-Summary/) + compares and contrasts this model with similar models that have been + developed and tries to give an overview of where each one stands + with its strengths and weaknesses. + + +## GPT-3 tutorials +* [Building a Chatbot with OpenAI's GPT-3 engine, Twilio SMS and Python](https://www.twilio.com/blog/openai-gpt-3-chatbot-python-twilio-sms) + is a step-by-step tutorial for using GPT-3 as a smart backend + for an SMS-based chatbot powered by the [Twilio API](/twilio.html). + +* [Automating my job by using GPT-3 to generate database-ready SQL to answer business questions](https://blog.seekwell.io/gpt3) + walks through how the author created a bridge to translate between + plain English-language questions and + [relational database](/databases.html) SQL. The post provides both + a story for why someone would want to use GPT-3 for this purpose and + incremental steps for how the author started and figured out how + to make it better. In the end it does not quite work in all scenarios + but the proof of concept is impressive and the story is a fun read. + +* [gpt-3-experiments](https://github.com/minimaxir/gpt-3-experiments) + contains Python code open sourced under the MIT license that + shows how to interact with the API. + +* [Twilio](/twilio.html) put out a series of fun GPT-3 tutorials that show + the range of creative outputs the model can generate: + + * [Control a Spooky Ghost Writer for Halloween with OpenAI's GPT-3 Engine, Python, and Twilio WhatsApp API](https://www.twilio.com/blog/ghost-writer-spooky-openai-gpt3-python-whatsapp) + * [Generating Lyrics in the Style of your Favorite Artist with Python, OpenAI's GPT-3 and Twilio SMS](https://www.twilio.com/blog/generating-lyrics-in-the-style-of-your-favorite-artist-with-python-openai-s-gpt-3-and-twilio-sms) + * [Automated Yugioh Deckbuilding in Python with OpenAI's GPT-3 and Twilio SMS](https://www.twilio.com/blog/building-computer-generated-yugioh-decks-in-python-with-openai-s-gpt-3-and-twilio-sms) + * [Build a Telephone Chatbot with GPT-3 and Twilio Autopilot](https://www.twilio.com/blog/build-telephone-chatbot-gpt3-twilio-autopilot) + diff --git a/content/pages/10-working/01-event-streams.markdown b/content/pages/10-working/01-event-streams.markdown new file mode 100644 index 000000000..0daa6e45f --- /dev/null +++ b/content/pages/10-working/01-event-streams.markdown @@ -0,0 +1,58 @@ +title: Event Streams +category: page +slug: event-streams +sortorder: 1002 +toc: False +sidebartitle: Event Streams +meta: An event stream is a log of one or more events. + + +Event streams are a log of one or more "things that happen", which are +usually referred to as events. Event streams are +conceptually focused around events than objects or tables, which are +the typical storage unit of [relational databases](/databases.html). + +Apache Kafka and Gazette are a popular open source implementations of event +streams. Amazon Web Services' Kinesis and +[Azure Event-Hubs](https://azure.microsoft.com/en-us/services/event-hubs/) +are proprietary hosted implementations. + + +## Why do event streams matter to developers? +The way that data is stored affects how you can work with it. Constraints +and guarantees like consistency make it easier to code certain applications +but harder to build other types of applications that need performance in +different ways. Event streams make it easier to build applications that +analyze large amounts of constantly-updated data because the events are +not stored relationally. + + +## How are event streams typically stored? +Some applications, such as aggregating millions of sensors, or thousands +of streaming cameras, constantly output large amounts of data with no breaks. +It is difficult to process such large volumes of data in traditional data +stores, so event streams are built off of a simpler data structure: logs. + +Logs are ordered sequences of events and they typically have less constraints +than a database. In event streams, logs are also immutable. They do not change +once they are written. Instead, newer events are written in the sequence as +state changes. The reduced constraints compared to a database and the +immutability mean that logs can handle the high throughput writes needed to +keep up with the constant flood of data from the source of an event stream. + + +## Event stream resources +* [What is Apache Kafka?](https://www.youtube.com/watch?v=FKgi3n-FyNU) sounds + like it just focuses on Kafka but it actually covers the fundamental + concepts behind event streams and how they fit into + [microservices](/microservices.html) architectures. + +* Quora has a solid answer to the question of + [what is an event stream?](https://www.quora.com/What-is-an-event-stream). + +* [Summary of the Amazon Kinesis Event in the Northern Virginia (US-EAST-1) Region](https://aws.amazon.com/message/11201/) + is specific to AWS Kinesis but it explains how Amazon uses event + streams at scale to run and coordinate a significant number of their + services. When their event streams service went down... it took a + whole lot of other stuff down at the same time. There is also some + [additional analysis in this post by an independent developer](https://ryanfrantz.com/posts/aws-kinesis-outage-analysis.html). diff --git a/content/pages/10-working/18-developer-demos.md b/content/pages/10-working/18-developer-demos.md new file mode 100644 index 000000000..a195edfdc --- /dev/null +++ b/content/pages/10-working/18-developer-demos.md @@ -0,0 +1,29 @@ +title: Demoing to Software Developers +category: page +slug: demo-software-developers +sortorder: 1018 +toc: False +sidebartitle: Developer Demos +meta: How to give technical demos to software developers. + + +Creating and executing an appealing technical demo to an audience of software +developers is a ton of work, but there is no better way to get people +legitimately interested in your product if you land a great demo with +an appropriate audience. The inherent difficulty involved in exceptional +technical demos also creates a large barrier that prevent others from simply +copying your work, which can happen with technical blog content. + +To achieve a standout technical demo you must: + +1. show how to easily solve a difficult technical problem +1. speak plainly but accurately +1. do it live, including writing code if required +1. tell a story with a narrative arc +1. rehearse constantly, both the happy path and recovering from errors + + +Examples: +* [Twilio Phone Calls Demo at NY Tech Meetup (2010)](https://www.youtube.com/watch?v=-VuXIgp9S7o) +* [Concurrency from the Ground Up (2015)](https://www.youtube.com/watch?v=MCs5OvhV9S4) +* [The Mother of All Demos (1968)](https://www.youtube.com/watch?v=yJDv-zdhzMY) diff --git a/content/pages/examples/celery/celery-example-projects-code.markdown b/content/pages/examples/celery/celery-example-projects-code.markdown new file mode 100644 index 000000000..ba474a42f --- /dev/null +++ b/content/pages/examples/celery/celery-example-projects-code.markdown @@ -0,0 +1,17 @@ +title: Celery Example Projects and Code +category: page +slug: celery-code-examples +sortorder: 500040001 +toc: False +sidebartitle: Celery Example Code +meta: Python example projects and code for using the Celery asynchronous task queue. + + +## Example Projects with Great Example Code +The following active projects use the [Celery](/celery.html) task queue +in various ways. The code within the projects can show you how to build +your own applications. + + +### flask-celery-example + diff --git a/content/pages/examples/django/django-conf-urls-url.markdown b/content/pages/examples/django/django-conf-urls-url.markdown index 6540e8fe8..23f28e83c 100644 --- a/content/pages/examples/django/django-conf-urls-url.markdown +++ b/content/pages/examples/django/django-conf-urls-url.markdown @@ -128,7 +128,7 @@ urlpatterns = [ ## Example 3 from register [register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), -[Bootstrap](/bootstrap.html), [PostgreSQL](/postgresql.html) project that is +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is open source under the [GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). This web application makes it easier for people to register as organ donors. diff --git a/content/pages/examples/django/django-contrib-admin-helpers-actionform.markdown b/content/pages/examples/django/django-contrib-admin-helpers-actionform.markdown new file mode 100644 index 000000000..322d1d28a --- /dev/null +++ b/content/pages/examples/django/django-contrib-admin-helpers-actionform.markdown @@ -0,0 +1,102 @@ +title: django.contrib.admin.helpers ActionForm Example Code +category: page +slug: django-contrib-admin-helpers-actionform-examples +sortorder: 500011020 +toc: False +sidebartitle: django.contrib.admin.helpers ActionForm +meta: Python example code for the ActionForm class from the django.contrib.admin.helpers module of the Django project. + + +[ActionForm](https://github.com/django/django/blob/master/django/contrib/admin/helpers.py) +is a class within the django.contrib.admin.helpers module of the +[Django](/django.html) project. It is not typically used when creating +applications but is sometimes used by libraries that want to extend the +[actions available](https://docs.djangoproject.com/en/stable/ref/contrib/admin/actions/) +within the +[Django Admin](https://docs.djangoproject.com/en/stable/ref/contrib/admin/). + + +## Example 1 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / forms.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./forms.py) + +```python +# forms.py +import os.path + +from django import forms +~~from django.contrib.admin.helpers import ActionForm +from django.utils.translation import gettext_lazy as _ + + +class ImportForm(forms.Form): + import_file = forms.FileField( + label=_('File to import') + ) + input_format = forms.ChoiceField( + label=_('Format'), + choices=(), + ) + + def __init__(self, import_formats, *args, **kwargs): + super().__init__(*args, **kwargs) + choices = [] + for i, f in enumerate(import_formats): + choices.append((str(i), f().get_title(),)) + if len(import_formats) > 1: + choices.insert(0, ('', '---')) + + self.fields['input_format'].choices = choices + + +class ConfirmImportForm(forms.Form): + + +## ... source file abbreviated to get to ActionForm examples ... + + + + def clean_import_file_name(self): + data = self.cleaned_data['import_file_name'] + data = os.path.basename(data) + return data + + +class ExportForm(forms.Form): + file_format = forms.ChoiceField( + label=_('Format'), + choices=(), + ) + + def __init__(self, formats, *args, **kwargs): + super().__init__(*args, **kwargs) + choices = [] + for i, f in enumerate(formats): + choices.append((str(i), f().get_title(),)) + if len(formats) > 1: + choices.insert(0, ('', '---')) + + self.fields['file_format'].choices = choices + + +def export_action_form_factory(formats): +~~ class _ExportActionForm(ActionForm): + file_format = forms.ChoiceField( + label=_('Format'), choices=formats, required=False) + _ExportActionForm.__name__ = str('ExportActionForm') + + return _ExportActionForm + + + +## ... source file continues with no further ActionForm examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-admin-helpers-adminform.markdown b/content/pages/examples/django/django-contrib-admin-helpers-adminform.markdown new file mode 100644 index 000000000..27b6fe19d --- /dev/null +++ b/content/pages/examples/django/django-contrib-admin-helpers-adminform.markdown @@ -0,0 +1,120 @@ +title: django.contrib.admin.helpers AdminForm Example Code +category: page +slug: django-contrib-admin-helpers-adminform-examples +sortorder: 500011021 +toc: False +sidebartitle: django.contrib.admin.helpers AdminForm +meta: Python example code for the AdminForm class from the django.contrib.admin.helpers module of the Django project. + + +[AdminForm](https://github.com/django/django/blob/master/django/contrib/admin/helpers.py) +is a class within the django.contrib.admin.helpers module of the +[Django](/django.html) project. AdminForm is not usually used directly by +developers but can be used by libraries that want to extend the +[forms](https://docs.djangoproject.com/en/3.0/ref/contrib/admin/admindocs/) +within the +[Django Admin](https://docs.djangoproject.com/en/stable/ref/contrib/admin/). + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / admin / placeholderadmin.py**](https://github.com/divio/django-cms/blob/develop/cms/admin/placeholderadmin.py) + +```python +# placeholderadmin.py +import uuid +import warnings + +from django.conf.urls import url +~~from django.contrib.admin.helpers import AdminForm +from django.contrib.admin.utils import get_deleted_objects +from django.core.exceptions import PermissionDenied +from django.db import router, transaction +from django.http import ( + HttpResponse, + HttpResponseBadRequest, + HttpResponseForbidden, + HttpResponseNotFound, + HttpResponseRedirect, +) +from django.shortcuts import get_list_or_404, get_object_or_404, render +from django.template.response import TemplateResponse +from django.utils.decorators import method_decorator +from django.utils.encoding import force_text +from django.utils import translation +from django.utils.translation import ugettext as _ +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.decorators.http import require_POST + +from six.moves.urllib.parse import parse_qsl, urlparse + +from six import get_unbound_function, get_method_function + +from cms import operations + + +## ... source file abbreviated to get to AdminForm examples ... + + + saved_successfully = False + cancel_clicked = request.POST.get("_cancel", False) + raw_fields = request.GET.get("edit_fields") + fields = [field for field in raw_fields.split(",") if field in self.frontend_editable_fields] + if not fields: + context = { + 'opts': opts, + 'message': force_text(_("Field %s not found")) % raw_fields + } + return render(request, 'admin/cms/page/plugin/error_form.html', context) + if not request.user.has_perm("{0}.change_{1}".format(self.model._meta.app_label, + self.model._meta.model_name)): + context = { + 'opts': opts, + 'message': force_text(_("You do not have permission to edit this item")) + } + return render(request, 'admin/cms/page/plugin/error_form.html', context) + form_class = self.get_form(request, obj, fields=fields) + if not cancel_clicked and request.method == 'POST': + form = form_class(instance=obj, data=request.POST) + if form.is_valid(): + form.save() + saved_successfully = True + else: + form = form_class(instance=obj) +~~ admin_form = AdminForm(form, fieldsets=[(None, {'fields': fields})], prepopulated_fields={}, + model_admin=self) + media = self.media + admin_form.media + context = { + 'CMS_MEDIA_URL': get_cms_setting('MEDIA_URL'), + 'title': opts.verbose_name, + 'plugin': None, + 'plugin_id': None, + 'adminform': admin_form, + 'add': False, + 'is_popup': True, + 'media': media, + 'opts': opts, + 'change': True, + 'save_as': False, + 'has_add_permission': False, + 'window_close_timeout': 10, + } + if cancel_clicked: + context.update({ + 'cancel': True, + }) + return render(request, 'admin/cms/page/plugin/confirm_form.html', context) + if not cancel_clicked and request.method == 'POST' and saved_successfully: + return render(request, 'admin/cms/page/plugin/confirm_form.html', context) + + +## ... source file continues with no further AdminForm examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-admin-helpers.markdown b/content/pages/examples/django/django-contrib-admin-helpers.markdown new file mode 100644 index 000000000..0e32e48f9 --- /dev/null +++ b/content/pages/examples/django/django-contrib-admin-helpers.markdown @@ -0,0 +1,382 @@ +title: django.contrib.admin helpers Example Code +category: page +slug: django-contrib-admin-helpers-examples +sortorder: 500011017 +toc: False +sidebartitle: django.contrib.admin helpers +meta: Python example code for the helpers callable from the django.contrib.admin module of the Django project. + + +[helpers](https://github.com/django/django/blob/master/django/contrib/admin/helpers.py) +is a module within the [Django](/django.html) project code base. It +contains classes related to extending the functionality of the +[Django Admin](https://docs.djangoproject.com/en/3.0/ref/contrib/admin/actions/), +such as [ActionForm](/django-contrib-admin-helpers-actionform-examples.html) +and [AdminForm](/django-contrib-admin-helpers-adminform-examples.html). + + +## Example 1 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / folderadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/folderadmin.py) + +```python +# folderadmin.py +from __future__ import absolute_import, division, unicode_literals + +import itertools +import os +import re +from collections import OrderedDict + +from django import forms +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import messages +~~from django.contrib.admin import helpers +from django.contrib.admin.utils import capfirst, quote, unquote +from django.core.exceptions import PermissionDenied, ValidationError +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db import models, router +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils.encoding import force_text +from django.utils.html import escape +from django.utils.http import urlquote, urlunquote +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy, ungettext + +from .. import settings +from ..models import ( + File, Folder, FolderPermission, FolderRoot, ImagesWithMissingData, + UnsortedImages, tools, +) +from ..settings import FILER_IMAGE_MODEL, FILER_PAGINATE_BY +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import get_delete_permission +from ..utils.filer_easy_thumbnails import FilerActionThumbnailer +from ..utils.loader import load_model + + +## ... source file abbreviated to get to helpers examples ... + + + if "move-to-clipboard-%d" % (f.id,) in request.POST: + clipboard = tools.get_user_clipboard(request.user) + if f.has_edit_permission(request): + tools.move_file_to_clipboard([f], clipboard) + return HttpResponseRedirect(request.get_full_path()) + else: + raise PermissionDenied + + selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME) + if ( + actions and request.method == 'POST' + and 'index' in request.POST + and '_save' not in request.POST + ): + if selected: + response = self.response_action(request, files_queryset=file_qs, folders_queryset=folder_qs) + if response: + return response + else: + msg = _("Items must be selected in order to perform " + "actions on them. No items have been changed.") + self.message_user(request, msg) + + if ( + actions and request.method == 'POST' +~~ and helpers.ACTION_CHECKBOX_NAME in request.POST + and 'index' not in request.POST + and '_save' not in request.POST + ): + if selected: + response = self.response_action(request, files_queryset=file_qs, folders_queryset=folder_qs) + if response: + return response + + if actions: + action_form = self.action_form(auto_id=None) + action_form.fields['action'].choices = self.get_action_choices(request) + else: + action_form = None + + selection_note_all = ungettext('%(total_count)s selected', + 'All %(total_count)s selected', paginator.count) + + try: + paginated_items = paginator.page(request.GET.get('page', 1)) + except PageNotAnInteger: + paginated_items = paginator.page(1) + except EmptyPage: + paginated_items = paginator.page(paginator.num_pages) + + + +## ... source file abbreviated to get to helpers examples ... + + + self.log_deletion(request, f, force_text(f)) + f.delete() + self.message_user(request, _("Successfully deleted %(count)d files and/or folders.") % {"count": n, }) + return None + + if all_perms_needed or all_protected: + title = _("Cannot delete files and/or folders") + else: + title = _("Are you sure?") + + context = self.admin_site.each_context(request) + context.update({ + "title": title, + "instance": current_folder, + "breadcrumbs_action": _("Delete files and/or folders"), + "deletable_objects": all_deletable_objects, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": all_perms_needed, + "protected": all_protected, + "opts": opts, + 'is_popup': popup_status(request), + 'filer_admin_context': AdminContext(request), + "root_path": reverse('admin:index'), + "app_label": app_label, +~~ "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + }) + + return render( + request, + "admin/filer/delete_selected_files_confirmation.html", + context + ) + + delete_files_or_folders.short_description = ugettext_lazy( + "Delete selected files and/or folders") + + def _format_callback(self, obj, user, admin_site, perms_needed): + has_admin = obj.__class__ in admin_site._registry + opts = obj._meta + if has_admin: + admin_url = reverse('%s:%s_%s_change' + % (admin_site.name, + opts.app_label, + opts.object_name.lower()), + None, (quote(obj._get_pk_val()),)) + p = get_delete_permission(opts) + if not user.has_perm(p): + perms_needed.add(opts.verbose_name) + return mark_safe('%s: %s' % + + +## ... source file abbreviated to get to helpers examples ... + + + conflicting_names = [folder.name for folder in self.get_queryset(request).filter(parent=destination, name__in=folders_queryset.values('name'))] + if conflicting_names: + messages.error(request, _("Folders with names %s already exist at the selected " + "destination") % ", ".join(conflicting_names)) + elif n: + self._move_files_and_folders_impl(files_queryset, folders_queryset, destination) + self.message_user(request, _("Successfully moved %(count)d files and/or folders to folder '%(destination)s'.") % { + "count": n, + "destination": destination, + }) + return None + + context = self.admin_site.each_context(request) + context.update({ + "title": _("Move files and/or folders"), + "instance": current_folder, + "breadcrumbs_action": _("Move files and/or folders"), + "to_move": to_move, + "destination_folders": folders, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": perms_needed, + "opts": opts, + "root_path": reverse('admin:index'), + "app_label": app_label, +~~ "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + }) + + return render(request, "admin/filer/folder/choose_move_destination.html", context) + + move_files_and_folders.short_description = ugettext_lazy("Move selected files and/or folders") + + def _rename_file(self, file_obj, form_data, counter, global_counter): + original_basename, original_extension = os.path.splitext(file_obj.original_filename) + if file_obj.name: + current_basename, current_extension = os.path.splitext(file_obj.name) + else: + current_basename = "" + current_extension = "" + file_obj.name = form_data['rename_format'] % { + 'original_filename': file_obj.original_filename, + 'original_basename': original_basename, + 'original_extension': original_extension, + 'current_filename': file_obj.name or "", + 'current_basename': current_basename, + 'current_extension': current_extension, + 'current_folder': getattr(file_obj.folder, 'name', ''), + 'counter': counter + 1, # 1-based + 'global_counter': global_counter + 1, # 1-based + } + + +## ... source file abbreviated to get to helpers examples ... + + + raise PermissionDenied + form = RenameFilesForm(request.POST) + if form.is_valid(): + if files_queryset.count() + folders_queryset.count(): + n = self._rename_files_impl(files_queryset, folders_queryset, form.cleaned_data, 0) + self.message_user(request, _("Successfully renamed %(count)d files.") % { + "count": n, + }) + return None + else: + form = RenameFilesForm() + + context = self.admin_site.each_context(request) + context.update({ + "title": _("Rename files"), + "instance": current_folder, + "breadcrumbs_action": _("Rename files"), + "to_rename": to_rename, + "rename_form": form, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": perms_needed, + "opts": opts, + "root_path": reverse('admin:index'), + "app_label": app_label, +~~ "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + }) + + return render(request, "admin/filer/folder/choose_rename_format.html", context) + + rename_files.short_description = ugettext_lazy("Rename files") + + def _generate_new_filename(self, filename, suffix): + basename, extension = os.path.splitext(filename) + return basename + suffix + extension + + def _copy_file(self, file_obj, destination, suffix, overwrite): + if overwrite: + raise NotImplementedError + + + filename = self._generate_new_filename(file_obj.file.name, suffix) + + file_obj.pk = None + file_obj.id = None + file_obj.save() + file_obj.folder = destination + file_obj._file_data_changed_hint = False # no need to update size, sha1, etc. + file_obj.file = file_obj._copy_file(filename) + file_obj.original_filename = self._generate_new_filename(file_obj.original_filename, suffix) + + +## ... source file abbreviated to get to helpers examples ... + + + form = CopyFilesAndFoldersForm() + + try: + selected_destination_folder = int(request.POST.get('destination', 0)) + except ValueError: + if current_folder: + selected_destination_folder = current_folder.pk + else: + selected_destination_folder = 0 + + context = self.admin_site.each_context(request) + context.update({ + "title": _("Copy files and/or folders"), + "instance": current_folder, + "breadcrumbs_action": _("Copy files and/or folders"), + "to_copy": to_copy, + "destination_folders": folders, + "selected_destination_folder": selected_destination_folder, + "copy_form": form, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": perms_needed, + "opts": opts, + "root_path": reverse('admin:index'), + "app_label": app_label, +~~ "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + }) + + return render(request, "admin/filer/folder/choose_copy_destination.html", context) + + copy_files_and_folders.short_description = ugettext_lazy("Copy selected files and/or folders") + + def _check_resize_perms(self, request, files_queryset, folders_queryset): + try: + check_files_read_permissions(request, files_queryset) + check_folder_read_permissions(request, folders_queryset) + check_files_edit_permissions(request, files_queryset) + except PermissionDenied: + return True + return False + + def _list_folders_to_resize(self, request, folders): + for fo in folders: + children = list(self._list_folders_to_resize(request, fo.children.all())) + children.extend([self._format_callback(f, request.user, self.admin_site, set()) for f in sorted(fo.files) if isinstance(f, Image)]) + if children: + yield self._format_callback(fo, request.user, self.admin_site, set()) + yield children + + def _list_all_to_resize(self, request, files_queryset, folders_queryset): + + +## ... source file abbreviated to get to helpers examples ... + + + form.cleaned_data['width'] = form.cleaned_data['thumbnail_option'].width + form.cleaned_data['height'] = form.cleaned_data['thumbnail_option'].height + form.cleaned_data['crop'] = form.cleaned_data['thumbnail_option'].crop + form.cleaned_data['upscale'] = form.cleaned_data['thumbnail_option'].upscale + if files_queryset.count() + folders_queryset.count(): + n = self._resize_images_impl(files_queryset, folders_queryset, form.cleaned_data) + self.message_user(request, _("Successfully resized %(count)d images.") % {"count": n, }) + return None + else: + form = ResizeImagesForm() + + context = self.admin_site.each_context(request) + context.update({ + "title": _("Resize images"), + "instance": current_folder, + "breadcrumbs_action": _("Resize images"), + "to_resize": to_resize, + "resize_form": form, + "cmsplugin_enabled": 'cmsplugin_filer_image' in django_settings.INSTALLED_APPS, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": perms_needed, + "opts": opts, + "root_path": reverse('admin:index'), + "app_label": app_label, +~~ "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + }) + + return render(request, "admin/filer/folder/choose_images_resize_options.html", context) + + resize_images.short_description = ugettext_lazy("Resize selected images") + + + +## ... source file continues with no further helpers examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-admin-options-csrf-protect-m.markdown b/content/pages/examples/django/django-contrib-admin-options-csrf-protect-m.markdown new file mode 100644 index 000000000..334ae0b80 --- /dev/null +++ b/content/pages/examples/django/django-contrib-admin-options-csrf-protect-m.markdown @@ -0,0 +1,116 @@ +title: django.contrib.admin.options csrf_protect_m code examples +category: page +slug: django-contrib-admin-options-csrf-protect-m-examples +sortorder: 500011025 +toc: False +sidebartitle: django.contrib.admin.options csrf_protect_m +meta: Python example code for the csrf_protect_m function from the django.contrib.admin.options module of the Django project. + + +csrf_protect_m is a function within the django.contrib.admin.options module of the Django project. + + +## Example 1 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / admin.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./admin.py) + +```python +# admin.py +~~from django.contrib.admin.options import ModelAdmin, csrf_protect_m +from django.contrib.admin.views.main import SEARCH_VAR, ChangeList +from django.core.exceptions import PermissionDenied +from django.core.paginator import InvalidPage, Paginator +from django.shortcuts import render +from django.utils.encoding import force_str +from django.utils.translation import ungettext + +from haystack import connections +from haystack.constants import DEFAULT_ALIAS +from haystack.query import SearchQuerySet +from haystack.utils import get_model_ct_tuple + + +class SearchChangeList(ChangeList): + def __init__(self, **kwargs): + self.haystack_connection = kwargs.pop("haystack_connection", DEFAULT_ALIAS) + super(SearchChangeList, self).__init__(**kwargs) + + def get_results(self, request): + if SEARCH_VAR not in request.GET: + return super(SearchChangeList, self).get_results(request) + + sqs = ( + SearchQuerySet(self.haystack_connection) + + +## ... source file abbreviated to get to csrf_protect_m examples ... + + + result_count = paginator.count + full_result_count = ( + SearchQuerySet(self.haystack_connection).models(self.model).all().count() + ) + + can_show_all = result_count <= self.list_max_show_all + multi_page = result_count > self.list_per_page + + try: + result_list = paginator.page(self.page_num + 1).object_list + result_list = [result.object for result in result_list] + except InvalidPage: + result_list = () + + self.result_count = result_count + self.full_result_count = full_result_count + self.result_list = result_list + self.can_show_all = can_show_all + self.multi_page = multi_page + self.paginator = paginator + + +class SearchModelAdminMixin(object): + haystack_connection = DEFAULT_ALIAS + +~~ @csrf_protect_m + def changelist_view(self, request, extra_context=None): + if not self.has_change_permission(request, None): + raise PermissionDenied + + if SEARCH_VAR not in request.GET: + return super(SearchModelAdminMixin, self).changelist_view( + request, extra_context + ) + + indexed_models = ( + connections[self.haystack_connection] + .get_unified_index() + .get_indexed_models() + ) + + if self.model not in indexed_models: + return super(SearchModelAdminMixin, self).changelist_view( + request, extra_context + ) + + list_display = list(self.list_display) + + kwargs = { + "haystack_connection": self.haystack_connection, + + +## ... source file continues with no further csrf_protect_m examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-admin-options-incorrectlookupparameters.markdown b/content/pages/examples/django/django-contrib-admin-options-incorrectlookupparameters.markdown new file mode 100644 index 000000000..56d6cf44e --- /dev/null +++ b/content/pages/examples/django/django-contrib-admin-options-incorrectlookupparameters.markdown @@ -0,0 +1,137 @@ +title: django.contrib.admin.options IncorrectLookupParameters code examples +category: page +slug: django-contrib-admin-options-incorrectlookupparameters-examples +sortorder: 500011023 +toc: False +sidebartitle: django.contrib.admin.options IncorrectLookupParameters +meta: Python example code for the IncorrectLookupParameters class from the django.contrib.admin.options module of the Django project. + + +IncorrectLookupParameters is a class within the django.contrib.admin.options module of the Django project. + + +## Example 1 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / utils.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./utils.py) + +```python +# utils.py +from django.template import Context +from django.utils import translation +from jet import settings +from jet.models import PinnedApplication + +try: + from django.apps.registry import apps +except ImportError: + try: + from django.apps import apps # Fix Django 1.7 import issue + except ImportError: + pass +from django.core.serializers.json import DjangoJSONEncoder +from django.http import HttpResponse +try: + from django.core.urlresolvers import reverse, resolve, NoReverseMatch +except ImportError: # Django 1.11 + from django.urls import reverse, resolve, NoReverseMatch + +from django.contrib.admin import AdminSite +from django.utils.encoding import smart_text +from django.utils.text import capfirst +from django.contrib import messages +from django.utils.encoding import force_text +from django.utils.functional import Promise +~~from django.contrib.admin.options import IncorrectLookupParameters +from django.contrib import admin +from django.utils.translation import ugettext_lazy as _ +from django.utils.text import slugify + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # Python 2.6 + + +class JsonResponse(HttpResponse): + + def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs): + if safe and not isinstance(data, dict): + raise TypeError('In order to allow non-dict objects to be ' + 'serialized set the safe parameter to False') + kwargs.setdefault('content_type', 'application/json') + data = json.dumps(data, cls=encoder) + super(JsonResponse, self).__init__(content=data, **kwargs) + + +def get_app_list(context, order=True): + admin_site = get_admin_site(context) + request = context['request'] + + +## ... source file abbreviated to get to IncorrectLookupParameters examples ... + + + if hasattr(model_admin, 'get_search_fields') else model_admin.search_fields + list_select_related = model_admin.get_list_select_related(request) \ + if hasattr(model_admin, 'get_list_select_related') else model_admin.list_select_related + + actions = model_admin.get_actions(request) + if actions: + list_display = ['action_checkbox'] + list(list_display) + + ChangeList = model_admin.get_changelist(request) + + change_list_args = [ + request, model, list_display, list_display_links, list_filter, + model_admin.date_hierarchy, search_fields, list_select_related, + model_admin.list_per_page, model_admin.list_max_show_all, + model_admin.list_editable, model_admin] + + try: + sortable_by = model_admin.get_sortable_by(request) + change_list_args.append(sortable_by) + except AttributeError: + pass + + try: + cl = ChangeList(*change_list_args) + queryset = cl.get_queryset(request) +~~ except IncorrectLookupParameters: + pass + + return queryset + + +def get_possible_language_codes(): + language_code = translation.get_language() + + language_code = language_code.replace('_', '-').lower() + language_codes = [] + + split = language_code.split('-', 2) + if len(split) == 2: + language_code = '%s-%s' % (split[0].lower(), split[1].upper()) if split[0] != split[1] else split[0] + + language_codes.append(language_code) + + if len(split) == 2: + language_codes.append(split[0].lower()) + + return language_codes + + +def get_original_menu_items(context): + + +## ... source file continues with no further IncorrectLookupParameters examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-admin-options-is-popup-var.markdown b/content/pages/examples/django/django-contrib-admin-options-is-popup-var.markdown new file mode 100644 index 000000000..d19f241c2 --- /dev/null +++ b/content/pages/examples/django/django-contrib-admin-options-is-popup-var.markdown @@ -0,0 +1,154 @@ +title: django.contrib.admin.options IS_POPUP_VAR code examples +category: page +slug: django-contrib-admin-options-is-popup-var-examples +sortorder: 500011022 +toc: False +sidebartitle: django.contrib.admin.options IS_POPUP_VAR +meta: Python example code for the IS_POPUP_VAR class from the django.contrib.admin.options module of the Django project. + + +IS_POPUP_VAR is a class within the django.contrib.admin.options module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / admin / pageadmin.py**](https://github.com/divio/django-cms/blob/develop/cms/admin/pageadmin.py) + +```python +# pageadmin.py +from collections import namedtuple +import copy +import json +import sys +import uuid + + +import django +from django.contrib.admin.helpers import AdminForm +from django.conf import settings +from django.conf.urls import url +from django.contrib import admin, messages +from django.contrib.admin.models import LogEntry, CHANGE +~~from django.contrib.admin.options import IS_POPUP_VAR +from django.contrib.admin.utils import get_deleted_objects +from django.contrib.contenttypes.models import ContentType +from django.contrib.sites.models import Site +from django.core.exceptions import (ObjectDoesNotExist, + PermissionDenied, ValidationError) +from django.db import router, transaction +from django.db.models import Q, Prefetch +from django.http import ( + HttpResponseRedirect, + HttpResponse, + Http404, + HttpResponseBadRequest, + HttpResponseForbidden, +) +from django.shortcuts import render, get_object_or_404 +from django.template.defaultfilters import escape +from django.template.loader import get_template +from django.template.response import SimpleTemplateResponse, TemplateResponse +from django.utils.encoding import force_text +from django.utils.translation import ugettext, ugettext_lazy as _, get_language +from django.utils.decorators import method_decorator +from django.views.decorators.http import require_POST +from django.http import QueryDict + + + +## ... source file continues with no further IS_POPUP_VAR examples... + +``` + + +## Example 2 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / tools.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/tools.py) + +```python +# tools.py +from __future__ import absolute_import, unicode_literals + +~~from django.contrib.admin.options import IS_POPUP_VAR +from django.core.exceptions import PermissionDenied +from django.utils.http import urlencode + + +ALLOWED_PICK_TYPES = ('folder', 'file') + + +def check_files_edit_permissions(request, files): + for f in files: + if not f.has_edit_permission(request): + raise PermissionDenied + + +def check_folder_edit_permissions(request, folders): + for f in folders: + if not f.has_edit_permission(request): + raise PermissionDenied + check_files_edit_permissions(request, f.files) + check_folder_edit_permissions(request, f.children.all()) + + +def check_files_read_permissions(request, files): + for f in files: + if not f.has_read_permission(request): + + +## ... source file abbreviated to get to IS_POPUP_VAR examples ... + + + params = params or {} + if popup_status(request): + params[IS_POPUP_VAR] = '1' + pick_type = popup_pick_type(request) + if pick_type: + params['_pick'] = pick_type + return params + + +def admin_url_params_encoded(request, first_separator='?', params=None): + params = urlencode( + sorted(admin_url_params(request, params=params).items()) + ) + if not params: + return '' + return '{0}{1}'.format(first_separator, params) + + +class AdminContext(dict): + def __init__(self, request): + super(AdminContext, self).__init__() + self.update(admin_url_params(request)) + + def __missing__(self, key): + if key == 'popup': +~~ return self.get(IS_POPUP_VAR, False) == '1' + elif key == 'pick': + return self.get('_pick', '') + elif key.startswith('pick_'): + return self.get('_pick', '') == key.split('pick_')[1] + + def __getattr__(self, name): + if name in ('popup', 'pick') or name.startswith('pick_'): + return self.get(name) + raise AttributeError + + + +## ... source file continues with no further IS_POPUP_VAR examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-admin-options-modeladmin.markdown b/content/pages/examples/django/django-contrib-admin-options-modeladmin.markdown new file mode 100644 index 000000000..93bd414bf --- /dev/null +++ b/content/pages/examples/django/django-contrib-admin-options-modeladmin.markdown @@ -0,0 +1,94 @@ +title: django.contrib.admin.options ModelAdmin code examples +category: page +slug: django-contrib-admin-options-modeladmin-examples +sortorder: 500011024 +toc: False +sidebartitle: django.contrib.admin.options ModelAdmin +meta: Python example code for the ModelAdmin class from the django.contrib.admin.options module of the Django project. + + +ModelAdmin is a class within the django.contrib.admin.options module of the Django project. + + +## Example 1 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / admin.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./admin.py) + +```python +# admin.py +~~from django.contrib.admin.options import ModelAdmin, csrf_protect_m +from django.contrib.admin.views.main import SEARCH_VAR, ChangeList +from django.core.exceptions import PermissionDenied +from django.core.paginator import InvalidPage, Paginator +from django.shortcuts import render +from django.utils.encoding import force_str +from django.utils.translation import ungettext + +from haystack import connections +from haystack.constants import DEFAULT_ALIAS +from haystack.query import SearchQuerySet +from haystack.utils import get_model_ct_tuple + + +class SearchChangeList(ChangeList): + def __init__(self, **kwargs): + self.haystack_connection = kwargs.pop("haystack_connection", DEFAULT_ALIAS) + super(SearchChangeList, self).__init__(**kwargs) + + def get_results(self, request): + if SEARCH_VAR not in request.GET: + return super(SearchChangeList, self).get_results(request) + + sqs = ( + SearchQuerySet(self.haystack_connection) + + +## ... source file abbreviated to get to ModelAdmin examples ... + + + "cl": changelist, + "media": media, + "has_add_permission": self.has_add_permission(request), + "opts": changelist.opts, + "app_label": self.model._meta.app_label, + "action_form": action_form, + "actions_on_top": self.actions_on_top, + "actions_on_bottom": self.actions_on_bottom, + "actions_selection_counter": getattr(self, "actions_selection_counter", 0), + } + context.update(extra_context or {}) + request.current_app = self.admin_site.name + app_name, model_name = get_model_ct_tuple(self.model) + return render( + request, + self.change_list_template + or [ + "admin/%s/%s/change_list.html" % (app_name, model_name), + "admin/%s/change_list.html" % app_name, + "admin/change_list.html", + ], + context, + ) + + +~~class SearchModelAdmin(SearchModelAdminMixin, ModelAdmin): + pass + + + +## ... source file continues with no further ModelAdmin examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-admin-sites-notregistered.markdown b/content/pages/examples/django/django-contrib-admin-sites-notregistered.markdown new file mode 100644 index 000000000..731cd623b --- /dev/null +++ b/content/pages/examples/django/django-contrib-admin-sites-notregistered.markdown @@ -0,0 +1,66 @@ +title: django.contrib.admin.sites NotRegistered code examples +category: page +slug: django-contrib-admin-sites-notregistered-examples +sortorder: 500011026 +toc: False +sidebartitle: django.contrib.admin.sites NotRegistered +meta: Python example code for the NotRegistered class from the django.contrib.admin.sites module of the Django project. + + +NotRegistered is a class within the django.contrib.admin.sites module of the Django project. + + +## Example 1 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / admin.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./admin.py) + +```python +# admin.py +from typing import Tuple, Type, Optional + +from django import forms +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import admin +from django.contrib import messages +~~from django.contrib.admin.sites import NotRegistered +from django.http import HttpResponseRedirect, HttpRequest, HttpResponse +from django.urls import get_urlconf, get_resolver +from django.utils.translation import gettext_lazy as _ + +from .fields import TreeItemChoiceField +from .settings import MODEL_TREE, MODEL_TREE_ITEM +from .utils import get_tree_model, get_tree_item_model, get_app_n_model + +if False: # pragma: nocover + from .models import TreeItemBase, TreeBase # noqa + + +SMUGGLER_INSTALLED = 'smuggler' in django_settings.INSTALLED_APPS + +MODEL_TREE_CLASS = get_tree_model() +MODEL_TREE_ITEM_CLASS = get_tree_item_model() + +_TREE_ADMIN = lambda: TreeAdmin +_ITEM_ADMIN = lambda: TreeItemAdmin + + +def get_model_url_name(model_nfo: Tuple[str, str], page: str, with_namespace: bool = False) -> str: + prefix = '' + if with_namespace: + + +## ... source file continues with no further NotRegistered examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-admin-sites-site.markdown b/content/pages/examples/django/django-contrib-admin-sites-site.markdown new file mode 100644 index 000000000..2aabe9df0 --- /dev/null +++ b/content/pages/examples/django/django-contrib-admin-sites-site.markdown @@ -0,0 +1,290 @@ +title: django.contrib.admin.sites site code examples +category: page +slug: django-contrib-admin-sites-site-examples +sortorder: 500011027 +toc: False +sidebartitle: django.contrib.admin.sites site +meta: Python example code for the site function from the django.contrib.admin.sites module of the Django project. + + +site is a function within the django.contrib.admin.sites module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / tests / test_admin.py**](https://github.com/divio/django-cms/blob/develop/cms/tests/test_admin.py) + +```python +# test_admin.py +import json +import datetime + +from djangocms_text_ckeditor.cms_plugins import TextPlugin +from djangocms_text_ckeditor.models import Text +from django.contrib import admin +from django.contrib.admin.models import LogEntry +~~from django.contrib.admin.sites import site +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Permission +from django.contrib.sites.models import Site +from django.urls import reverse +from django.http import (Http404, HttpResponseBadRequest, + HttpResponseNotFound) +from django.utils.encoding import force_text, smart_str +from django.utils import timezone + +from cms import api +from cms.api import create_page, create_title, add_plugin, publish_page +from cms.admin.pageadmin import PageAdmin +from cms.constants import TEMPLATE_INHERITANCE_MAGIC +from cms.models import StaticPlaceholder +from cms.models.pagemodel import Page, PageType +from cms.models.permissionmodels import GlobalPagePermission, PagePermission +from cms.models.placeholdermodel import Placeholder +from cms.models.pluginmodel import CMSPlugin +from cms.models.titlemodels import Title +from cms.test_utils import testcases as base +from cms.test_utils.testcases import ( + CMSTestCase, URL_CMS_PAGE_DELETE, URL_CMS_PAGE,URL_CMS_TRANSLATION_DELETE, + URL_CMS_PAGE_CHANGE_LANGUAGE, URL_CMS_PAGE_CHANGE, + URL_CMS_PAGE_PUBLISHED, +) +from cms.utils.conf import get_cms_setting +from cms.utils.urlutils import admin_reverse + + +class AdminTestsBase(CMSTestCase): + @property + def admin_class(self): +~~ return site._registry[Page] + + def _get_guys(self, admin_only=False, use_global_permissions=True): + admin_user = self.get_superuser() + + if admin_only: + return admin_user + staff_user = self._get_staff_user(use_global_permissions) + return admin_user, staff_user + + def _get_staff_user(self, use_global_permissions=True): + USERNAME = 'test' + + if get_user_model().USERNAME_FIELD == 'email': + normal_guy = get_user_model().objects.create_user(USERNAME, 'test@test.com', 'test@test.com') + else: + normal_guy = get_user_model().objects.create_user(USERNAME, 'test@test.com', USERNAME) + + normal_guy.is_staff = True + normal_guy.is_active = True + perms = Permission.objects.filter( + codename__in=['change_page', 'change_title', 'add_page', 'add_title', 'delete_page', 'delete_title'] + ) + normal_guy.save() + normal_guy.user_permissions.set(perms) + if use_global_permissions: + gpp = GlobalPagePermission.objects.create( + user=normal_guy, + can_change=True, + can_delete=True, + can_change_advanced_settings=False, + can_publish=True, + can_change_permissions=False, + can_move_page=True, + ) + gpp.sites.set(Site.objects.all()) + return normal_guy + + +class AdminTestCase(AdminTestsBase): + + def test_extension_not_in_admin(self): + admin_user, staff = self._get_guys() + with self.login_user_context(admin_user): + request = self.get_request(URL_CMS_PAGE_CHANGE % 1, 'en',) +~~ response = site.index(request) + self.assertNotContains(response, '/mytitleextension/') + self.assertNotContains(response, '/mypageextension/') + + def test_2apphooks_with_same_namespace(self): + PAGE1 = 'Test Page' + PAGE2 = 'Test page 2' + APPLICATION_URLS = 'project.sampleapp.urls' + + admin_user, normal_guy = self._get_guys() + + current_site = Site.objects.get(pk=1) + + page = create_page(PAGE1, "nav_playground.html", "en", + site=current_site, created_by=admin_user) + page2 = create_page(PAGE2, "nav_playground.html", "en", + site=current_site, created_by=admin_user) + + page.application_urls = APPLICATION_URLS + page.application_namespace = "space1" + page.save() + page2.application_urls = APPLICATION_URLS + page2.save() + + page_data = { + + +## ... source file abbreviated to get to site examples ... + + + admin_user = self.get_superuser() + create_page("home", "nav_playground.html", "en", + created_by=admin_user, published=True) + page = create_page("delete-page", "nav_playground.html", "en", + created_by=admin_user, published=True) + create_page('child-page', "nav_playground.html", "de", + created_by=admin_user, published=True, parent=page) + body = page.placeholders.get(slot='body') + add_plugin(body, 'TextPlugin', 'en', body='text') + page.publish('en') + with self.login_user_context(admin_user): + data = {'post': 'yes'} + response = self.client.post(URL_CMS_PAGE_DELETE % page.pk, data) + self.assertRedirects(response, URL_CMS_PAGE) + + def test_search_fields(self): + superuser = self.get_superuser() + from django.contrib.admin import site + + with self.login_user_context(superuser): +~~ for model, admin_instance in site._registry.items(): + if model._meta.app_label != 'cms': + continue + if not admin_instance.search_fields: + continue + url = admin_reverse('cms_%s_changelist' % model._meta.model_name) + response = self.client.get('%s?q=1' % url) + errmsg = response.content + self.assertEqual(response.status_code, 200, errmsg) + + def test_pagetree_filtered(self): + superuser = self.get_superuser() + create_page("root-page", "nav_playground.html", "en", + created_by=superuser, published=True) + with self.login_user_context(superuser): + url = admin_reverse('cms_page_changelist') + response = self.client.get('%s?template__exact=nav_playground.html' % url) + errmsg = response.content + self.assertEqual(response.status_code, 200, errmsg) + + def test_delete_translation(self): + admin_user = self.get_superuser() + page = create_page("delete-page-translation", "nav_playground.html", "en", + created_by=admin_user, published=True) + create_title("de", "delete-page-translation-2", page, slug="delete-page-translation-2") + + +## ... source file abbreviated to get to site examples ... + + + page_admin = PageAdmin(Page, None) + page_admin._current_page = page + page.publish("en") + draft_page = page.get_draft_object() + admin_url = reverse("admin:cms_page_edit_title_fields", args=( + draft_page.pk, language + )) + + post_data = { + 'title': "A Title" + } + with self.login_user_context(admin_user): + self.client.post(admin_url, post_data) + draft_page = Page.objects.get(pk=page.pk).get_draft_object() + self.assertTrue(draft_page.is_dirty('en')) + + +class NoDBAdminTests(CMSTestCase): + @property + def admin_class(self): +~~ return site._registry[Page] + + def test_lookup_allowed_site__exact(self): + self.assertTrue(self.admin_class.lookup_allowed('site__exact', '1')) + + def test_lookup_allowed_published(self): + self.assertTrue(self.admin_class.lookup_allowed('published', value='1')) + + +class PluginPermissionTests(AdminTestsBase): + def setUp(self): + self._page = create_page('test page', 'nav_playground.html', 'en') + self._placeholder = self._page.placeholders.all()[0] + + def _get_admin(self): + User = get_user_model() + + fields = dict(email="admin@django-cms.org", is_staff=True, is_active=True) + + if (User.USERNAME_FIELD != 'email'): + fields[User.USERNAME_FIELD] = "admin" + + admin_user = User(**fields) + + admin_user.set_password('admin') + + +## ... source file abbreviated to get to site examples ... + + + page2_data = { + 'reverse_id': 'p1', + 'template': 'col_two.html', + } + + with self.login_user_context(superuser): + response = self.client.post(page2_endpoint, page2_data) + expected_error = ( + '
    ' + '
  • A page with this reverse URL id exists already.
' + ) + self.assertEqual(response.status_code, 200) + self.assertContains(response, expected_error.format(page2.pk), html=True) + + def test_advanced_settings_endpoint(self): + admin_user = self.get_superuser() + site = Site.objects.get_current() + page = create_page('Page 1', 'nav_playground.html', 'en') + page_data = { + 'language': 'en', +~~ 'site': site.pk, + 'template': 'col_two.html', + } + path = admin_reverse('cms_page_advanced', args=(page.pk,)) + + with self.login_user_context(admin_user): + en_path = path + u"?language=en" + redirect_path = admin_reverse('cms_page_changelist') + '?language=en' + response = self.client.post(en_path, page_data) + self.assertRedirects(response, redirect_path) + self.assertEqual(Page.objects.get(pk=page.pk).template, 'col_two.html') + + page_data['language'] = 'de' + page_data['template'] = 'nav_playground.html' + + with self.login_user_context(admin_user): + de_path = path + u"?language=de" + redirect_path = admin_reverse('cms_page_change', args=(page.pk,)) + '?language=de' + response = self.client.post(de_path, page_data) + self.assertRedirects(response, redirect_path) + self.assertEqual(Page.objects.get(pk=page.pk).template, 'col_two.html') + + de_translation = create_title('de', title='Page 1', page=page.reload()) + de_translation.slug = '' + de_translation.save() + + +## ... source file continues with no further site examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-finders-basefinder.markdown b/content/pages/examples/django/django-contrib-staticfiles-finders-basefinder.markdown new file mode 100644 index 000000000..92766a9a8 --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-finders-basefinder.markdown @@ -0,0 +1,100 @@ +title: django.contrib.staticfiles.finders BaseFinder Example Code +category: page +slug: django-contrib-staticfiles-finders-basefinder-examples +sortorder: 500011067 +toc: False +sidebartitle: django.contrib.staticfiles.finders BaseFinder +meta: Python example code for the BaseFinder class from the django.contrib.staticfiles.finders module of the Django project. + + +BaseFinder is a class within the django.contrib.staticfiles.finders module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / finders.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./finders.py) + +```python +# finders.py +from itertools import chain + +from django.contrib.staticfiles.storage import staticfiles_storage +~~from django.contrib.staticfiles.finders import BaseFinder, BaseStorageFinder, find, \ + AppDirectoriesFinder as DjangoAppDirectoriesFinder, FileSystemFinder as DjangoFileSystemFinder +from django.utils._os import safe_join +from os.path import normpath + +from pipeline.conf import settings + + +class PipelineFinder(BaseStorageFinder): + storage = staticfiles_storage + + def find(self, path, all=False): + if not settings.PIPELINE_ENABLED: + return super(PipelineFinder, self).find(path, all) + else: + return [] + + def list(self, ignore_patterns): + return [] + + +~~class ManifestFinder(BaseFinder): + def find(self, path, all=False): + matches = [] + for elem in chain(settings.STYLESHEETS.values(), settings.JAVASCRIPT.values()): + if normpath(elem['output_filename']) == normpath(path): + match = safe_join(settings.PIPELINE_ROOT, path) + if not all: + return match + matches.append(match) + return matches + + def list(self, *args): + return [] + + +~~class CachedFileFinder(BaseFinder): + def find(self, path, all=False): + try: + start, _, extn = path.rsplit('.', 2) + except ValueError: + return [] + path = '.'.join((start, extn)) + return find(path, all=all) or [] + + def list(self, *args): + return [] + + +class PatternFilterMixin(object): + ignore_patterns = [] + + def get_ignored_patterns(self): + return list(set(self.ignore_patterns)) + + def list(self, ignore_patterns): + if ignore_patterns: + ignore_patterns = ignore_patterns + self.get_ignored_patterns() + return super(PatternFilterMixin, self).list(ignore_patterns) + + + + +## ... source file continues with no further BaseFinder examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-finders-basestoragefinder.markdown b/content/pages/examples/django/django-contrib-staticfiles-finders-basestoragefinder.markdown new file mode 100644 index 000000000..799b108ed --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-finders-basestoragefinder.markdown @@ -0,0 +1,72 @@ +title: django.contrib.staticfiles.finders BaseStorageFinder Example Code +category: page +slug: django-contrib-staticfiles-finders-basestoragefinder-examples +sortorder: 500011068 +toc: False +sidebartitle: django.contrib.staticfiles.finders BaseStorageFinder +meta: Python example code for the BaseStorageFinder class from the django.contrib.staticfiles.finders module of the Django project. + + +BaseStorageFinder is a class within the django.contrib.staticfiles.finders module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / finders.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./finders.py) + +```python +# finders.py +from itertools import chain + +from django.contrib.staticfiles.storage import staticfiles_storage +~~from django.contrib.staticfiles.finders import BaseFinder, BaseStorageFinder, find, \ + AppDirectoriesFinder as DjangoAppDirectoriesFinder, FileSystemFinder as DjangoFileSystemFinder +from django.utils._os import safe_join +from os.path import normpath + +from pipeline.conf import settings + + +~~class PipelineFinder(BaseStorageFinder): + storage = staticfiles_storage + + def find(self, path, all=False): + if not settings.PIPELINE_ENABLED: + return super(PipelineFinder, self).find(path, all) + else: + return [] + + def list(self, ignore_patterns): + return [] + + +class ManifestFinder(BaseFinder): + def find(self, path, all=False): + matches = [] + for elem in chain(settings.STYLESHEETS.values(), settings.JAVASCRIPT.values()): + if normpath(elem['output_filename']) == normpath(path): + match = safe_join(settings.PIPELINE_ROOT, path) + if not all: + return match + matches.append(match) + return matches + + def list(self, *args): + + +## ... source file continues with no further BaseStorageFinder examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-finders-find.markdown b/content/pages/examples/django/django-contrib-staticfiles-finders-find.markdown new file mode 100644 index 000000000..c30f933a5 --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-finders-find.markdown @@ -0,0 +1,107 @@ +title: django.contrib.staticfiles.finders find Example Code +category: page +slug: django-contrib-staticfiles-finders-find-examples +sortorder: 500011069 +toc: False +sidebartitle: django.contrib.staticfiles.finders find +meta: Python example code for the find callable from the django.contrib.staticfiles.finders module of the Django project. + + +find is a callable within the django.contrib.staticfiles.finders module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / finders.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./finders.py) + +```python +# finders.py +from itertools import chain + +from django.contrib.staticfiles.storage import staticfiles_storage +~~from django.contrib.staticfiles.finders import BaseFinder, BaseStorageFinder, find, \ + AppDirectoriesFinder as DjangoAppDirectoriesFinder, FileSystemFinder as DjangoFileSystemFinder +from django.utils._os import safe_join +from os.path import normpath + +from pipeline.conf import settings + + +class PipelineFinder(BaseStorageFinder): + storage = staticfiles_storage + +~~ def find(self, path, all=False): + if not settings.PIPELINE_ENABLED: + return super(PipelineFinder, self).find(path, all) + else: + return [] + + def list(self, ignore_patterns): + return [] + + +class ManifestFinder(BaseFinder): +~~ def find(self, path, all=False): + matches = [] + for elem in chain(settings.STYLESHEETS.values(), settings.JAVASCRIPT.values()): + if normpath(elem['output_filename']) == normpath(path): + match = safe_join(settings.PIPELINE_ROOT, path) + if not all: + return match + matches.append(match) + return matches + + def list(self, *args): + return [] + + +class CachedFileFinder(BaseFinder): +~~ def find(self, path, all=False): + try: + start, _, extn = path.rsplit('.', 2) + except ValueError: + return [] + path = '.'.join((start, extn)) +~~ return find(path, all=all) or [] + + def list(self, *args): + return [] + + +class PatternFilterMixin(object): + ignore_patterns = [] + + def get_ignored_patterns(self): + return list(set(self.ignore_patterns)) + + def list(self, ignore_patterns): + if ignore_patterns: + ignore_patterns = ignore_patterns + self.get_ignored_patterns() + return super(PatternFilterMixin, self).list(ignore_patterns) + + +class AppDirectoriesFinder(PatternFilterMixin, DjangoAppDirectoriesFinder): + ignore_patterns = [ + '*.js', + '*.css', + '*.less', + '*.scss', + '*.styl', + + +## ... source file continues with no further find examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-finders-get-finders.markdown b/content/pages/examples/django/django-contrib-staticfiles-finders-get-finders.markdown new file mode 100644 index 000000000..fbc7b0457 --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-finders-get-finders.markdown @@ -0,0 +1,78 @@ +title: django.contrib.staticfiles.finders get_finders Example Code +category: page +slug: django-contrib-staticfiles-finders-get-finders-examples +sortorder: 500011070 +toc: False +sidebartitle: django.contrib.staticfiles.finders get_finders +meta: Python example code for the get_finders callable from the django.contrib.staticfiles.finders module of the Django project. + + +get_finders is a callable within the django.contrib.staticfiles.finders module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / manifest.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./manifest.py) + +```python +# manifest.py +import os + +from django.conf.settings import settings as django_settings +~~from django.contrib.staticfiles.finders import get_finders +from django.contrib.staticfiles.storage import staticfiles_storage + +from pipeline.conf import settings + +from manifesto import Manifest + +from pipeline.packager import Packager + + +class PipelineManifest(Manifest): + def __init__(self): + self.packager = Packager() + self.packages = self.collect_packages() +~~ self.finders = get_finders() + self.package_files = [] + + def collect_packages(self): + packages = [] + for package_name in self.packager.packages['css']: + package = self.packager.package_for('css', package_name) + if package.manifest: + packages.append(package) + for package_name in self.packager.packages['js']: + package = self.packager.package_for('js', package_name) + if package.manifest: + packages.append(package) + return packages + + def cache(self): + + if settings.PIPELINE_ENABLED: + for package in self.packages: + path = package.output_filename + self.package_files.append(path) + yield staticfiles_storage.url(path) + else: + for package in self.packages: + for path in self.packager.compile(package.paths): + + +## ... source file continues with no further get_finders examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-finders.markdown b/content/pages/examples/django/django-contrib-staticfiles-finders.markdown new file mode 100644 index 000000000..f86f42dcd --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-finders.markdown @@ -0,0 +1,232 @@ +title: django.contrib.staticfiles finders Example Code +category: page +slug: django-contrib-staticfiles-finders-examples +sortorder: 500011065 +toc: False +sidebartitle: django.contrib.staticfiles finders +meta: Python example code for the finders callable from the django.contrib.staticfiles module of the Django project. + + +finders is a callable within the django.contrib.staticfiles module of the Django project. + + +## Example 1 from django-debug-toolbar +[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar) +([project documentation](https://github.com/jazzband/django-debug-toolbar) +and [PyPI page](https://pypi.org/project/django-debug-toolbar/)) +grants a developer detailed request-response cycle information while +developing a [Django](/django.html) web application. +The code for django-debug-toolbar is +[open source](https://github.com/jazzband/django-debug-toolbar/blob/master/LICENSE) +and maintained by the developer community group known as +[Jazzband](https://jazzband.co/). + +[**django-debug-toolbar / debug_toolbar / panels / staticfiles.py**](https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/panels/staticfiles.py) + +```python +# staticfiles.py +from collections import OrderedDict +from os.path import join, normpath + +from django.conf import settings +~~from django.contrib.staticfiles import finders, storage +from django.core.files.storage import get_storage_class +from django.utils.functional import LazyObject +from django.utils.translation import gettext_lazy as _, ngettext as __ + +from debug_toolbar import panels +from debug_toolbar.utils import ThreadCollector + +try: + import threading +except ImportError: + threading = None + + +class StaticFile: + + def __init__(self, path): + self.path = path + + def __str__(self): + return self.path + + def real_path(self): +~~ return finders.find(self.path) + + def url(self): + return storage.staticfiles_storage.url(self.path) + + +class FileCollector(ThreadCollector): + def collect(self, path, thread=None): + if path.endswith("/"): + return + super().collect(StaticFile(path), thread) + + +collector = FileCollector() + + +class DebugConfiguredStorage(LazyObject): + + def _setup(self): + + configured_storage_cls = get_storage_class(settings.STATICFILES_STORAGE) + + class DebugStaticFilesStorage(configured_storage_cls): + def __init__(self, collector, *args, **kwargs): + super().__init__(*args, **kwargs) + + +## ... source file abbreviated to get to finders examples ... + + + return __("%(num_used)s file used", "%(num_used)s files used", num_used) % { + "num_used": num_used + } + + def process_request(self, request): + collector.clear_collection() + return super().process_request(request) + + def generate_stats(self, request, response): + used_paths = collector.get_collection() + self._paths[threading.currentThread()] = used_paths + + self.record_stats( + { + "num_found": self.num_found, + "num_used": self.num_used, + "staticfiles": used_paths, + "staticfiles_apps": self.get_staticfiles_apps(), + "staticfiles_dirs": self.get_staticfiles_dirs(), + "staticfiles_finders": self.get_staticfiles_finders(), + } + ) + + def get_staticfiles_finders(self): + finders_mapping = OrderedDict() +~~ for finder in finders.get_finders(): + for path, finder_storage in finder.list([]): + if getattr(finder_storage, "prefix", None): + prefixed_path = join(finder_storage.prefix, path) + else: + prefixed_path = path + finder_cls = finder.__class__ + finder_path = ".".join([finder_cls.__module__, finder_cls.__name__]) + real_path = finder_storage.path(path) + payload = (prefixed_path, real_path) + finders_mapping.setdefault(finder_path, []).append(payload) + self.num_found += 1 + return finders_mapping + + def get_staticfiles_dirs(self): + dirs = [] +~~ for finder in finders.get_finders(): +~~ if isinstance(finder, finders.FileSystemFinder): + dirs.extend(finder.locations) + return [(prefix, normpath(dir)) for prefix, dir in dirs] + + def get_staticfiles_apps(self): + apps = [] +~~ for finder in finders.get_finders(): +~~ if isinstance(finder, finders.AppDirectoriesFinder): + for app in finder.apps: + if app not in apps: + apps.append(app) + return apps + + + +## ... source file continues with no further finders examples... + +``` + + +## Example 2 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / collector.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./collector.py) + +```python +# collector.py +import os + +from collections import OrderedDict + +import django +~~from django.contrib.staticfiles import finders +from django.contrib.staticfiles.storage import staticfiles_storage + +from pipeline.finders import PipelineFinder + + +class Collector(object): + request = None + + def __init__(self, storage=None): + if storage is None: + storage = staticfiles_storage + self.storage = storage + + def _get_modified_time(self, storage, prefixed_path): + if django.VERSION[:2] >= (1, 10): + return storage.get_modified_time(prefixed_path) + return storage.modified_time(prefixed_path) + + def clear(self, path=""): + dirs, files = self.storage.listdir(path) + for f in files: + fpath = os.path.join(path, f) + self.storage.delete(fpath) + for d in dirs: + self.clear(os.path.join(path, d)) + + def collect(self, request=None, files=[]): + if self.request and self.request is request: + return + self.request = request + found_files = OrderedDict() +~~ for finder in finders.get_finders(): + if isinstance(finder, PipelineFinder): + continue + for path, storage in finder.list(['CVS', '.*', '*-']): + if getattr(storage, 'prefix', None): + prefixed_path = os.path.join(storage.prefix, path) + else: + prefixed_path = path + + if (prefixed_path not in found_files and + (not files or prefixed_path in files)): + found_files[prefixed_path] = (storage, path) + self.copy_file(path, prefixed_path, storage) + + if files and len(files) == len(found_files): + break + + return found_files.keys() + + def copy_file(self, path, prefixed_path, source_storage): + if not self.delete_file(path, prefixed_path, source_storage): + return + with source_storage.open(path) as source_file: + self.storage.save(prefixed_path, source_file) + + + +## ... source file continues with no further finders examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-handlers-staticfileshandler.markdown b/content/pages/examples/django/django-contrib-staticfiles-handlers-staticfileshandler.markdown new file mode 100644 index 000000000..b9aaa6a9e --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-handlers-staticfileshandler.markdown @@ -0,0 +1,107 @@ +title: django.contrib.staticfiles.handlers StaticFilesHandler Example Code +category: page +slug: django-contrib-staticfiles-handlers-staticfileshandler-examples +sortorder: 500011071 +toc: False +sidebartitle: django.contrib.staticfiles.handlers StaticFilesHandler +meta: Python example code for the StaticFilesHandler class from the django.contrib.staticfiles.handlers module of the Django project. + + +StaticFilesHandler is a class within the django.contrib.staticfiles.handlers module of the Django project. + + +## Example 1 from django-webtest +[django-webtest](https://github.com/django-webtest/django-webtest) +([PyPI package information](https://pypi.org/project/django-webtest/)) +is a [Django](/django.html) extension that makes it easier to use +[WebTest](http://docs.pylonsproject.org/projects/webtest/) with +your projects. + +The project is open sourced under the +[MIT license](https://github.com/django-webtest/django-webtest/blob/master/LICENSE.txt). + +[**django-webtest / django_webtest / __init__.py**](https://github.com/django-webtest/django-webtest/blob/master/django_webtest/./__init__.py) + +```python +# __init__.py +import copy + +from django.conf import settings +from django.test.signals import template_rendered +from django.core.handlers.wsgi import WSGIHandler +from django.test import TestCase, TransactionTestCase +from django.test.client import store_rendered_templates + +from functools import partial + +try: + from importlib import import_module +except ImportError: + from django.utils.importlib import import_module + +from django.core import signals +try: + from django.db import close_old_connections +except ImportError: + from django.db import close_connection + close_old_connections = None +try: + from django.core.servers.basehttp import ( + AdminMediaHandler as StaticFilesHandler) +except ImportError: +~~ from django.contrib.staticfiles.handlers import StaticFilesHandler + +from webtest import TestApp +try: + from webtest.utils import NoDefault +except ImportError: + NoDefault = '' + +from django_webtest.response import DjangoWebtestResponse +from django_webtest.compat import to_string, to_wsgi_safe_string + + +_notgiven = object() + + +class DjangoTestApp(TestApp): + response_class = DjangoWebtestResponse + + def __init__(self, *args, **kwargs): + extra_environ = (kwargs.get('extra_environ') or {}).copy() + extra_environ.setdefault('HTTP_HOST', 'testserver') + kwargs['extra_environ'] = extra_environ + super(DjangoTestApp, self).__init__(self.get_wsgi_handler(), *args, **kwargs) + + def get_wsgi_handler(self): +~~ return StaticFilesHandler(WSGIHandler()) + + def set_user(self, user): + if user is None and 'WEBTEST_USER' in self.extra_environ: + del self.extra_environ['WEBTEST_USER'] + if user is not None: + self.extra_environ = self._update_environ(self.extra_environ, user) + + def _update_environ(self, environ, user=_notgiven): + environ = environ or {} + + if user is not _notgiven: + if user is None: + environ['WEBTEST_USER'] = '' + else: + username = _get_username(user) + environ['WEBTEST_USER'] = to_wsgi_safe_string(username) + + return environ + + def do_request(self, req, status, expect_errors): + if close_old_connections is not None: # Django 1.6+ + signals.request_started.disconnect(close_old_connections) + signals.request_finished.disconnect(close_old_connections) + else: # Django < 1.6 + + +## ... source file continues with no further StaticFilesHandler examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-storage-cachedstaticfilesstorage.markdown b/content/pages/examples/django/django-contrib-staticfiles-storage-cachedstaticfilesstorage.markdown new file mode 100644 index 000000000..62d79de7f --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-storage-cachedstaticfilesstorage.markdown @@ -0,0 +1,110 @@ +title: django.contrib.staticfiles.storage CachedStaticFilesStorage Example Code +category: page +slug: django-contrib-staticfiles-storage-cachedstaticfilesstorage-examples +sortorder: 500011072 +toc: False +sidebartitle: django.contrib.staticfiles.storage CachedStaticFilesStorage +meta: Python example code for the CachedStaticFilesStorage class from the django.contrib.staticfiles.storage module of the Django project. + + +CachedStaticFilesStorage is a class within the django.contrib.staticfiles.storage module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / storage.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./storage.py) + +```python +# storage.py +import gzip + +from io import BytesIO + +~~from django.contrib.staticfiles.storage import CachedStaticFilesStorage, ManifestStaticFilesStorage, StaticFilesStorage +from django.contrib.staticfiles.utils import matches_patterns + +from django.core.files.base import File + + +class PipelineMixin(object): + packing = True + + def post_process(self, paths, dry_run=False, **options): + if dry_run: + return + + from pipeline.packager import Packager + packager = Packager(storage=self) + for package_name in packager.packages['css']: + package = packager.package_for('css', package_name) + output_file = package.output_filename + if self.packing: + packager.pack_stylesheets(package) + paths[output_file] = (self, output_file) + yield output_file, output_file, True + for package_name in packager.packages['js']: + package = packager.package_for('js', package_name) + output_file = package.output_filename + + +## ... source file abbreviated to get to CachedStaticFilesStorage examples ... + + + for path in paths: + if path: + if not matches_patterns(path, self.gzip_patterns): + continue + original_file = self.open(path) + gzipped_path = f"{path}.gz" + if self.exists(gzipped_path): + self.delete(gzipped_path) + gzipped_file = self._compress(original_file) + gzipped_path = self.save(gzipped_path, gzipped_file) + yield gzipped_path, gzipped_path, True + + +class NonPackagingMixin(object): + packing = False + + +class PipelineStorage(PipelineMixin, StaticFilesStorage): + pass + + +class NonPackagingPipelineStorage(NonPackagingMixin, PipelineStorage): + pass + + +~~class PipelineCachedStorage(PipelineMixin, CachedStaticFilesStorage): + pass + + +class NonPackagingPipelineCachedStorage(NonPackagingMixin, PipelineCachedStorage): + pass + + +class PipelineManifestStorage(PipelineMixin, ManifestStaticFilesStorage): + pass + + +class NonPackagingPipelineManifestStorage(NonPackagingMixin, ManifestStaticFilesStorage): + pass + + + +## ... source file continues with no further CachedStaticFilesStorage examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-storage-hashedfilesmixin.markdown b/content/pages/examples/django/django-contrib-staticfiles-storage-hashedfilesmixin.markdown new file mode 100644 index 000000000..ca526d574 --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-storage-hashedfilesmixin.markdown @@ -0,0 +1,57 @@ +title: django.contrib.staticfiles.storage HashedFilesMixin Example Code +category: page +slug: django-contrib-staticfiles-storage-hashedfilesmixin-examples +sortorder: 500011073 +toc: False +sidebartitle: django.contrib.staticfiles.storage HashedFilesMixin +meta: Python example code for the HashedFilesMixin class from the django.contrib.staticfiles.storage module of the Django project. + + +HashedFilesMixin is a class within the django.contrib.staticfiles.storage module of the Django project. + + +## Example 1 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / admin / staticfiles.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/admin/staticfiles.py) + +```python +# staticfiles.py +import hashlib + +from django.conf import settings +~~from django.contrib.staticfiles.storage import HashedFilesMixin +from django.core.files.storage import get_storage_class +from django.templatetags.static import static + +from wagtail import __version__ + + +try: + use_version_strings = settings.WAGTAILADMIN_STATIC_FILE_VERSION_STRINGS +except AttributeError: + + if settings.DEBUG: + use_version_strings = True + else: + storage = get_storage_class(settings.STATICFILES_STORAGE) + use_version_strings = not issubclass(storage, HashedFilesMixin) + + +if use_version_strings: + VERSION_HASH = hashlib.sha1( + (__version__ + settings.SECRET_KEY).encode('utf-8') + ).hexdigest()[:8] +else: + VERSION_HASH = None + + + +## ... source file continues with no further HashedFilesMixin examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-storage-manifeststaticfilesstorage.markdown b/content/pages/examples/django/django-contrib-staticfiles-storage-manifeststaticfilesstorage.markdown new file mode 100644 index 000000000..d920d3c9f --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-storage-manifeststaticfilesstorage.markdown @@ -0,0 +1,102 @@ +title: django.contrib.staticfiles.storage ManifestStaticFilesStorage Example Code +category: page +slug: django-contrib-staticfiles-storage-manifeststaticfilesstorage-examples +sortorder: 500011074 +toc: False +sidebartitle: django.contrib.staticfiles.storage ManifestStaticFilesStorage +meta: Python example code for the ManifestStaticFilesStorage class from the django.contrib.staticfiles.storage module of the Django project. + + +ManifestStaticFilesStorage is a class within the django.contrib.staticfiles.storage module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / storage.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./storage.py) + +```python +# storage.py +import gzip + +from io import BytesIO + +~~from django.contrib.staticfiles.storage import CachedStaticFilesStorage, ManifestStaticFilesStorage, StaticFilesStorage +from django.contrib.staticfiles.utils import matches_patterns + +from django.core.files.base import File + + +class PipelineMixin(object): + packing = True + + def post_process(self, paths, dry_run=False, **options): + if dry_run: + return + + from pipeline.packager import Packager + packager = Packager(storage=self) + for package_name in packager.packages['css']: + package = packager.package_for('css', package_name) + output_file = package.output_filename + if self.packing: + packager.pack_stylesheets(package) + paths[output_file] = (self, output_file) + yield output_file, output_file, True + for package_name in packager.packages['js']: + package = packager.package_for('js', package_name) + output_file = package.output_filename + + +## ... source file abbreviated to get to ManifestStaticFilesStorage examples ... + + + gzipped_file = self._compress(original_file) + gzipped_path = self.save(gzipped_path, gzipped_file) + yield gzipped_path, gzipped_path, True + + +class NonPackagingMixin(object): + packing = False + + +class PipelineStorage(PipelineMixin, StaticFilesStorage): + pass + + +class NonPackagingPipelineStorage(NonPackagingMixin, PipelineStorage): + pass + + +class PipelineCachedStorage(PipelineMixin, CachedStaticFilesStorage): + pass + + +class NonPackagingPipelineCachedStorage(NonPackagingMixin, PipelineCachedStorage): + pass + + +~~class PipelineManifestStorage(PipelineMixin, ManifestStaticFilesStorage): + pass + + +~~class NonPackagingPipelineManifestStorage(NonPackagingMixin, ManifestStaticFilesStorage): + pass + + + +## ... source file continues with no further ManifestStaticFilesStorage examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-storage-staticfiles-storage.markdown b/content/pages/examples/django/django-contrib-staticfiles-storage-staticfiles-storage.markdown new file mode 100644 index 000000000..ae20ee1a5 --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-storage-staticfiles-storage.markdown @@ -0,0 +1,197 @@ +title: django.contrib.staticfiles.storage staticfiles_storage Example Code +category: page +slug: django-contrib-staticfiles-storage-staticfiles-storage-examples +sortorder: 500011076 +toc: False +sidebartitle: django.contrib.staticfiles.storage staticfiles_storage +meta: Python example code for the staticfiles_storage callable from the django.contrib.staticfiles.storage module of the Django project. + + +staticfiles_storage is a callable within the django.contrib.staticfiles.storage module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / forms / fields.py**](https://github.com/jrief/django-angular/blob/master/djng/forms/fields.py) + +```python +# fields.py +import re +import mimetypes + +from django.conf import settings +~~from django.contrib.staticfiles.storage import staticfiles_storage +from django.core import signing +from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.core.files.storage import default_storage +from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile +from django.urls import reverse_lazy +from django.forms import fields, models as model_fields, widgets +from django.utils.html import format_html +from django.utils.module_loading import import_string +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext_lazy as _, ungettext_lazy + +from djng import app_settings +from .widgets import DropFileWidget, DropImageWidget + + +class DefaultFieldMixin(object): + render_label = True + + def has_subwidgets(self): + return False + + def get_potential_errors(self): + return self.get_input_required_errors() + + + +## ... source file abbreviated to get to staticfiles_storage examples ... + + + +class FileField(FileFieldMixin, fields.FileField): + storage = app_settings.upload_storage + signer = signing.Signer() + + def __init__(self, *args, **kwargs): + accept = kwargs.pop('accept', '*/*') + fileupload_url = kwargs.pop('fileupload_url', reverse_lazy('fileupload')) + area_label = kwargs.pop('area_label', _("Drop file here or click to upload")) + attrs = { + 'accept': accept, + 'ngf-pattern': accept, + } + kwargs.update(widget=DropFileWidget(area_label, fileupload_url, attrs=attrs)) + super(FileField, self).__init__(*args, **kwargs) + + @classmethod + def preview(cls, file_obj): + available_name = cls.storage.get_available_name(file_obj.name) + temp_name = cls.storage.save(available_name, file_obj) + extension = mimetypes.guess_extension(file_obj.content_type) + if extension: + extension = extension[1:] + else: + extension = '_blank' +~~ icon_url = staticfiles_storage.url('djng/icons/{}.png'.format(extension)) + return { + 'url': 'url({})'.format(icon_url), + 'temp_name': cls.signer.sign(temp_name), + 'file_name': file_obj.name, + 'file_size': file_obj.size, + 'charset': file_obj.charset, + 'content_type': file_obj.content_type, + 'content_type_extra': file_obj.content_type_extra, + } + + +class ImageField(FileFieldMixin, fields.ImageField): + storage = app_settings.upload_storage + signer = signing.Signer() + + def __init__(self, *args, **kwargs): + if 'easy_thumbnails' not in settings.INSTALLED_APPS: + raise ImproperlyConfigured("'djng.forms.fields.ImageField' requires 'easy-thubnails' to be installed") + accept = kwargs.pop('accept', 'image/*') + fileupload_url = kwargs.pop('fileupload_url', reverse_lazy('fileupload')) + area_label = kwargs.pop('area_label', _("Drop image here or click to upload")) + attrs = { + 'accept': accept, + 'ngf-pattern': accept, + + +## ... source file continues with no further staticfiles_storage examples... + +``` + + +## Example 2 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / manifest.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./manifest.py) + +```python +# manifest.py +import os + +from django.conf.settings import settings as django_settings +from django.contrib.staticfiles.finders import get_finders +~~from django.contrib.staticfiles.storage import staticfiles_storage + +from pipeline.conf import settings + +from manifesto import Manifest + +from pipeline.packager import Packager + + +class PipelineManifest(Manifest): + def __init__(self): + self.packager = Packager() + self.packages = self.collect_packages() + self.finders = get_finders() + self.package_files = [] + + def collect_packages(self): + packages = [] + for package_name in self.packager.packages['css']: + package = self.packager.package_for('css', package_name) + if package.manifest: + packages.append(package) + for package_name in self.packager.packages['js']: + package = self.packager.package_for('js', package_name) + if package.manifest: + packages.append(package) + return packages + + def cache(self): + + if settings.PIPELINE_ENABLED: + for package in self.packages: + path = package.output_filename + self.package_files.append(path) +~~ yield staticfiles_storage.url(path) + else: + for package in self.packages: + for path in self.packager.compile(package.paths): + self.package_files.append(path) +~~ yield staticfiles_storage.url(path) + + ignore_patterns = getattr(django_settings, "STATICFILES_IGNORE_PATTERNS", None) + for finder in self.finders: + for path, storage in finder.list(ignore_patterns): + if getattr(storage, 'prefix', None): + prefixed_path = os.path.join(storage.prefix, path) + else: + prefixed_path = path + + if prefixed_path not in self.package_files: + + self.package_files.append(prefixed_path) +~~ yield staticfiles_storage.url(prefixed_path) + + + +## ... source file continues with no further staticfiles_storage examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-storage-staticfilesstorage.markdown b/content/pages/examples/django/django-contrib-staticfiles-storage-staticfilesstorage.markdown new file mode 100644 index 000000000..0562d9564 --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-storage-staticfilesstorage.markdown @@ -0,0 +1,118 @@ +title: django.contrib.staticfiles.storage StaticFilesStorage Example Code +category: page +slug: django-contrib-staticfiles-storage-staticfilesstorage-examples +sortorder: 500011075 +toc: False +sidebartitle: django.contrib.staticfiles.storage StaticFilesStorage +meta: Python example code for the StaticFilesStorage class from the django.contrib.staticfiles.storage module of the Django project. + + +StaticFilesStorage is a class within the django.contrib.staticfiles.storage module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / storage.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./storage.py) + +```python +# storage.py +import gzip + +from io import BytesIO + +~~from django.contrib.staticfiles.storage import CachedStaticFilesStorage, ManifestStaticFilesStorage, StaticFilesStorage +from django.contrib.staticfiles.utils import matches_patterns + +from django.core.files.base import File + + +class PipelineMixin(object): + packing = True + + def post_process(self, paths, dry_run=False, **options): + if dry_run: + return + + from pipeline.packager import Packager + packager = Packager(storage=self) + for package_name in packager.packages['css']: + package = packager.package_for('css', package_name) + output_file = package.output_filename + if self.packing: + packager.pack_stylesheets(package) + paths[output_file] = (self, output_file) + yield output_file, output_file, True + for package_name in packager.packages['js']: + package = packager.package_for('js', package_name) + output_file = package.output_filename + + +## ... source file abbreviated to get to StaticFilesStorage examples ... + + + for name, hashed_name, processed in super_class.post_process(paths.copy(), dry_run, **options): + if hashed_name != name: + paths[hashed_name] = (self, hashed_name) + yield name, hashed_name, processed + + if dry_run: + return + + for path in paths: + if path: + if not matches_patterns(path, self.gzip_patterns): + continue + original_file = self.open(path) + gzipped_path = f"{path}.gz" + if self.exists(gzipped_path): + self.delete(gzipped_path) + gzipped_file = self._compress(original_file) + gzipped_path = self.save(gzipped_path, gzipped_file) + yield gzipped_path, gzipped_path, True + + +class NonPackagingMixin(object): + packing = False + + +~~class PipelineStorage(PipelineMixin, StaticFilesStorage): + pass + + +class NonPackagingPipelineStorage(NonPackagingMixin, PipelineStorage): + pass + + +class PipelineCachedStorage(PipelineMixin, CachedStaticFilesStorage): + pass + + +class NonPackagingPipelineCachedStorage(NonPackagingMixin, PipelineCachedStorage): + pass + + +class PipelineManifestStorage(PipelineMixin, ManifestStaticFilesStorage): + pass + + +class NonPackagingPipelineManifestStorage(NonPackagingMixin, ManifestStaticFilesStorage): + pass + + + +## ... source file continues with no further StaticFilesStorage examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-storage.markdown b/content/pages/examples/django/django-contrib-staticfiles-storage.markdown new file mode 100644 index 000000000..9ea16df48 --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-storage.markdown @@ -0,0 +1,143 @@ +title: django.contrib.staticfiles storage Example Code +category: page +slug: django-contrib-staticfiles-storage-examples +sortorder: 500011066 +toc: False +sidebartitle: django.contrib.staticfiles storage +meta: Python example code for the storage callable from the django.contrib.staticfiles module of the Django project. + + +storage is a callable within the django.contrib.staticfiles module of the Django project. + + +## Example 1 from django-debug-toolbar +[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar) +([project documentation](https://github.com/jazzband/django-debug-toolbar) +and [PyPI page](https://pypi.org/project/django-debug-toolbar/)) +grants a developer detailed request-response cycle information while +developing a [Django](/django.html) web application. +The code for django-debug-toolbar is +[open source](https://github.com/jazzband/django-debug-toolbar/blob/master/LICENSE) +and maintained by the developer community group known as +[Jazzband](https://jazzband.co/). + +[**django-debug-toolbar / debug_toolbar / panels / staticfiles.py**](https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/panels/staticfiles.py) + +```python +# staticfiles.py +from collections import OrderedDict +from os.path import join, normpath + +from django.conf import settings +~~from django.contrib.staticfiles import finders, storage +from django.core.files.storage import get_storage_class +from django.utils.functional import LazyObject +from django.utils.translation import gettext_lazy as _, ngettext as __ + +from debug_toolbar import panels +from debug_toolbar.utils import ThreadCollector + +try: + import threading +except ImportError: + threading = None + + +class StaticFile: + + def __init__(self, path): + self.path = path + + def __str__(self): + return self.path + + def real_path(self): + return finders.find(self.path) + + def url(self): +~~ return storage.staticfiles_storage.url(self.path) + + +class FileCollector(ThreadCollector): + def collect(self, path, thread=None): + if path.endswith("/"): + return + super().collect(StaticFile(path), thread) + + +collector = FileCollector() + + +class DebugConfiguredStorage(LazyObject): + + def _setup(self): + + configured_storage_cls = get_storage_class(settings.STATICFILES_STORAGE) + + class DebugStaticFilesStorage(configured_storage_cls): + def __init__(self, collector, *args, **kwargs): + super().__init__(*args, **kwargs) + self.collector = collector + + def url(self, path): + self.collector.collect(path) + return super().url(path) + + self._wrapped = DebugStaticFilesStorage(collector) + + +~~_original_storage = storage.staticfiles_storage + + +class StaticFilesPanel(panels.Panel): + + name = "Static files" + template = "debug_toolbar/panels/staticfiles.html" + + @property + def title(self): + return _("Static files (%(num_found)s found, %(num_used)s used)") % { + "num_found": self.num_found, + "num_used": self.num_used, + } + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.num_found = 0 + self._paths = {} + + def enable_instrumentation(self): +~~ storage.staticfiles_storage = DebugConfiguredStorage() + + def disable_instrumentation(self): +~~ storage.staticfiles_storage = _original_storage + + @property + def num_used(self): + return len(self._paths[threading.currentThread()]) + + nav_title = _("Static files") + + @property + def nav_subtitle(self): + num_used = self.num_used + return __("%(num_used)s file used", "%(num_used)s files used", num_used) % { + "num_used": num_used + } + + def process_request(self, request): + collector.clear_collection() + return super().process_request(request) + + def generate_stats(self, request, response): + used_paths = collector.get_collection() + self._paths[threading.currentThread()] = used_paths + + self.record_stats( + { + + +## ... source file continues with no further storage examples... + +``` + diff --git a/content/pages/examples/django/django-contrib-staticfiles-utils-matches-patterns.markdown b/content/pages/examples/django/django-contrib-staticfiles-utils-matches-patterns.markdown new file mode 100644 index 000000000..47c78f231 --- /dev/null +++ b/content/pages/examples/django/django-contrib-staticfiles-utils-matches-patterns.markdown @@ -0,0 +1,121 @@ +title: django.contrib.staticfiles.utils matches_patterns Example Code +category: page +slug: django-contrib-staticfiles-utils-matches-patterns-examples +sortorder: 500011077 +toc: False +sidebartitle: django.contrib.staticfiles.utils matches_patterns +meta: Python example code for the matches_patterns callable from the django.contrib.staticfiles.utils module of the Django project. + + +matches_patterns is a callable within the django.contrib.staticfiles.utils module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / storage.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./storage.py) + +```python +# storage.py +import gzip + +from io import BytesIO + +from django.contrib.staticfiles.storage import CachedStaticFilesStorage, ManifestStaticFilesStorage, StaticFilesStorage +~~from django.contrib.staticfiles.utils import matches_patterns + +from django.core.files.base import File + + +class PipelineMixin(object): + packing = True + + def post_process(self, paths, dry_run=False, **options): + if dry_run: + return + + from pipeline.packager import Packager + packager = Packager(storage=self) + for package_name in packager.packages['css']: + package = packager.package_for('css', package_name) + output_file = package.output_filename + if self.packing: + packager.pack_stylesheets(package) + paths[output_file] = (self, output_file) + yield output_file, output_file, True + for package_name in packager.packages['js']: + package = packager.package_for('js', package_name) + output_file = package.output_filename + if self.packing: + + +## ... source file abbreviated to get to matches_patterns examples ... + + + +class GZIPMixin(object): + gzip_patterns = ("*.css", "*.js") + + def _compress(self, original_file): + content = BytesIO() + gzip_file = gzip.GzipFile(mode='wb', fileobj=content) + gzip_file.write(original_file.read()) + gzip_file.close() + content.seek(0) + return File(content) + + def post_process(self, paths, dry_run=False, **options): + super_class = super(GZIPMixin, self) + if hasattr(super_class, 'post_process'): + for name, hashed_name, processed in super_class.post_process(paths.copy(), dry_run, **options): + if hashed_name != name: + paths[hashed_name] = (self, hashed_name) + yield name, hashed_name, processed + + if dry_run: + return + + for path in paths: + if path: +~~ if not matches_patterns(path, self.gzip_patterns): + continue + original_file = self.open(path) + gzipped_path = f"{path}.gz" + if self.exists(gzipped_path): + self.delete(gzipped_path) + gzipped_file = self._compress(original_file) + gzipped_path = self.save(gzipped_path, gzipped_file) + yield gzipped_path, gzipped_path, True + + +class NonPackagingMixin(object): + packing = False + + +class PipelineStorage(PipelineMixin, StaticFilesStorage): + pass + + +class NonPackagingPipelineStorage(NonPackagingMixin, PipelineStorage): + pass + + +class PipelineCachedStorage(PipelineMixin, CachedStaticFilesStorage): + pass + + +## ... source file continues with no further matches_patterns examples... + +``` + diff --git a/content/pages/examples/django/django-core-cache.markdown b/content/pages/examples/django/django-core-cache.markdown new file mode 100644 index 000000000..f8bb4baf2 --- /dev/null +++ b/content/pages/examples/django/django-core-cache.markdown @@ -0,0 +1,115 @@ +title: django.core cache code examples +category: page +slug: django-core-cache-examples +sortorder: 500011078 +toc: False +sidebartitle: django.core cache +meta: Python example code for the cache function from the django.core module of the Django project. + + +cache is a function within the django.core module of the Django project. + + +## Example 1 from django-debug-toolbar +[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar) +([project documentation](https://github.com/jazzband/django-debug-toolbar) +and [PyPI page](https://pypi.org/project/django-debug-toolbar/)) +grants a developer detailed request-response cycle information while +developing a [Django](/django.html) web application. +The code for django-debug-toolbar is +[open source](https://github.com/jazzband/django-debug-toolbar/blob/master/LICENSE) +and maintained by the developer community group known as +[Jazzband](https://jazzband.co/). + +[**django-debug-toolbar / debug_toolbar / panels / cache.py**](https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/panels/cache.py) + +```python +# cache.py +import inspect +import sys +import time +from collections import OrderedDict + +from django.conf import settings +~~from django.core import cache +from django.core.cache import CacheHandler, caches as original_caches +from django.core.cache.backends.base import BaseCache +from django.dispatch import Signal +from django.middleware import cache as middleware_cache +from django.utils.translation import gettext_lazy as _, ngettext as __ + +from debug_toolbar import settings as dt_settings +from debug_toolbar.panels import Panel +from debug_toolbar.utils import ( + get_stack, + get_template_info, + render_stacktrace, + tidy_stacktrace, +) + +cache_called = Signal() + + +def send_signal(method): + def wrapped(self, *args, **kwargs): + t = time.time() + value = method(self, *args, **kwargs) + t = time.time() - t + + + +## ... source file abbreviated to get to cache examples ... + + + @property + def nav_subtitle(self): + cache_calls = len(self.calls) + return __( + "%(cache_calls)d call in %(time).2fms", + "%(cache_calls)d calls in %(time).2fms", + cache_calls, + ) % {"cache_calls": cache_calls, "time": self.total_time} + + @property + def title(self): + count = len(getattr(settings, "CACHES", ["default"])) + return __( + "Cache calls from %(count)d backend", + "Cache calls from %(count)d backends", + count, + ) % {"count": count} + + def enable_instrumentation(self): + if isinstance(middleware_cache.caches, CacheHandlerPatch): +~~ cache.caches = middleware_cache.caches + else: +~~ cache.caches = CacheHandlerPatch() + + def disable_instrumentation(self): +~~ cache.caches = original_caches + middleware_cache.caches = original_caches + + def generate_stats(self, request, response): + self.record_stats( + { + "total_calls": len(self.calls), + "calls": self.calls, + "total_time": self.total_time, + "hits": self.hits, + "misses": self.misses, + "counts": self.counts, + } + ) + + def generate_server_timing(self, request, response): + stats = self.get_stats() + value = stats.get("total_time", 0) + title = "Cache {} Calls".format(stats.get("total_calls", 0)) + self.record_server_timing("total_time", title, value) + + + +## ... source file continues with no further cache examples... + +``` + diff --git a/content/pages/examples/django/django-core-checks.markdown b/content/pages/examples/django/django-core-checks.markdown new file mode 100644 index 000000000..c4bceb4db --- /dev/null +++ b/content/pages/examples/django/django-core-checks.markdown @@ -0,0 +1,388 @@ +title: django.core checks code examples +category: page +slug: django-core-checks-examples +sortorder: 500011079 +toc: False +sidebartitle: django.core checks +meta: Python example code for the checks function from the django.core module of the Django project. + + +checks is a function within the django.core module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / tests / test_apphooks.py**](https://github.com/divio/django-cms/blob/develop/cms/tests/test_apphooks.py) + +```python +# test_apphooks.py +import sys +import mock + +from django.contrib.admin.models import CHANGE, LogEntry +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Permission +from django.contrib.contenttypes.models import ContentType +from django.contrib.sites.models import Site +~~from django.core import checks +from django.core.cache import cache +from django.core.checks.urls import check_url_config +from django.test.utils import override_settings +from django.urls import NoReverseMatch, clear_url_caches, resolve, reverse +from django.utils.timezone import now +from django.utils.translation import override as force_language + +from six import string_types + +from cms.admin.forms import AdvancedSettingsForm +from cms.api import create_page, create_title +from cms.app_base import CMSApp +from cms.apphook_pool import apphook_pool +from cms.appresolver import applications_page_check, clear_app_resolvers, get_app_patterns +from cms.constants import PUBLISHER_STATE_DIRTY +from cms.models import Title, Page +from cms.middleware.page import get_page +from cms.test_utils.project.placeholderapp.models import Example1 +from cms.test_utils.testcases import CMSTestCase +from cms.tests.test_menu_utils import DumbPageLanguageUrl +from cms.toolbar.toolbar import CMSToolbar +from cms.utils.conf import get_cms_setting +from cms.utils.urlutils import admin_reverse +from menus.menu_pool import menu_pool + + +## ... source file abbreviated to get to checks examples ... + + + create_title("de", "aphooked-page-de", page) + self.assertTrue(page.publish('en')) + self.assertTrue(page.publish('de')) + self.assertTrue(blank_page.publish('en')) + with force_language("en"): + response = self.client.get(self.get_pages_root()) + self.assertTemplateUsed(response, 'sampleapp/home.html') + self.assertContains(response, '<--noplaceholder-->') + response = self.client.get('/en/blankapp/') + self.assertTemplateUsed(response, 'nav_playground.html') + + self.apphook_clear() + + @override_settings(ROOT_URLCONF='cms.test_utils.project.urls_for_apphook_tests') + def test_apphook_does_not_crash_django_checks(self): + self.apphook_clear() + superuser = get_user_model().objects.create_superuser('admin', 'admin@admin.com', 'admin') + create_page("apphooked-page", "nav_playground.html", "en", + created_by=superuser, published=True, apphook="SampleApp") + self.reload_urls() +~~ checks.run_checks() + self.apphook_clear() + + @override_settings(ROOT_URLCONF='cms.test_utils.project.urls_for_apphook_tests') + def test_apphook_on_root_reverse(self): + self.apphook_clear() + superuser = get_user_model().objects.create_superuser('admin', 'admin@admin.com', 'admin') + page = create_page("apphooked-page", "nav_playground.html", "en", + created_by=superuser, published=True, apphook="SampleApp") + create_title("de", "aphooked-page-de", page) + self.assertTrue(page.publish('de')) + self.assertTrue(page.publish('en')) + + self.reload_urls() + + self.assertFalse(reverse('sample-settings').startswith('//')) + self.apphook_clear() + + @override_settings(ROOT_URLCONF='cms.test_utils.project.urls_for_apphook_tests') + def test_multisite_apphooks(self): + self.apphook_clear() + site1, _ = Site.objects.get_or_create(pk=1) + site2, _ = Site.objects.get_or_create(pk=2) + superuser = get_user_model().objects.create_superuser('admin', 'admin@admin.com', 'admin') + home_site_1 = create_page( + + +## ... source file continues with no further checks examples... + +``` + + +## Example 2 from django-cors-headers +[django-cors-headers](https://github.com/ottoyiu/django-cors-headers) +is an +[open source](https://github.com/ottoyiu/django-cors-headers/blob/master/LICENSE) +library for enabling +[Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) +handling in your [Django](/django.html) web applications and appropriately +dealing with HTTP headers for CORS requests. + +[**django-cors-headers / src/corsheaders / checks.py**](https://github.com/ottoyiu/django-cors-headers/blob/master/src/corsheaders/./checks.py) + +```python +# checks.py +import re +from collections.abc import Sequence +from numbers import Integral +from urllib.parse import urlparse + +from django.conf import settings +~~from django.core import checks + +from corsheaders.conf import conf + +re_type = type(re.compile("")) + + +@checks.register +def check_settings(app_configs, **kwargs): + errors = [] + + if not is_sequence(conf.CORS_ALLOW_HEADERS, str): + errors.append( +~~ checks.Error( + "CORS_ALLOW_HEADERS should be a sequence of strings.", + id="corsheaders.E001", + ) + ) + + if not is_sequence(conf.CORS_ALLOW_METHODS, str): + errors.append( +~~ checks.Error( + "CORS_ALLOW_METHODS should be a sequence of strings.", + id="corsheaders.E002", + ) + ) + + if not isinstance(conf.CORS_ALLOW_CREDENTIALS, bool): + errors.append( +~~ checks.Error( + "CORS_ALLOW_CREDENTIALS should be a bool.", id="corsheaders.E003" + ) + ) + + if ( + not isinstance(conf.CORS_PREFLIGHT_MAX_AGE, Integral) + or conf.CORS_PREFLIGHT_MAX_AGE < 0 + ): + errors.append( +~~ checks.Error( + ( + "CORS_PREFLIGHT_MAX_AGE should be an integer greater than " + + "or equal to zero." + ), + id="corsheaders.E004", + ) + ) + + if not isinstance(conf.CORS_ORIGIN_ALLOW_ALL, bool): + errors.append( +~~ checks.Error( + "CORS_ORIGIN_ALLOW_ALL should be a bool.", id="corsheaders.E005" + ) + ) + + if not is_sequence(conf.CORS_ORIGIN_WHITELIST, str): + errors.append( +~~ checks.Error( + "CORS_ORIGIN_WHITELIST should be a sequence of strings.", + id="corsheaders.E006", + ) + ) + else: + special_origin_values = ( + "null", + "file://", + ) + for origin in conf.CORS_ORIGIN_WHITELIST: + if origin in special_origin_values: + continue + parsed = urlparse(origin) + if parsed.scheme == "" or parsed.netloc == "": + errors.append( +~~ checks.Error( + ( + "Origin {} in CORS_ORIGIN_WHITELIST is missing " + + " scheme or netloc" + ).format(repr(origin)), + id="corsheaders.E013", + hint=( + "Add a scheme (e.g. https://) or netloc (e.g. " + + "example.com)." + ), + ) + ) + else: + for part in ("path", "params", "query", "fragment"): + if getattr(parsed, part) != "": + errors.append( +~~ checks.Error( + ( + "Origin {} in CORS_ORIGIN_WHITELIST should " + + "not have {}" + ).format(repr(origin), part), + id="corsheaders.E014", + ) + ) + + if not is_sequence(conf.CORS_ORIGIN_REGEX_WHITELIST, (str, re_type)): + errors.append( +~~ checks.Error( + ( + "CORS_ORIGIN_REGEX_WHITELIST should be a sequence of " + + "strings and/or compiled regexes." + ), + id="corsheaders.E007", + ) + ) + + if not is_sequence(conf.CORS_EXPOSE_HEADERS, str): + errors.append( +~~ checks.Error( + "CORS_EXPOSE_HEADERS should be a sequence.", id="corsheaders.E008" + ) + ) + + if not isinstance(conf.CORS_URLS_REGEX, (str, re_type)): + errors.append( +~~ checks.Error( + "CORS_URLS_REGEX should be a string or regex.", id="corsheaders.E009" + ) + ) + + if not isinstance(conf.CORS_REPLACE_HTTPS_REFERER, bool): + errors.append( +~~ checks.Error( + "CORS_REPLACE_HTTPS_REFERER should be a bool.", id="corsheaders.E011" + ) + ) + + if hasattr(settings, "CORS_MODEL"): + errors.append( +~~ checks.Error( + ( + "The CORS_MODEL setting has been removed - see " + + "django-cors-headers' HISTORY." + ), + id="corsheaders.E012", + ) + ) + + return errors + + +def is_sequence(thing, type_or_types): + return isinstance(thing, Sequence) and all( + isinstance(x, type_or_types) for x in thing + ) + + + +## ... source file continues with no further checks examples... + +``` + + +## Example 3 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / snippets / tests.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/snippets/tests.py) + +```python +# tests.py +import json + +from django.contrib.admin.utils import quote +from django.contrib.auth import get_user_model +from django.contrib.auth.models import AnonymousUser, Permission +~~from django.core import checks +from django.core.exceptions import ValidationError +from django.core.files.base import ContentFile +from django.core.files.uploadedfile import SimpleUploadedFile +from django.http import HttpRequest, HttpResponse +from django.test import RequestFactory, TestCase +from django.test.utils import override_settings +from django.urls import reverse +from taggit.models import Tag + +from wagtail.admin.edit_handlers import FieldPanel +from wagtail.admin.forms import WagtailAdminModelForm +from wagtail.core.models import Page +from wagtail.snippets.blocks import SnippetChooserBlock +from wagtail.snippets.edit_handlers import SnippetChooserPanel +from wagtail.snippets.models import SNIPPET_MODELS, register_snippet +from wagtail.snippets.views.snippets import get_snippet_edit_handler +from wagtail.tests.snippets.forms import FancySnippetForm +from wagtail.tests.snippets.models import ( + AlphaSnippet, FancySnippet, FileUploadSnippet, RegisterDecorator, RegisterFunction, + SearchableSnippet, StandardSnippet, StandardSnippetWithCustomPrimaryKey, ZuluSnippet) +from wagtail.tests.testapp.models import ( + Advert, AdvertWithCustomPrimaryKey, AdvertWithCustomUUIDPrimaryKey, AdvertWithTabbedInterface, + SnippetChooserModel, SnippetChooserModelWithCustomPrimaryKey) +from wagtail.tests.utils import WagtailTestUtils + + +## ... source file abbreviated to get to checks examples ... + + + def setUp(self): + self.login() + + def get(self, pk, params=None): + return self.client.get(reverse('wagtailsnippets:chosen', + args=('tests', 'advertwithcustomuuidprimarykey', quote(pk))), + params or {}) + + def test_choose_a_page(self): + response = self.get(pk=AdvertWithCustomUUIDPrimaryKey.objects.all()[0].pk) + response_json = json.loads(response.content.decode()) + self.assertEqual(response_json['step'], 'chosen') + + +class TestPanelConfigurationChecks(TestCase, WagtailTestUtils): + + def setUp(self): + self.warning_id = 'wagtailadmin.W002' + + def get_checks_result(): +~~ checks_result = checks.run_checks(tags=['panels']) + return [ + warning for warning in + checks_result if warning.id == self.warning_id] + + self.get_checks_result = get_checks_result + + def test_model_with_single_tabbed_panel_only(self): + + StandardSnippet.content_panels = [FieldPanel('text')] + +~~ warning = checks.Warning( + "StandardSnippet.content_panels will have no effect on snippets editing", + hint="""Ensure that StandardSnippet uses `panels` instead of `content_panels`\ +or set up an `edit_handler` if you want a tabbed editing interface. +There are no default tabs on non-Page models so there will be no\ + Content tab for the content_panels to render in.""", + obj=StandardSnippet, + id='wagtailadmin.W002', + ) + + checks_results = self.get_checks_result() + + self.assertEqual([warning], checks_results) + + delattr(StandardSnippet, 'content_panels') + + + +## ... source file continues with no further checks examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions-disallowedredirect.markdown b/content/pages/examples/django/django-core-exceptions-disallowedredirect.markdown new file mode 100644 index 000000000..6ad7cc979 --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions-disallowedredirect.markdown @@ -0,0 +1,64 @@ +title: django.core.exceptions DisallowedRedirect Example Code +category: page +slug: django-core-exceptions-disallowedredirect-examples +sortorder: 500011098 +toc: False +sidebartitle: django.core.exceptions DisallowedRedirect +meta: Python example code for the DisallowedRedirect class from the django.core.exceptions module of the Django project. + + +DisallowedRedirect is a class within the django.core.exceptions module of the Django project. + + +## Example 1 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / http.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./http.py) + +```python +# http.py +from urllib.parse import urlparse + +~~from django.core.exceptions import DisallowedRedirect +from django.http import HttpResponse +from django.utils.encoding import iri_to_uri + + +class OAuth2ResponseRedirect(HttpResponse): + status_code = 302 + + def __init__(self, redirect_to, allowed_schemes, *args, **kwargs): + super().__init__(*args, **kwargs) + self["Location"] = iri_to_uri(redirect_to) + self.allowed_schemes = allowed_schemes + self.validate_redirect(redirect_to) + + @property + def url(self): + return self["Location"] + + def validate_redirect(self, redirect_to): + parsed = urlparse(str(redirect_to)) + if not parsed.scheme: +~~ raise DisallowedRedirect("OAuth2 redirects require a URI scheme.") + if parsed.scheme not in self.allowed_schemes: +~~ raise DisallowedRedirect( + "Redirect to scheme {!r} is not permitted".format(parsed.scheme) + ) + + + +## ... source file continues with no further DisallowedRedirect examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions-fielddoesnotexist.markdown b/content/pages/examples/django/django-core-exceptions-fielddoesnotexist.markdown new file mode 100644 index 000000000..fda98d83f --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions-fielddoesnotexist.markdown @@ -0,0 +1,972 @@ +title: django.core.exceptions FieldDoesNotExist Example Code +category: page +slug: django-core-exceptions-fielddoesnotexist-examples +sortorder: 500011099 +toc: False +sidebartitle: django.core.exceptions FieldDoesNotExist +meta: Python example code for the FieldDoesNotExist class from the django.core.exceptions module of the Django project. + + +FieldDoesNotExist is a class within the django.core.exceptions module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog / models.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog/models.py) + +```python +# models.py +from __future__ import unicode_literals + +import json +import ast + +from django.conf import settings +from django.contrib.contenttypes.fields import GenericRelation +from django.contrib.contenttypes.models import ContentType +~~from django.core.exceptions import FieldDoesNotExist +from django.db import models, DEFAULT_DB_ALIAS +from django.db.models import QuerySet, Q +from django.utils import formats, timezone +from django.utils.encoding import python_2_unicode_compatible, smart_text +from django.utils.six import iteritems, integer_types +from django.utils.translation import ugettext_lazy as _ + +from jsonfield.fields import JSONField +from dateutil import parser +from dateutil.tz import gettz + + +class LogEntryManager(models.Manager): + + def log_create(self, instance, **kwargs): + changes = kwargs.get('changes', None) + pk = self._get_pk_value(instance) + + if changes is not None: + kwargs.setdefault('content_type', ContentType.objects.get_for_model(instance)) + kwargs.setdefault('object_pk', pk) + kwargs.setdefault('object_repr', smart_text(instance)) + + if isinstance(pk, integer_types): + + +## ... source file abbreviated to get to FieldDoesNotExist examples ... + + + @property + def changes_str(self, colon=': ', arrow=smart_text(' \u2192 '), separator='; '): + substrings = [] + + for field, values in iteritems(self.changes_dict): + substring = smart_text('{field_name:s}{colon:s}{old:s}{arrow:s}{new:s}').format( + field_name=field, + colon=colon, + old=values[0], + arrow=arrow, + new=values[1], + ) + substrings.append(substring) + + return separator.join(substrings) + + @property + def changes_display_dict(self): + from auditlog.registry import auditlog + model = self.content_type.model_class() + model_fields = auditlog.get_model_fields(model._meta.model) + changes_display_dict = {} + for field_name, values in iteritems(self.changes_dict): + try: + field = model._meta.get_field(field_name) +~~ except FieldDoesNotExist: + changes_display_dict[field_name] = values + continue + values_display = [] + choices_dict = None + if hasattr(field, 'choices') and len(field.choices) > 0: + choices_dict = dict(field.choices) + if hasattr(field, 'base_field') and getattr(field.base_field, 'choices', False): + choices_dict = dict(field.base_field.choices) + + if choices_dict: + for value in values: + try: + value = ast.literal_eval(value) + if type(value) is [].__class__: + values_display.append(', '.join([choices_dict.get(val, 'None') for val in value])) + else: + values_display.append(choices_dict.get(value, 'None')) + except ValueError: + values_display.append(choices_dict.get(value, 'None')) + except: + values_display.append(choices_dict.get(value, 'None')) + else: + try: + field_type = field.get_internal_type() + + +## ... source file continues with no further FieldDoesNotExist examples... + +``` + + +## Example 2 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / utils.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/./utils.py) + +```python +# utils.py +import base64 +import importlib +import json +import random +import re +import string +import unicodedata +from collections import OrderedDict +from urllib.parse import urlsplit + +import django +from django.contrib.auth import get_user_model +from django.contrib.sites.models import Site +~~from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured +from django.core.serializers.json import DjangoJSONEncoder +from django.core.validators import ValidationError, validate_email +from django.db.models import FileField +from django.db.models.fields import ( + BinaryField, + DateField, + DateTimeField, + EmailField, + TimeField, +) +from django.utils import dateparse +from django.utils.encoding import force_bytes, force_str + + +MAX_USERNAME_SUFFIX_LENGTH = 7 +USERNAME_SUFFIX_CHARS = ( + [string.digits] * 4 + + [string.ascii_letters] * (MAX_USERNAME_SUFFIX_LENGTH - 4)) + + +def _generate_unique_username_base(txts, regex=None): + from .account.adapter import get_adapter + adapter = get_adapter() + username = None + + +## ... source file abbreviated to get to FieldDoesNotExist examples ... + + + else: + ret = path_or_callable + return ret + + +SERIALIZED_DB_FIELD_PREFIX = '_db_' + + +def serialize_instance(instance): + data = {} + for k, v in instance.__dict__.items(): + if k.startswith('_') or callable(v): + continue + try: + field = instance._meta.get_field(k) + if isinstance(field, BinaryField): + v = force_str(base64.b64encode(v)) + elif isinstance(field, FileField): + if v and not isinstance(v, str): + v = v.name + try: + json.dumps(v, cls=DjangoJSONEncoder) + except TypeError: + v = field.get_prep_value(v) + k = SERIALIZED_DB_FIELD_PREFIX + k +~~ except FieldDoesNotExist: + pass + data[k] = v + return json.loads(json.dumps(data, cls=DjangoJSONEncoder)) + + +def deserialize_instance(model, data): + ret = model() + for k, v in data.items(): + is_db_value = False + if k.startswith(SERIALIZED_DB_FIELD_PREFIX): + k = k[len(SERIALIZED_DB_FIELD_PREFIX):] + is_db_value = True + if v is not None: + try: + f = model._meta.get_field(k) + if isinstance(f, DateTimeField): + v = dateparse.parse_datetime(v) + elif isinstance(f, TimeField): + v = dateparse.parse_time(v) + elif isinstance(f, DateField): + v = dateparse.parse_date(v) + elif isinstance(f, BinaryField): + v = force_bytes( + base64.b64decode( + force_bytes(v))) + elif is_db_value: + try: + if django.VERSION < (3, 0): + v = f.from_db_value(v, None, None, None) + else: + v = f.from_db_value(v, None, None) + except Exception: + raise ImproperlyConfigured( + "Unable to auto serialize field '{}', custom" + " serialization override required".format(k) + ) +~~ except FieldDoesNotExist: + pass + setattr(ret, k, v) + return ret + + +def set_form_field_order(form, field_order): + if field_order is None: + return + fields = OrderedDict() + for key in field_order: + try: + fields[key] = form.fields.pop(key) + except KeyError: # ignore unknown fields + pass + fields.update(form.fields) # add remaining fields in original order + form.fields = fields + + +def build_absolute_uri(request, location, protocol=None): + from .account import app_settings as account_settings + + if request is None: + site = Site.objects.get_current() + bits = urlsplit(location) + + +## ... source file continues with no further FieldDoesNotExist examples... + +``` + + +## Example 3 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / utils.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./utils.py) + +```python +# utils.py +import warnings +from collections import OrderedDict + +from django.conf import settings +~~from django.core.exceptions import FieldDoesNotExist, FieldError +from django.db import models +from django.db.models.constants import LOOKUP_SEP +from django.db.models.expressions import Expression +from django.db.models.fields.related import ForeignObjectRel, RelatedField +from django.utils import timezone +from django.utils.encoding import force_str +from django.utils.text import capfirst +from django.utils.translation import gettext as _ + +from .exceptions import FieldLookupError + + +def deprecate(msg, level_modifier=0): + warnings.warn(msg, MigrationNotice, stacklevel=3 + level_modifier) + + +class MigrationNotice(DeprecationWarning): + url = 'https://django-filter.readthedocs.io/en/master/guide/migration.html' + + def __init__(self, message): + super().__init__('%s See: %s' % (message, self.url)) + + +class RenameAttributesBase(type): + + +## ... source file abbreviated to get to FieldDoesNotExist examples ... + + + + +def get_all_model_fields(model): + opts = model._meta + + return [ + f.name for f in sorted(opts.fields + opts.many_to_many) + if not isinstance(f, models.AutoField) and + not (getattr(f.remote_field, 'parent_link', False)) + ] + + +def get_model_field(model, field_name): + fields = get_field_parts(model, field_name) + return fields[-1] if fields else None + + +def get_field_parts(model, field_name): + parts = field_name.split(LOOKUP_SEP) + opts = model._meta + fields = [] + + for name in parts: + try: + field = opts.get_field(name) +~~ except FieldDoesNotExist: + return None + + fields.append(field) + if isinstance(field, RelatedField): + opts = field.remote_field.model._meta + elif isinstance(field, ForeignObjectRel): + opts = field.related_model._meta + + return fields + + +def resolve_field(model_field, lookup_expr): + query = model_field.model._default_manager.all().query + lhs = Expression(model_field) + lookups = lookup_expr.split(LOOKUP_SEP) + + assert len(lookups) > 0 + + try: + while lookups: + name = lookups[0] + args = (lhs, name) + if len(lookups) == 1: + final_lookup = lhs.get_lookup(name) + + +## ... source file continues with no further FieldDoesNotExist examples... + +``` + + +## Example 4 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / managers.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./managers.py) + +```python +# managers.py +~~from django.core.exceptions import FieldDoesNotExist +from django.db import models +from django.db.models import Q +from guardian.core import ObjectPermissionChecker +from guardian.ctypes import get_content_type +from guardian.exceptions import ObjectNotPersisted +from django.contrib.auth.models import Permission + +import warnings + + +class BaseObjectPermissionManager(models.Manager): + + @property + def user_or_group_field(self): + try: + self.model._meta.get_field('user') + return 'user' +~~ except FieldDoesNotExist: + return 'group' + + def is_generic(self): + try: + self.model._meta.get_field('object_pk') + return True +~~ except FieldDoesNotExist: + return False + + def assign_perm(self, perm, user_or_group, obj): + if getattr(obj, 'pk', None) is None: + raise ObjectNotPersisted("Object %s needs to be persisted first" + % obj) + ctype = get_content_type(obj) + if not isinstance(perm, Permission): + permission = Permission.objects.get(content_type=ctype, codename=perm) + else: + permission = perm + + kwargs = {'permission': permission, self.user_or_group_field: user_or_group} + if self.is_generic(): + kwargs['content_type'] = ctype + kwargs['object_pk'] = obj.pk + else: + kwargs['content_object'] = obj + obj_perm, _ = self.get_or_create(**kwargs) + return obj_perm + + def bulk_assign_perm(self, perm, user_or_group, queryset): + if isinstance(queryset, list): + ctype = get_content_type(queryset[0]) + + +## ... source file continues with no further FieldDoesNotExist examples... + +``` + + +## Example 5 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / resources.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./resources.py) + +```python +# resources.py +import django +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.core.management.color import no_style +from django.core.paginator import Paginator +from django.db import DEFAULT_DB_ALIAS, connections +from django.db.models.fields.related import ForeignObjectRel +from django.db.models.query import QuerySet +from django.db.transaction import ( + TransactionManagementError, + atomic, + savepoint, + savepoint_commit, + savepoint_rollback +) +from django.utils.encoding import force_str +from django.utils.safestring import mark_safe + +from . import widgets +from .fields import Field +from .instance_loaders import ModelInstanceLoader +from .results import Error, Result, RowResult +from .utils import atomic_if_using_transaction + +if django.VERSION[0] >= 3: +~~ from django.core.exceptions import FieldDoesNotExist +else: + from django.db.models.fields import FieldDoesNotExist + + +logger = logging.getLogger(__name__) +logger.addHandler(logging.NullHandler()) + +USE_TRANSACTIONS = getattr(settings, 'IMPORT_EXPORT_USE_TRANSACTIONS', True) +CHUNK_SIZE = getattr(settings, 'IMPORT_EXPORT_CHUNK_SIZE', 1) + + +def get_related_model(field): + if hasattr(field, 'related_model'): + return field.related_model + if field.rel: + return field.rel.to + + +class ResourceOptions: + + model = None + fields = None + + exclude = None + + +## ... source file abbreviated to get to FieldDoesNotExist examples ... + + + continue + + field = new_class.field_from_django_field(f.name, f, + readonly=False) + field_list.append((f.name, field, )) + + new_class.fields.update(OrderedDict(field_list)) + + if opts.fields is not None: + field_list = [] + for field_name in opts.fields: + if field_name in declared_fields: + continue + if field_name.find('__') == -1: + continue + + model = opts.model + attrs = field_name.split('__') + for i, attr in enumerate(attrs): + verbose_path = ".".join([opts.model.__name__] + attrs[0:i+1]) + + try: + f = model._meta.get_field(attr) +~~ except FieldDoesNotExist as e: + logger.debug(e, exc_info=e) +~~ raise FieldDoesNotExist( + "%s: %s has no field named '%s'" % + (verbose_path, model.__name__, attr)) + + if i < len(attrs) - 1: + if isinstance(f, ForeignObjectRel): + model = get_related_model(f) + else: + if get_related_model(f) is None: + raise KeyError( + '%s is not a relation' % verbose_path) + model = get_related_model(f) + + if isinstance(f, ForeignObjectRel): + f = f.field + + field = new_class.field_from_django_field(field_name, f, + readonly=True) + field_list.append((field_name, field)) + + new_class.fields.update(OrderedDict(field_list)) + + return new_class + + + continue + if f.name in declared_fields: + + +## ... source file continues with no further FieldDoesNotExist examples... + +``` + + +## Example 6 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / serializers.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./serializers.py) + +```python +# serializers.py +import copy +import inspect +import traceback +from collections import OrderedDict, defaultdict +from collections.abc import Mapping + +~~from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured +from django.core.exceptions import ValidationError as DjangoValidationError +from django.db import models +from django.db.models.fields import Field as DjangoModelField +from django.utils import timezone +from django.utils.functional import cached_property +from django.utils.translation import gettext_lazy as _ + +from rest_framework.compat import postgres_fields +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.fields import get_error_detail, set_value +from rest_framework.settings import api_settings +from rest_framework.utils import html, model_meta, representation +from rest_framework.utils.field_mapping import ( + ClassLookupDict, get_field_kwargs, get_nested_relation_kwargs, + get_relation_kwargs, get_url_kwargs +) +from rest_framework.utils.serializer_helpers import ( + BindingDict, BoundField, JSONBoundField, NestedBoundField, ReturnDict, + ReturnList +) +from rest_framework.validators import ( + UniqueForDateValidator, UniqueForMonthValidator, UniqueForYearValidator, + UniqueTogetherValidator +) + + +## ... source file abbreviated to get to FieldDoesNotExist examples ... + + + extra_kwargs[key] = value + + return extra_kwargs, hidden_fields + + def _get_model_fields(self, field_names, declared_fields, extra_kwargs): + model = getattr(self.Meta, 'model') + model_fields = {} + + for field_name in field_names: + if field_name in declared_fields: + field = declared_fields[field_name] + source = field.source or field_name + else: + try: + source = extra_kwargs[field_name]['source'] + except KeyError: + source = field_name + + if '.' in source or source == '*': + continue + + try: + field = model._meta.get_field(source) + if isinstance(field, DjangoModelField): + model_fields[source] = field +~~ except FieldDoesNotExist: + pass + + return model_fields + + + def get_validators(self): + validators = getattr(getattr(self, 'Meta', None), 'validators', None) + if validators is not None: + return list(validators) + + return ( + self.get_unique_together_validators() + + self.get_unique_for_date_validators() + ) + + def get_unique_together_validators(self): + model_class_inheritance_tree = ( + [self.Meta.model] + + list(self.Meta.model._meta.parents) + ) + + field_sources = OrderedDict( + (field.field_name, field.source) for field in self._writable_fields + if (field.source != '*') and ('.' not in field.source) + + +## ... source file continues with no further FieldDoesNotExist examples... + +``` + + +## Example 7 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / utils.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/./utils.py) + +```python +# utils.py +import inspect +import warnings +from collections import OrderedDict +from functools import total_ordering +from itertools import chain + +~~from django.core.exceptions import FieldDoesNotExist +from django.db import models +from django.utils.html import format_html_join + + +class Sequence(list): + + def expand(self, columns): + ellipses = self.count("...") + if ellipses > 1: + raise ValueError("'...' must be used at most once in a sequence.") + elif ellipses == 0: + self.append("...") + + columns = list(columns) # take a copy and exhaust the generator + head = [] + tail = [] + target = head # start by adding things to the head + for name in self: + if name == "...": + target = tail + continue + target.append(name) + if name in columns: + columns.pop(columns.index(name)) + + +## ... source file abbreviated to get to FieldDoesNotExist examples ... + + + if safe and getattr(current, "alters_data", False): + raise ValueError(self.ALTERS_DATA_ERROR_FMT.format(method=repr(current))) + if not getattr(current, "do_not_call_in_templates", False): + current = current() + if current is None: + break + return current + except Exception: + if not quiet: + raise + + @property + def bits(self): + if self == "": + return () + return self.split(self.SEPARATOR) + + def get_field(self, model): + if not hasattr(model, "_meta"): + return + + field = None + for bit in self.bits: + try: + field = model._meta.get_field(bit) +~~ except FieldDoesNotExist: + break + + if hasattr(field, "remote_field"): + rel = getattr(field, "remote_field", None) + model = getattr(rel, "model", model) + + return field + + def penultimate(self, context, quiet=True): + path, _, remainder = self.rpartition(self.SEPARATOR) + return A(path).resolve(context, quiet=quiet), remainder + + +A = Accessor # alias + + +class AttributeDict(OrderedDict): + + blacklist = ("th", "td", "_ordering", "thead", "tbody", "tfoot") + + def _iteritems(self): + for key, v in self.items(): + value = v() if callable(v) else v + if key not in self.blacklist and value is not None: + + +## ... source file continues with no further FieldDoesNotExist examples... + +``` + + +## Example 8 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / forms_account_handling.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./forms_account_handling.py) + +```python +# forms_account_handling.py +import random +import string + +import django.contrib.auth.models +from django import forms +from django.contrib.auth import get_user_model +from django.contrib.auth.forms import UserCreationForm +~~from django.core.exceptions import FieldDoesNotExist +from django.db.models.fields import CharField +from django.db.models.fields import EmailField +from django.utils.translation import gettext_lazy as _ +from wiki.conf import settings + + +def _get_field(model, field): + try: + return model._meta.get_field(field) +~~ except FieldDoesNotExist: + return + + +User = get_user_model() + + +def check_user_field(user_model): + return isinstance(_get_field(user_model, user_model.USERNAME_FIELD), CharField) + + +def check_email_field(user_model): + return isinstance( + _get_field(user_model, user_model.get_email_field_name()), EmailField + ) + + +CustomUser = ( + User + if ( + settings.ACCOUNT_HANDLING and check_user_field(User) and check_email_field(User) + ) + else django.contrib.auth.models.User +) + + + +## ... source file continues with no further FieldDoesNotExist examples... + +``` + + +## Example 9 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / admin / edit_handlers.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/admin/edit_handlers.py) + +```python +# edit_handlers.py +import functools +import re + +from django import forms +~~from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured +from django.db.models.fields import CharField, TextField +from django.forms.formsets import DELETION_FIELD_NAME, ORDERING_FIELD_NAME +from django.forms.models import fields_for_model +from django.template.loader import render_to_string +from django.utils.functional import cached_property +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy +from taggit.managers import TaggableManager + +from wagtail.admin import compare, widgets +from wagtail.core.fields import RichTextField +from wagtail.core.models import Page +from wagtail.core.utils import camelcase_to_underscore, resolve_model_string +from wagtail.utils.decorators import cached_classmethod + +from .forms.models import ( # NOQA + DIRECT_FORM_FIELD_OVERRIDES, FORM_FIELD_OVERRIDES, WagtailAdminModelForm, formfield_for_dbfield) +from .forms.pages import WagtailAdminPageForm + + +def widget_with_script(widget, script): + return mark_safe('{0}'.format(widget, script)) + + + + +## ... source file abbreviated to get to FieldDoesNotExist examples ... + + + def get_comparison_class(self): + widget_override = self.widget_overrides().get(self.field_name, None) + if widget_override and widget_override.is_hidden: + return + + try: + field = self.db_field + + if field.choices: + return compare.ChoiceFieldComparison + + if field.is_relation: + if isinstance(field, TaggableManager): + return compare.TagsFieldComparison + elif field.many_to_many: + return compare.M2MFieldComparison + + return compare.ForeignObjectComparison + + if isinstance(field, RichTextField): + return compare.RichTextFieldComparison + + if isinstance(field, (CharField, TextField)): + return compare.TextFieldComparison + +~~ except FieldDoesNotExist: + pass + + return compare.FieldComparison + + def get_comparison(self): + comparator_class = self.get_comparison_class() + + if comparator_class: + try: + return [functools.partial(comparator_class, self.db_field)] +~~ except FieldDoesNotExist: + return [] + return [] + + @cached_property + def db_field(self): + try: + model = self.model + except AttributeError: + raise ImproperlyConfigured("%r must be bound to a model before calling db_field" % self) + + return model._meta.get_field(self.field_name) + + def on_form_bound(self): + self.bound_field = self.form[self.field_name] + self.heading = self.heading or self.bound_field.label + self.help_text = self.bound_field.help_text + + def __repr__(self): + return "<%s '%s' with model=%s instance=%s request=%s form=%s>" % ( + self.__class__.__name__, self.field_name, + self.model, self.instance, self.request, self.form.__class__.__name__) + + +class RichTextFieldPanel(FieldPanel): + + +## ... source file continues with no further FieldDoesNotExist examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions-fielderror.markdown b/content/pages/examples/django/django-core-exceptions-fielderror.markdown new file mode 100644 index 000000000..e9ea93104 --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions-fielderror.markdown @@ -0,0 +1,371 @@ +title: django.core.exceptions FieldError Example Code +category: page +slug: django-core-exceptions-fielderror-examples +sortorder: 500011100 +toc: False +sidebartitle: django.core.exceptions FieldError +meta: Python example code for the FieldError class from the django.core.exceptions module of the Django project. + + +FieldError is a class within the django.core.exceptions module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / api.py**](https://github.com/divio/django-cms/blob/develop/cms/./api.py) + +```python +# api.py +import datetime + +from django.contrib.auth import get_user_model +from django.contrib.sites.models import Site +~~from django.core.exceptions import FieldError +from django.core.exceptions import PermissionDenied +from django.core.exceptions import ValidationError +from django.db import transaction +from django.template.defaultfilters import slugify +from django.template.loader import get_template +from django.utils.translation import activate + +from six import string_types + +from cms import constants +from cms.app_base import CMSApp +from cms.apphook_pool import apphook_pool +from cms.constants import TEMPLATE_INHERITANCE_MAGIC +from cms.models.pagemodel import Page +from cms.models.permissionmodels import (PageUser, PagePermission, GlobalPagePermission, + ACCESS_PAGE_AND_DESCENDANTS) +from cms.models.placeholdermodel import Placeholder +from cms.models.pluginmodel import CMSPlugin +from cms.models.titlemodels import Title +from cms.plugin_base import CMSPluginBase +from cms.plugin_pool import plugin_pool +from cms.utils import copy_plugins, get_current_site +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import get_language_list + + +## ... source file abbreviated to get to FieldError examples ... + + + + if navigation_extenders: + raw_menus = menu_pool.get_menus_by_attribute("cms_enabled", True) + menus = [menu[0] for menu in raw_menus] + assert navigation_extenders in menus + + accepted_limitations = (constants.VISIBILITY_ALL, constants.VISIBILITY_USERS, constants.VISIBILITY_ANONYMOUS) + assert limit_visibility_in_menu in accepted_limitations + + assert position in ('last-child', 'first-child', 'left', 'right') + target_node = parent.node if parent else None + + if apphook: + application_urls = _verify_apphook(apphook, apphook_namespace) + else: + application_urls = None + + if created_by and isinstance(created_by, get_user_model()): + _thread_locals.user = created_by + created_by = getattr(created_by, get_user_model().USERNAME_FIELD) + else: + _thread_locals.user = None + + if reverse_id: + if Page.objects.drafts().filter(reverse_id=reverse_id, node__site=site).exists(): +~~ raise FieldError('A page with the reverse_id="%s" already exist.' % reverse_id) + + page = Page( + created_by=created_by, + changed_by=created_by, + publication_date=publication_date, + publication_end_date=publication_end_date, + in_navigation=in_navigation, + soft_root=soft_root, + reverse_id=reverse_id, + navigation_extenders=navigation_extenders, + template=template, + application_urls=application_urls, + application_namespace=apphook_namespace, + login_required=login_required, + limit_visibility_in_menu=limit_visibility_in_menu, + xframe_options=xframe_options, + ) + page.set_tree_node(site=site, target=target_node, position=position) + page.save() + page.rescan_placeholders() + + create_title( + language=language, + title=title, + + +## ... source file continues with no further FieldError examples... + +``` + + +## Example 2 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / utils.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./utils.py) + +```python +# utils.py +import warnings +from collections import OrderedDict + +from django.conf import settings +~~from django.core.exceptions import FieldDoesNotExist, FieldError +from django.db import models +from django.db.models.constants import LOOKUP_SEP +from django.db.models.expressions import Expression +from django.db.models.fields.related import ForeignObjectRel, RelatedField +from django.utils import timezone +from django.utils.encoding import force_str +from django.utils.text import capfirst +from django.utils.translation import gettext as _ + +from .exceptions import FieldLookupError + + +def deprecate(msg, level_modifier=0): + warnings.warn(msg, MigrationNotice, stacklevel=3 + level_modifier) + + +class MigrationNotice(DeprecationWarning): + url = 'https://django-filter.readthedocs.io/en/master/guide/migration.html' + + def __init__(self, message): + super().__init__('%s See: %s' % (message, self.url)) + + +class RenameAttributesBase(type): + + +## ... source file abbreviated to get to FieldError examples ... + + + elif isinstance(field, ForeignObjectRel): + opts = field.related_model._meta + + return fields + + +def resolve_field(model_field, lookup_expr): + query = model_field.model._default_manager.all().query + lhs = Expression(model_field) + lookups = lookup_expr.split(LOOKUP_SEP) + + assert len(lookups) > 0 + + try: + while lookups: + name = lookups[0] + args = (lhs, name) + if len(lookups) == 1: + final_lookup = lhs.get_lookup(name) + if not final_lookup: + lhs = query.try_transform(*args) + final_lookup = lhs.get_lookup('exact') + return lhs.output_field, final_lookup.lookup_name + lhs = query.try_transform(*args) + lookups = lookups[1:] +~~ except FieldError as e: + raise FieldLookupError(model_field, lookup_expr) from e + + +def handle_timezone(value, is_dst=None): + if settings.USE_TZ and timezone.is_naive(value): + return timezone.make_aware(value, timezone.get_current_timezone(), is_dst) + elif not settings.USE_TZ and timezone.is_aware(value): + return timezone.make_naive(value, timezone.utc) + return value + + +def verbose_field_name(model, field_name): + if field_name is None: + return '[invalid name]' + + parts = get_field_parts(model, field_name) + if not parts: + return '[invalid name]' + + names = [] + for part in parts: + if isinstance(part, ForeignObjectRel): + if part.related_name: + names.append(part.related_name.replace('_', ' ')) + + +## ... source file continues with no further FieldError examples... + +``` + + +## Example 3 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / tracker.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./tracker.py) + +```python +# tracker.py +from copy import deepcopy +from functools import wraps + +import django +~~from django.core.exceptions import FieldError +from django.db import models +from django.db.models.fields.files import FileDescriptor +from django.db.models.query_utils import DeferredAttribute + + +class DescriptorMixin: + tracker_instance = None + + def __get__(self, instance, owner): + if instance is None: + return self + was_deferred = False + field_name = self._get_field_name() + if field_name in instance._deferred_fields: + instance._deferred_fields.remove(field_name) + was_deferred = True + value = super().__get__(instance, owner) + if was_deferred: + self.tracker_instance.saved_data[field_name] = deepcopy(value) + return value + + def _get_field_name(self): + return self.field_name + + + +## ... source file abbreviated to get to FieldError examples ... + + + else: + self.saved_data.update(**self.current(fields=fields)) + + for field, field_value in self.saved_data.items(): + self.saved_data[field] = deepcopy(field_value) + + def current(self, fields=None): + if fields is None: + deferred_fields = self.deferred_fields + if deferred_fields: + fields = [ + field for field in self.fields + if field not in deferred_fields + ] + else: + fields = self.fields + + return {f: self.get_field_value(f) for f in fields} + + def has_changed(self, field): + if field in self.fields: + if field in self.deferred_fields and field not in self.instance.__dict__: + return False + return self.previous(field) != self.get_field_value(field) + else: +~~ raise FieldError('field "%s" not tracked' % field) + + def previous(self, field): + + if self.instance.pk and field in self.deferred_fields and field not in self.saved_data: + + if field not in self.instance.__dict__: + self.get_field_value(field) + + else: + current_value = self.get_field_value(field) + self.instance.refresh_from_db(fields=[field]) + self.saved_data[field] = deepcopy(self.get_field_value(field)) + setattr(self.instance, self.field_map[field], current_value) + + return self.saved_data.get(field) + + def changed(self): + return { + field: self.previous(field) + for field in self.fields + if self.has_changed(field) + } + + def init_deferred_fields(self): + + +## ... source file abbreviated to get to FieldError examples ... + + + field for field in update_fields if + field in self.fields + ) + getattr(instance, self.attname).set_saved_fields( + fields=fields + ) + return ret + + setattr(model, method, inner) + + def __get__(self, instance, owner): + if instance is None: + return self + else: + return getattr(instance, self.attname) + + +class ModelInstanceTracker(FieldInstanceTracker): + + def has_changed(self, field): + if not self.instance.pk: + return True + elif field in self.saved_data: + return self.previous(field) != self.get_field_value(field) + else: +~~ raise FieldError('field "%s" not tracked' % field) + + def changed(self): + if not self.instance.pk: + return {} + saved = self.saved_data.items() + current = self.current() + return {k: v for k, v in saved if v != current[k]} + + +class ModelTracker(FieldTracker): + tracker_class = ModelInstanceTracker + + def get_field_map(self, cls): + return {field: field for field in self.fields} + + + +## ... source file continues with no further FieldError examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions-improperlyconfigured.markdown b/content/pages/examples/django/django-core-exceptions-improperlyconfigured.markdown index d38b11d7a..8b4c0bcb0 100644 --- a/content/pages/examples/django/django-core-exceptions-improperlyconfigured.markdown +++ b/content/pages/examples/django/django-core-exceptions-improperlyconfigured.markdown @@ -1,6 +1,6 @@ title: django.core.exceptions ImproperlyConfigured Example Code category: page -slug: django-core-exceptions-improperlyconfigured +slug: django-core-exceptions-improperlyconfigured-examples sortorder: 500012505 toc: False sidebartitle: django.core.exceptions ImproperlyConfigured diff --git a/content/pages/examples/django/django-core-exceptions-middlewarenotused.markdown b/content/pages/examples/django/django-core-exceptions-middlewarenotused.markdown new file mode 100644 index 000000000..d93d2e380 --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions-middlewarenotused.markdown @@ -0,0 +1,122 @@ +title: django.core.exceptions MiddlewareNotUsed Example Code +category: page +slug: django-core-exceptions-middlewarenotused-examples +sortorder: 500011102 +toc: False +sidebartitle: django.core.exceptions MiddlewareNotUsed +meta: Python example code for the MiddlewareNotUsed class from the django.core.exceptions module of the Django project. + + +MiddlewareNotUsed is a class within the django.core.exceptions module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / middleware.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./middleware.py) + +```python +# middleware.py +~~from django.core.exceptions import MiddlewareNotUsed +from django.utils.encoding import DjangoUnicodeDecodeError +from django.utils.html import strip_spaces_between_tags as minify_html + +from pipeline.conf import settings + +from django.utils.deprecation import MiddlewareMixin + + +class MinifyHTMLMiddleware(MiddlewareMixin): + def __init__(self, *args, **kwargs): + super(MinifyHTMLMiddleware, self).__init__(*args, **kwargs) + if not settings.PIPELINE_ENABLED: +~~ raise MiddlewareNotUsed + + def process_response(self, request, response): + if response.has_header('Content-Type') and 'text/html' in response['Content-Type']: + try: + response.content = minify_html(response.content.decode('utf-8').strip()) + response['Content-Length'] = str(len(response.content)) + except DjangoUnicodeDecodeError: + pass + return response + + + +## ... source file continues with no further MiddlewareNotUsed examples... + +``` + + +## Example 2 from django-user-visit +[django-user-visit](https://github.com/yunojuno/django-user-visit) +([PyPI package information](https://pypi.org/project/django-user-visit/)) +is a [Django](/django.html) app and +[middleware](https://docs.djangoproject.com/en/stable/topics/http/middleware/) +for tracking daily user visits to your web application. The goal +is to record per user per day instead of for every request a user +sends to the application. The project is provided as open source +under the +[MIT license](https://github.com/yunojuno/django-user-visit/blob/master/LICENSE). + +[**django-user-visit / user_visit / middleware.py**](https://github.com/yunojuno/django-user-visit/blob/master/user_visit/./middleware.py) + +```python +# middleware.py +import logging +import typing + +import django.db +~~from django.core.exceptions import MiddlewareNotUsed +from django.http import HttpRequest, HttpResponse +from django.utils import timezone + +from user_visit.models import UserVisit + +from .settings import RECORDING_DISABLED + +logger = logging.getLogger(__name__) + +SESSION_KEY = "user_visit.hash" + + +class UserVisitMiddleware: + + def __init__(self, get_response: typing.Callable) -> None: + if RECORDING_DISABLED: +~~ raise MiddlewareNotUsed("UserVisit recording has been disabled") + self.get_response = get_response + + def __call__(self, request: HttpRequest) -> typing.Optional[HttpResponse]: + if request.user.is_anonymous: + return self.get_response(request) + + uv = UserVisit.objects.build(request, timezone.now()) + if request.session.get(SESSION_KEY, "") == uv.hash: + return self.get_response(request) + + try: + uv.save() + except django.db.IntegrityError: + logger.warning("Unable to record user visit - duplicate request hash") + else: + request.session[SESSION_KEY] = uv.hash + return self.get_response(request) + + + +## ... source file continues with no further MiddlewareNotUsed examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions-non-field-errors.markdown b/content/pages/examples/django/django-core-exceptions-non-field-errors.markdown new file mode 100644 index 000000000..0421e6dd7 --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions-non-field-errors.markdown @@ -0,0 +1,158 @@ +title: django.core.exceptions NON_FIELD_ERRORS Example Code +category: page +slug: django-core-exceptions-non-field-errors-examples +sortorder: 500011103 +toc: False +sidebartitle: django.core.exceptions NON_FIELD_ERRORS +meta: Python example code for the NON_FIELD_ERRORS constant from the django.core.exceptions module of the Django project. + + +NON_FIELD_ERRORS is a constant within the django.core.exceptions module of the Django project. + + +## Example 1 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / results.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./results.py) + +```python +# results.py +from collections import OrderedDict +from tablib import Dataset + +~~from django.core.exceptions import NON_FIELD_ERRORS + + +class Error: + def __init__(self, error, traceback=None, row=None): + self.error = error + self.traceback = traceback + self.row = row + + +class RowResult: + IMPORT_TYPE_UPDATE = 'update' + IMPORT_TYPE_NEW = 'new' + IMPORT_TYPE_DELETE = 'delete' + IMPORT_TYPE_SKIP = 'skip' + IMPORT_TYPE_ERROR = 'error' + IMPORT_TYPE_INVALID = 'invalid' + + valid_import_types = frozenset([ + IMPORT_TYPE_NEW, + IMPORT_TYPE_UPDATE, + IMPORT_TYPE_DELETE, + IMPORT_TYPE_SKIP, + ]) + + + +## ... source file abbreviated to get to NON_FIELD_ERRORS examples ... + + + self.diff = None + self.import_type = None + self.raw_values = {} + + +class InvalidRow: + + def __init__(self, number, validation_error, values): + self.number = number + self.error = validation_error + self.values = values + try: + self.error_dict = validation_error.message_dict + except AttributeError: + self.error_dict = {NON_FIELD_ERRORS: validation_error.messages} + + @property + def field_specific_errors(self): + return { + key: value for key, value in self.error_dict.items() + if key != NON_FIELD_ERRORS + } + + @property + def non_field_specific_errors(self): +~~ return self.error_dict.get(NON_FIELD_ERRORS, []) + + @property + def error_count(self): + count = 0 + for error_list in self.error_dict.values(): + count += len(error_list) + return count + + +class Result: + def __init__(self, *args, **kwargs): + super().__init__() + self.base_errors = [] + self.diff_headers = [] + self.rows = [] # RowResults + self.invalid_rows = [] # InvalidRow + self.failed_dataset = Dataset() + self.totals = OrderedDict([(RowResult.IMPORT_TYPE_NEW, 0), + (RowResult.IMPORT_TYPE_UPDATE, 0), + (RowResult.IMPORT_TYPE_DELETE, 0), + (RowResult.IMPORT_TYPE_SKIP, 0), + (RowResult.IMPORT_TYPE_ERROR, 0), + (RowResult.IMPORT_TYPE_INVALID, 0)]) + self.total_rows = 0 + + +## ... source file continues with no further NON_FIELD_ERRORS examples... + +``` + + +## Example 2 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / admin / messages.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/admin/messages.py) + +```python +# messages.py +from django.contrib import messages +~~from django.core.exceptions import NON_FIELD_ERRORS +from django.template.loader import render_to_string +from django.utils.html import format_html, format_html_join + + +def render(message, buttons, detail=''): + return render_to_string('wagtailadmin/shared/messages.html', { + 'message': message, + 'buttons': buttons, + 'detail': detail, + }) + + +def debug(request, message, buttons=None, extra_tags=''): + return messages.debug(request, render(message, buttons), extra_tags=extra_tags) + + +def info(request, message, buttons=None, extra_tags=''): + return messages.info(request, render(message, buttons), extra_tags=extra_tags) + + +def success(request, message, buttons=None, extra_tags=''): + return messages.success(request, render(message, buttons), extra_tags=extra_tags) + + + + +## ... source file continues with no further NON_FIELD_ERRORS examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions-objectdoesnotexist.markdown b/content/pages/examples/django/django-core-exceptions-objectdoesnotexist.markdown new file mode 100644 index 000000000..755ef4441 --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions-objectdoesnotexist.markdown @@ -0,0 +1,969 @@ +title: django.core.exceptions ObjectDoesNotExist Example Code +category: page +slug: django-core-exceptions-objectdoesnotexist-examples +sortorder: 500011104 +toc: False +sidebartitle: django.core.exceptions ObjectDoesNotExist +meta: Python example code for the ObjectDoesNotExist class from the django.core.exceptions module of the Django project. + + +ObjectDoesNotExist is a class within the django.core.exceptions module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog / diff.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog/diff.py) + +```python +# diff.py +from __future__ import unicode_literals + +from django.conf import settings +~~from django.core.exceptions import ObjectDoesNotExist +from django.db.models import Model, NOT_PROVIDED, DateTimeField +from django.utils import timezone +from django.utils.encoding import smart_text + + +def track_field(field): + from auditlog.models import LogEntry + if field.many_to_many: + return False + + if getattr(field, 'remote_field', None) is not None and field.remote_field.model == LogEntry: + return False + + elif getattr(field, 'rel', None) is not None and field.rel.to == LogEntry: + return False + + return True + + +def get_fields_in_model(instance): + assert isinstance(instance, Model) + + use_api = hasattr(instance._meta, 'get_fields') and callable(instance._meta.get_fields) + + if use_api: + return [f for f in instance._meta.get_fields() if track_field(f)] + return instance._meta.fields + + +def get_field_value(obj, field): + if isinstance(field, DateTimeField): + try: + value = field.to_python(getattr(obj, field.name, None)) + if value is not None and settings.USE_TZ and not timezone.is_naive(value): + value = timezone.make_naive(value, timezone=timezone.utc) +~~ except ObjectDoesNotExist: + value = field.default if field.default is not NOT_PROVIDED else None + else: + try: + value = smart_text(getattr(obj, field.name, None)) +~~ except ObjectDoesNotExist: + value = field.default if field.default is not NOT_PROVIDED else None + + return value + + +def model_instance_diff(old, new): + from auditlog.registry import auditlog + + if not(old is None or isinstance(old, Model)): + raise TypeError("The supplied old instance is not a valid model instance.") + if not(new is None or isinstance(new, Model)): + raise TypeError("The supplied new instance is not a valid model instance.") + + diff = {} + + if old is not None and new is not None: + fields = set(old._meta.fields + new._meta.fields) + model_fields = auditlog.get_model_fields(new._meta.model) + elif old is not None: + fields = set(get_fields_in_model(old)) + model_fields = auditlog.get_model_fields(old._meta.model) + elif new is not None: + fields = set(get_fields_in_model(new)) + model_fields = auditlog.get_model_fields(new._meta.model) + + +## ... source file continues with no further ObjectDoesNotExist examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / test_utils / testcases.py**](https://github.com/divio/django-cms/blob/develop/cms/test_utils/testcases.py) + +```python +# testcases.py +import json +import sys +import warnings + +from django.conf import settings +from django.contrib.auth import get_user_model +from django.contrib.auth.models import AnonymousUser, Permission +from django.contrib.sites.models import Site +from django.core.cache import cache +~~from django.core.exceptions import ObjectDoesNotExist +from django.forms.models import model_to_dict +from django.template import engines +from django.template.context import Context +from django.test import testcases +from django.test.client import RequestFactory +from django.urls import reverse +from django.utils.http import urlencode +from django.utils.timezone import now +from django.utils.translation import activate +from menus.menu_pool import menu_pool + +from six.moves.urllib.parse import unquote, urljoin + +from cms.api import create_page +from cms.constants import ( + PUBLISHER_STATE_DEFAULT, + PUBLISHER_STATE_DIRTY, + PUBLISHER_STATE_PENDING, +) +from cms.plugin_rendering import ContentRenderer, StructureRenderer +from cms.models import Page +from cms.models.permissionmodels import ( + GlobalPagePermission, + PagePermission, + + +## ... source file abbreviated to get to ObjectDoesNotExist examples ... + + + page_data['pagepermission_set-2-TOTAL_FORMS'] = 0 + page_data['pagepermission_set-2-INITIAL_FORMS'] = 0 + page_data['pagepermission_set-2-MAX_NUM_FORMS'] = 0 + return page_data + + def print_page_structure(self, qs): + for page in qs.order_by('path'): + ident = " " * page.level + print(u"%s%s (%s), path: %s, depth: %s, numchild: %s" % (ident, page, + page.pk, page.path, page.depth, page.numchild)) + + def print_node_structure(self, nodes, *extra): + def _rec(nodes, level=0): + ident = level * ' ' + for node in nodes: + raw_attrs = [(bit, getattr(node, bit, node.attr.get(bit, "unknown"))) for bit in extra] + attrs = ', '.join(['%s: %r' % data for data in raw_attrs]) + print(u"%s%s: %s" % (ident, node.title, attrs)) + _rec(node.children, level + 1) + + _rec(nodes) + + def assertObjectExist(self, qs, **filter): + try: + return qs.get(**filter) +~~ except ObjectDoesNotExist: + pass + raise self.failureException("ObjectDoesNotExist raised for filter %s" % filter) + + def assertObjectDoesNotExist(self, qs, **filter): + try: + qs.get(**filter) +~~ except ObjectDoesNotExist: + return + raise self.failureException("ObjectDoesNotExist not raised for filter %s" % filter) + + def copy_page(self, page, target_page, position=0, target_site=None): + from cms.utils.page import get_available_slug + + if target_site is None: + target_site = target_page.node.site + + data = { + 'position': position, + 'target': target_page.pk, + 'source_site': page.node.site_id, + 'copy_permissions': 'on', + 'copy_moderation': 'on', + } + source_translation = page.title_set.all()[0] + parent_translation = target_page.title_set.all()[0] + language = source_translation.language + copied_page_path = source_translation.get_path_for_base(parent_translation.path) + new_page_slug = get_available_slug(target_site, copied_page_path, language) + + with self.settings(SITE_ID=target_site.pk): + response = self.client.post(URL_CMS_PAGE + "%d/copy-page/" % page.pk, data) + + +## ... source file continues with no further ObjectDoesNotExist examples... + +``` + + +## Example 3 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / fields / folder.py**](https://github.com/divio/django-filer/blob/develop/filer/fields/folder.py) + +```python +# folder.py +from __future__ import absolute_import + +import warnings + +from django import forms +from django.contrib.admin.sites import site +from django.contrib.admin.widgets import ForeignKeyRawIdWidget +~~from django.core.exceptions import ObjectDoesNotExist +from django.db import models +from django.template.loader import render_to_string +from django.urls import reverse +from django.utils.http import urlencode +from django.utils.safestring import mark_safe + +from ..models import Folder +from ..utils.compatibility import truncate_words +from ..utils.model_label import get_model_label + + +class AdminFolderWidget(ForeignKeyRawIdWidget): + choices = None + input_type = 'hidden' + is_hidden = False + + def render(self, name, value, attrs=None, renderer=None): + obj = self.obj_for_value(value) + css_id = attrs.get('id') + css_id_folder = "%s_folder" % css_id + css_id_description_txt = "%s_description_txt" % css_id + if attrs is None: + attrs = {} + related_url = None + + +## ... source file abbreviated to get to ObjectDoesNotExist examples ... + + + context = { + 'hidden_input': hidden_input, + 'lookup_url': '%s%s' % (related_url, url), + 'lookup_name': name, + 'span_id': css_id_description_txt, + 'object': obj, + 'clear_id': '%s_clear' % css_id, + 'descid': css_id_description_txt, + 'noimg': 'filer/icons/nofile_32x32.png', + 'foldid': css_id_folder, + 'id': css_id, + } + html = render_to_string('admin/filer/widgets/admin_folder.html', context) + return mark_safe(html) + + def label_for_value(self, value): + obj = self.obj_for_value(value) + return ' %s' % truncate_words(obj, 14) + + def obj_for_value(self, value): + if not value: + return None + try: + key = self.rel.get_related_field().name + obj = self.rel.model._default_manager.get(**{key: value}) +~~ except ObjectDoesNotExist: + obj = None + return obj + + class Media(object): + js = ( + 'filer/js/addons/popup_handling.js', + ) + + +class AdminFolderFormField(forms.ModelChoiceField): + widget = AdminFolderWidget + + def __init__(self, rel, queryset, to_field_name, *args, **kwargs): + self.rel = rel + self.queryset = queryset + self.limit_choices_to = kwargs.pop('limit_choices_to', None) + self.to_field_name = to_field_name + self.max_value = None + self.min_value = None + kwargs.pop('widget', None) + forms.Field.__init__(self, widget=self.widget(rel, site), *args, **kwargs) + + def widget_attrs(self, widget): + widget.required = self.required + + +## ... source file continues with no further ObjectDoesNotExist examples... + +``` + + +## Example 4 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / utils.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./utils.py) + +```python +# utils.py +import logging +import os +from itertools import chain + +from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model +from django.contrib.auth.models import AnonymousUser, Group +~~from django.core.exceptions import ObjectDoesNotExist, PermissionDenied +from django.db.models import Model, QuerySet +from django.http import HttpResponseForbidden, HttpResponseNotFound +from django.shortcuts import render +from guardian.conf import settings as guardian_settings +from guardian.ctypes import get_content_type +from guardian.exceptions import NotUserNorGroup + +logger = logging.getLogger(__name__) +abspath = lambda *p: os.path.abspath(os.path.join(*p)) + + +def get_anonymous_user(): + User = get_user_model() + lookup = {User.USERNAME_FIELD: guardian_settings.ANONYMOUS_USER_NAME} + return User.objects.get(**lookup) + + +def get_identity(identity): + if isinstance(identity, AnonymousUser): + identity = get_anonymous_user() + + if isinstance(identity, QuerySet): + identity_model_type = identity.model + if identity_model_type == get_user_model(): + + +## ... source file abbreviated to get to ObjectDoesNotExist examples ... + + + redirect_field_name = redirect_field_name or REDIRECT_FIELD_NAME + + + has_permissions = False + if accept_global_perms: + has_permissions = all(request.user.has_perm(perm) for perm in perms) + if not has_permissions: + has_permissions = all(request.user.has_perm(perm, obj) + for perm in perms) + + if not has_permissions: + if return_403: + if guardian_settings.RENDER_403: + response = render(request, guardian_settings.TEMPLATE_403) + response.status_code = 403 + return response + elif guardian_settings.RAISE_403: + raise PermissionDenied + return HttpResponseForbidden() + if return_404: + if guardian_settings.RENDER_404: + response = render(request, guardian_settings.TEMPLATE_404) + response.status_code = 404 + return response + elif guardian_settings.RAISE_404: +~~ raise ObjectDoesNotExist + return HttpResponseNotFound() + else: + from django.contrib.auth.views import redirect_to_login + return redirect_to_login(request.get_full_path(), + login_url, + redirect_field_name) + + +from django.apps import apps as django_apps +from django.core.exceptions import ImproperlyConfigured + +def get_obj_perm_model_by_conf(setting_name): + try: + setting_value = getattr(guardian_settings, setting_name) + return django_apps.get_model(setting_value, require_ready=False) + except ValueError as e: + raise ImproperlyConfigured("{} must be of the form 'app_label.model_name'".format(setting_value)) from e + except LookupError as e: + raise ImproperlyConfigured( + "{} refers to model '{}' that has not been installed".format(setting_name, setting_value) + ) from e + + +def clean_orphan_obj_perms(): + + +## ... source file continues with no further ObjectDoesNotExist examples... + +``` + + +## Example 5 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / models.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./models.py) + +```python +# models.py + +~~from django.core.exceptions import ObjectDoesNotExist +from django.utils.encoding import force_str +from django.utils.text import capfirst + +from haystack.constants import DEFAULT_ALIAS +from haystack.exceptions import NotHandled, SpatialError +from haystack.utils import log as logging +from haystack.utils.app_loading import haystack_get_model + +try: + from geopy import distance as geopy_distance +except ImportError: + geopy_distance = None + + +class SearchResult(object): + + def __init__(self, app_label, model_name, pk, score, **kwargs): + self.app_label, self.model_name = app_label, model_name + self.pk = pk + self.score = score + self._object = None + self._model = None + self._verbose_name = None + self._additional_fields = [] + + +## ... source file abbreviated to get to ObjectDoesNotExist examples ... + + + return self.__dict__.get(attr, None) + + def _get_searchindex(self): + from haystack import connections + + return connections[DEFAULT_ALIAS].get_unified_index().get_index(self.model) + + searchindex = property(_get_searchindex) + + def _get_object(self): + if self._object is None: + if self.model is None: + self.log.error("Model could not be found for SearchResult '%s'.", self) + return None + + try: + try: + self._object = self.searchindex.read_queryset().get(pk=self.pk) + except NotHandled: + self.log.warning( + "Model '%s.%s' not handled by the routers.", + self.app_label, + self.model_name, + ) + self._object = self.model._default_manager.get(pk=self.pk) +~~ except ObjectDoesNotExist: + self.log.error( + "Object could not be found in database for SearchResult '%s'.", self + ) + self._object = None + + return self._object + + def _set_object(self, obj): + self._object = obj + + object = property(_get_object, _set_object) + + def _get_model(self): + if self._model is None: + try: + self._model = haystack_get_model(self.app_label, self.model_name) + except LookupError: + pass + + return self._model + + def _set_model(self, obj): + self._model = obj + + + +## ... source file continues with no further ObjectDoesNotExist examples... + +``` + + +## Example 6 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / fields.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./fields.py) + +```python +# fields.py +~~from django.core.exceptions import ObjectDoesNotExist +from django.db.models.fields import NOT_PROVIDED +from django.db.models.manager import Manager + +from . import widgets + + +class Field: + empty_values = [None, ''] + + def __init__(self, attribute=None, column_name=None, widget=None, + default=NOT_PROVIDED, readonly=False, saves_null_values=True): + self.attribute = attribute + self.default = default + self.column_name = column_name + if not widget: + widget = widgets.Widget() + self.widget = widget + self.readonly = readonly + self.saves_null_values = saves_null_values + + def __repr__(self): + path = '%s.%s' % (self.__class__.__module__, self.__class__.__name__) + column_name = getattr(self, 'column_name', None) + if column_name is not None: + + +## ... source file abbreviated to get to ObjectDoesNotExist examples ... + + + try: + value = data[self.column_name] + except KeyError: + raise KeyError("Column '%s' not found in dataset. Available " + "columns are: %s" % (self.column_name, list(data))) + + value = self.widget.clean(value, row=data) + + if value in self.empty_values and self.default != NOT_PROVIDED: + if callable(self.default): + return self.default() + return self.default + + return value + + def get_value(self, obj): + if self.attribute is None: + return None + + attrs = self.attribute.split('__') + value = obj + + for attr in attrs: + try: + value = getattr(value, attr, None) +~~ except (ValueError, ObjectDoesNotExist): + return None + if value is None: + return None + + if callable(value) and not isinstance(value, Manager): + value = value() + return value + + def save(self, obj, data, is_m2m=False): + if not self.readonly: + attrs = self.attribute.split('__') + for attr in attrs[:-1]: + obj = getattr(obj, attr, None) + cleaned = self.clean(data) + if cleaned is not None or self.saves_null_values: + if not is_m2m: + setattr(obj, attrs[-1], cleaned) + else: + getattr(obj, attrs[-1]).set(cleaned) + + def export(self, obj): + value = self.get_value(obj) + if value is None: + return "" + + +## ... source file continues with no further ObjectDoesNotExist examples... + +``` + + +## Example 7 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / managers.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./managers.py) + +```python +# managers.py +import django +~~from django.core.exceptions import ObjectDoesNotExist +from django.db import connection +from django.db import models +from django.db.models.constants import LOOKUP_SEP +from django.db.models.fields.related import OneToOneField, OneToOneRel +from django.db.models.query import ModelIterable +from django.db.models.query import QuerySet +from django.db.models.sql.datastructures import Join + + +class InheritanceIterable(ModelIterable): + def __iter__(self): + queryset = self.queryset + iter = ModelIterable(queryset) + if getattr(queryset, 'subclasses', False): + extras = tuple(queryset.query.extra.keys()) + subclasses = sorted(queryset.subclasses, key=len, reverse=True) + for obj in iter: + sub_obj = None + for s in subclasses: + sub_obj = queryset._get_sub_obj_recurse(obj, s) + if sub_obj: + break + if not sub_obj: + sub_obj = obj + + +## ... source file abbreviated to get to ObjectDoesNotExist examples ... + + + def _get_ancestors_path(self, model, levels=None): + if not issubclass(model, self.model): + raise ValueError( + "{!r} is not a subclass of {!r}".format(model, self.model)) + + ancestry = [] + parent_link = model._meta.get_ancestor_link(self.model) + if levels: + levels -= 1 + while parent_link is not None: + related = parent_link.remote_field + ancestry.insert(0, related.get_accessor_name()) + if levels or levels is None: + parent_model = related.model + parent_link = parent_model._meta.get_ancestor_link( + self.model) + else: + parent_link = None + return LOOKUP_SEP.join(ancestry) + + def _get_sub_obj_recurse(self, obj, s): + rel, _, s = s.partition(LOOKUP_SEP) + + try: + node = getattr(obj, rel) +~~ except ObjectDoesNotExist: + return None + if s: + child = self._get_sub_obj_recurse(node, s) + return child + else: + return node + + def get_subclass(self, *args, **kwargs): + return self.select_subclasses().get(*args, **kwargs) + + +class InheritanceQuerySet(InheritanceQuerySetMixin, QuerySet): + def instance_of(self, *models): + + + + where_queries = [] + for model in models: + where_queries.append('(' + ' AND '.join([ + '"{}"."{}" IS NOT NULL'.format( + model._meta.db_table, + field.attname, # Should this be something else? + ) for field in model._meta.parents.values() + ]) + ')') + + +## ... source file continues with no further ObjectDoesNotExist examples... + +``` + + +## Example 8 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / oauth2_validators.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./oauth2_validators.py) + +```python +# oauth2_validators.py +import base64 +import binascii +import http.client +import logging +from collections import OrderedDict +from datetime import datetime, timedelta +from urllib.parse import unquote_plus + +import requests +from django.conf import settings +from django.contrib.auth import authenticate, get_user_model +~~from django.core.exceptions import ObjectDoesNotExist +from django.db import transaction +from django.db.models import Q +from django.utils import timezone +from django.utils.timezone import make_aware +from django.utils.translation import gettext_lazy as _ +from oauthlib.oauth2 import RequestValidator + +from .exceptions import FatalClientError +from .models import ( + AbstractApplication, get_access_token_model, + get_application_model, get_grant_model, get_refresh_token_model +) +from .scopes import get_scopes_backend +from .settings import oauth2_settings + + +log = logging.getLogger("oauth2_provider") + +GRANT_TYPE_MAPPING = { + "authorization_code": (AbstractApplication.GRANT_AUTHORIZATION_CODE, ), + "password": (AbstractApplication.GRANT_PASSWORD, ), + "client_credentials": (AbstractApplication.GRANT_CLIENT_CREDENTIALS, ), + "refresh_token": ( + AbstractApplication.GRANT_AUTHORIZATION_CODE, + + +## ... source file abbreviated to get to ObjectDoesNotExist examples ... + + + scope=" ".join(request.scopes), + code_challenge=request.code_challenge or "", + code_challenge_method=request.code_challenge_method or "" + ) + + def _create_refresh_token(self, request, refresh_token_code, access_token): + return RefreshToken.objects.create( + user=request.user, + token=refresh_token_code, + application=request.client, + access_token=access_token + ) + + def revoke_token(self, token, token_type_hint, request, *args, **kwargs): + if token_type_hint not in ["access_token", "refresh_token"]: + token_type_hint = None + + token_types = { + "access_token": AccessToken, + "refresh_token": RefreshToken, + } + + token_type = token_types.get(token_type_hint, AccessToken) + try: + token_type.objects.get(token=token).revoke() +~~ except ObjectDoesNotExist: + for other_type in [_t for _t in token_types.values() if _t != token_type]: + list(map(lambda t: t.revoke(), other_type.objects.filter(token=token))) + + def validate_user(self, username, password, client, request, *args, **kwargs): + u = authenticate(username=username, password=password) + if u is not None and u.is_active: + request.user = u + return True + return False + + def get_original_scopes(self, refresh_token, request, *args, **kwargs): + rt = request.refresh_token_instance + if not rt.access_token_id: + return AccessToken.objects.get(source_refresh_token_id=rt.id).scope + + return rt.access_token.scope + + def validate_refresh_token(self, refresh_token, client, request, *args, **kwargs): + + null_or_recent = Q(revoked__isnull=True) | Q( + revoked__gt=timezone.now() - timedelta( + seconds=oauth2_settings.REFRESH_TOKEN_GRACE_PERIOD_SECONDS + ) + ) + + +## ... source file continues with no further ObjectDoesNotExist examples... + +``` + + +## Example 9 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / fields.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./fields.py) + +```python +# fields.py +import copy +import datetime +import decimal +import functools +import inspect +import re +import uuid +import warnings +from collections import OrderedDict +from collections.abc import Mapping + +from django.conf import settings +~~from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import ( + EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator, + MinValueValidator, ProhibitNullCharactersValidator, RegexValidator, + URLValidator, ip_address_validators +) +from django.forms import FilePathField as DjangoFilePathField +from django.forms import ImageField as DjangoImageField +from django.utils import timezone +from django.utils.dateparse import ( + parse_date, parse_datetime, parse_duration, parse_time +) +from django.utils.duration import duration_string +from django.utils.encoding import is_protected_type, smart_str +from django.utils.formats import localize_input, sanitize_separators +from django.utils.ipv6 import clean_ipv6_address +from django.utils.timezone import utc +from django.utils.translation import gettext_lazy as _ +from pytz.exceptions import InvalidTimeError + +from rest_framework import ( + ISO_8601, RemovedInDRF313Warning, RemovedInDRF314Warning +) +from rest_framework.exceptions import ErrorDetail, ValidationError + + +## ... source file abbreviated to get to ObjectDoesNotExist examples ... + + + if inspect.isbuiltin(obj): + raise BuiltinSignatureError( + 'Built-in function signatures are not inspectable. ' + 'Wrap the function call in a simple, pure Python function.') + + if not (inspect.isfunction(obj) or inspect.ismethod(obj) or isinstance(obj, functools.partial)): + return False + + sig = inspect.signature(obj) + params = sig.parameters.values() + return all( + param.kind == param.VAR_POSITIONAL or + param.kind == param.VAR_KEYWORD or + param.default != param.empty + for param in params + ) + + +def get_attribute(instance, attrs): + for attr in attrs: + try: + if isinstance(instance, Mapping): + instance = instance[attr] + else: + instance = getattr(instance, attr) +~~ except ObjectDoesNotExist: + return None + if is_simple_callable(instance): + try: + instance = instance() + except (AttributeError, KeyError) as exc: + raise ValueError('Exception raised in callable attribute "{}"; original exception was: {}'.format(attr, exc)) + + return instance + + +def set_value(dictionary, keys, value): + if not keys: + dictionary.update(value) + return + + for key in keys[:-1]: + if key not in dictionary: + dictionary[key] = {} + dictionary = dictionary[key] + + dictionary[keys[-1]] = value + + +def to_choices_dict(choices): + + +## ... source file continues with no further ObjectDoesNotExist examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions-permissiondenied.markdown b/content/pages/examples/django/django-core-exceptions-permissiondenied.markdown new file mode 100644 index 000000000..e741da531 --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions-permissiondenied.markdown @@ -0,0 +1,1120 @@ +title: django.core.exceptions PermissionDenied Example Code +category: page +slug: django-core-exceptions-permissiondenied-examples +sortorder: 500011105 +toc: False +sidebartitle: django.core.exceptions PermissionDenied +meta: Python example code for the PermissionDenied class from the django.core.exceptions module of the Django project. + + +PermissionDenied is a class within the django.core.exceptions module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / socialaccount / models.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/models.py) + +```python +# models.py +from __future__ import absolute_import + +from django.contrib.auth import authenticate +from django.contrib.sites.models import Site +from django.contrib.sites.shortcuts import get_current_site +~~from django.core.exceptions import PermissionDenied +from django.db import models +from django.utils.crypto import get_random_string +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +import allauth.app_settings +from allauth.account.models import EmailAddress +from allauth.account.utils import get_next_redirect_url, setup_user_email +from allauth.utils import get_user_model + +from ..utils import get_request_param +from . import app_settings, providers +from .adapter import get_adapter +from .fields import JSONField + + +class SocialAppManager(models.Manager): + def get_current(self, provider, request=None): + cache = {} + if request: + cache = getattr(request, '_socialapp_cache', {}) + request._socialapp_cache = cache + app = cache.get(provider) + if not app: + + +## ... source file abbreviated to get to PermissionDenied examples ... + + + def get_redirect_url(self, request): + url = self.state.get('next') + return url + + @classmethod + def state_from_request(cls, request): + state = {} + next_url = get_next_redirect_url(request) + if next_url: + state['next'] = next_url + state['process'] = get_request_param(request, 'process', 'login') + state['scope'] = get_request_param(request, 'scope', '') + state['auth_params'] = get_request_param(request, 'auth_params', '') + return state + + @classmethod + def stash_state(cls, request): + state = cls.state_from_request(request) + verifier = get_random_string() + request.session['socialaccount_state'] = (state, verifier) + return verifier + + @classmethod + def unstash_state(cls, request): + if 'socialaccount_state' not in request.session: +~~ raise PermissionDenied() + state, verifier = request.session.pop('socialaccount_state') + return state + + @classmethod + def verify_and_unstash_state(cls, request, verifier): + if 'socialaccount_state' not in request.session: +~~ raise PermissionDenied() + state, verifier2 = request.session.pop('socialaccount_state') + if verifier != verifier2: +~~ raise PermissionDenied() + return state + + + +## ... source file continues with no further PermissionDenied examples... + +``` + + +## Example 2 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / exceptions.py**](https://github.com/jazzband/django-axes/blob/master/axes/./exceptions.py) + +```python +# exceptions.py +~~from django.core.exceptions import PermissionDenied + + +~~class AxesBackendPermissionDenied(PermissionDenied): + + +class AxesBackendRequestParameterRequired(ValueError): + + + +## ... source file continues with no further PermissionDenied examples... + +``` + + +## Example 3 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / api.py**](https://github.com/divio/django-cms/blob/develop/cms/./api.py) + +```python +# api.py +import datetime + +from django.contrib.auth import get_user_model +from django.contrib.sites.models import Site +from django.core.exceptions import FieldError +~~from django.core.exceptions import PermissionDenied +from django.core.exceptions import ValidationError +from django.db import transaction +from django.template.defaultfilters import slugify +from django.template.loader import get_template +from django.utils.translation import activate + +from six import string_types + +from cms import constants +from cms.app_base import CMSApp +from cms.apphook_pool import apphook_pool +from cms.constants import TEMPLATE_INHERITANCE_MAGIC +from cms.models.pagemodel import Page +from cms.models.permissionmodels import (PageUser, PagePermission, GlobalPagePermission, + ACCESS_PAGE_AND_DESCENDANTS) +from cms.models.placeholdermodel import Placeholder +from cms.models.pluginmodel import CMSPlugin +from cms.models.titlemodels import Title +from cms.plugin_base import CMSPluginBase +from cms.plugin_pool import plugin_pool +from cms.utils import copy_plugins, get_current_site +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import get_language_list +from cms.utils.page import get_available_slug + + +## ... source file abbreviated to get to PermissionDenied examples ... + + + 'can_add': can_add or grant_all, + 'can_change': can_change or grant_all, + 'can_delete': can_delete or grant_all, + 'can_change_advanced_settings': can_change_advanced_settings or grant_all, + 'can_publish': can_publish or grant_all, + 'can_change_permissions': can_change_permissions or grant_all, + 'can_move_page': can_move_page or grant_all, + 'can_view': can_view or grant_all, + } + + page_permission = PagePermission(page=page, user=user, + grant_on=grant_on, **data) + page_permission.save() + if global_permission: + page_permission = GlobalPagePermission( + user=user, can_recover_page=can_recover_page, **data) + page_permission.save() + page_permission.sites.add(get_current_site()) + return page_permission + + +def publish_page(page, user, language): + page = page.reload() + + if not page.has_publish_permission(user): +~~ raise PermissionDenied() + with current_user(user.get_username()): + page.publish(language) + return page.reload() + + +def publish_pages(include_unpublished=False, language=None, site=None): + qs = Page.objects.drafts() + + if not include_unpublished: + qs = qs.filter(title_set__published=True).distinct() + + if site: + qs = qs.filter(node__site=site) + + output_language = None + for i, page in enumerate(qs): + add = True + titles = page.title_set + if not include_unpublished: + titles = titles.filter(published=True) + for lang in titles.values_list("language", flat=True): + if language is None or lang == language: + if not output_language: + output_language = lang + + +## ... source file continues with no further PermissionDenied examples... + +``` + + +## Example 4 from django-downloadview +[django-downloadview](https://github.com/benoitbryon/django-downloadview) +([project documentation](https://django-downloadview.readthedocs.io/en/1.9/) +and +[PyPI package information](https://pypi.org/project/django-downloadview/)) +is a [Django](/django.html) extension for serving downloads through your +web application. While typically you would use a web server to handle +[static content](/static-content.html), sometimes you need to control +file access, such as requiring a user to register before downloading a +PDF. In that situations, django-downloadview is a handy library to avoid +boilerplate code for common scenarios. + +[**django-downloadview / django_downloadview / decorators.py**](https://github.com/benoitbryon/django-downloadview/blob/master/django_downloadview/./decorators.py) + +```python +# decorators.py + +from functools import wraps + +from django.conf import settings +~~from django.core.exceptions import PermissionDenied +from django.core.signing import BadSignature, SignatureExpired, TimestampSigner + + +class DownloadDecorator(object): + + def __init__(self, middleware_factory): + self.middleware_factory = middleware_factory + + def __call__(self, view_func, *middleware_args, **middleware_kwargs): + + def decorated(request, *view_args, **view_kwargs): + response = view_func(request, *view_args, **view_kwargs) + middleware = self.middleware_factory(*middleware_args, **middleware_kwargs) + return middleware.process_response(request, response) + + return decorated + + +def _signature_is_valid(request): + + signer = TimestampSigner() + signature = request.GET.get("X-Signature") + expiration = getattr(settings, "DOWNLOADVIEW_URL_EXPIRATION", None) + + try: + signature_path = signer.unsign(signature, max_age=expiration) + except SignatureExpired as e: +~~ raise PermissionDenied("Signature expired") from e + except BadSignature as e: +~~ raise PermissionDenied("Signature invalid") from e + except Exception as e: +~~ raise PermissionDenied("Signature error") from e + + if request.path != signature_path: +~~ raise PermissionDenied("Signature mismatch") + + +def signature_required(function): + + @wraps(function) + def decorator(request, *args, **kwargs): + _signature_is_valid(request) + return function(request, *args, **kwargs) + + return decorator + + + +## ... source file continues with no further PermissionDenied examples... + +``` + + +## Example 5 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / tools.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/tools.py) + +```python +# tools.py +from __future__ import absolute_import, unicode_literals + +from django.contrib.admin.options import IS_POPUP_VAR +~~from django.core.exceptions import PermissionDenied +from django.utils.http import urlencode + + +ALLOWED_PICK_TYPES = ('folder', 'file') + + +def check_files_edit_permissions(request, files): + for f in files: + if not f.has_edit_permission(request): +~~ raise PermissionDenied + + +def check_folder_edit_permissions(request, folders): + for f in folders: + if not f.has_edit_permission(request): +~~ raise PermissionDenied + check_files_edit_permissions(request, f.files) + check_folder_edit_permissions(request, f.children.all()) + + +def check_files_read_permissions(request, files): + for f in files: + if not f.has_read_permission(request): +~~ raise PermissionDenied + + +def check_folder_read_permissions(request, folders): + for f in folders: + if not f.has_read_permission(request): +~~ raise PermissionDenied + check_files_read_permissions(request, f.files) + check_folder_read_permissions(request, f.children.all()) + + +def userperms_for_request(item, request): + r = [] + ps = ['read', 'edit', 'add_children'] + for p in ps: + attr = "has_%s_permission" % p + if hasattr(item, attr): + x = getattr(item, attr)(request) + if x: + r.append(p) + return r + + +def popup_status(request): + return ( + IS_POPUP_VAR in request.GET + or 'pop' in request.GET + or IS_POPUP_VAR in request.POST + or 'pop' in request.POST + ) + + + +## ... source file continues with no further PermissionDenied examples... + +``` + + +## Example 6 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / mixins.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./mixins.py) + +```python +# mixins.py +from collections.abc import Iterable + +from django.conf import settings +from django.contrib.auth.decorators import login_required, REDIRECT_FIELD_NAME +~~from django.core.exceptions import ImproperlyConfigured, PermissionDenied +from guardian.utils import get_user_obj_perms_model +UserObjectPermission = get_user_obj_perms_model() +from guardian.utils import get_40x_or_None, get_anonymous_user +from guardian.shortcuts import get_objects_for_user + + +class LoginRequiredMixin: + redirect_field_name = REDIRECT_FIELD_NAME + login_url = settings.LOGIN_URL + + def dispatch(self, request, *args, **kwargs): + return login_required(redirect_field_name=self.redirect_field_name, + login_url=self.login_url)( + super().dispatch + )(request, *args, **kwargs) + + +class PermissionRequiredMixin: + login_url = settings.LOGIN_URL + permission_required = None + redirect_field_name = REDIRECT_FIELD_NAME + return_403 = False + return_404 = False + raise_exception = False + + +## ... source file abbreviated to get to PermissionDenied examples ... + + + % self.permission_required) + return perms + + def get_permission_object(self): + if hasattr(self, 'permission_object'): + return self.permission_object + return (hasattr(self, 'get_object') and self.get_object() or + getattr(self, 'object', None)) + + def check_permissions(self, request): + obj = self.get_permission_object() + + forbidden = get_40x_or_None(request, + perms=self.get_required_permissions( + request), + obj=obj, + login_url=self.login_url, + redirect_field_name=self.redirect_field_name, + return_403=self.return_403, + return_404=self.return_404, + accept_global_perms=self.accept_global_perms + ) + if forbidden: + self.on_permission_check_fail(request, forbidden, obj=obj) + if forbidden and self.raise_exception: +~~ raise PermissionDenied() + return forbidden + + def on_permission_check_fail(self, request, response, obj=None): + + def dispatch(self, request, *args, **kwargs): + self.request = request + self.args = args + self.kwargs = kwargs + response = self.check_permissions(request) + if response: + return response + return super().dispatch(request, *args, **kwargs) + + +class GuardianUserMixin: + + @staticmethod + def get_anonymous(): + return get_anonymous_user() + + def add_obj_perm(self, perm, obj): + return UserObjectPermission.objects.assign_perm(perm, self, obj) + + def del_obj_perm(self, perm, obj): + + +## ... source file continues with no further PermissionDenied examples... + +``` + + +## Example 7 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / admin.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./admin.py) + +```python +# admin.py +from django.contrib.admin.options import ModelAdmin, csrf_protect_m +from django.contrib.admin.views.main import SEARCH_VAR, ChangeList +~~from django.core.exceptions import PermissionDenied +from django.core.paginator import InvalidPage, Paginator +from django.shortcuts import render +from django.utils.encoding import force_str +from django.utils.translation import ungettext + +from haystack import connections +from haystack.constants import DEFAULT_ALIAS +from haystack.query import SearchQuerySet +from haystack.utils import get_model_ct_tuple + + +class SearchChangeList(ChangeList): + def __init__(self, **kwargs): + self.haystack_connection = kwargs.pop("haystack_connection", DEFAULT_ALIAS) + super(SearchChangeList, self).__init__(**kwargs) + + def get_results(self, request): + if SEARCH_VAR not in request.GET: + return super(SearchChangeList, self).get_results(request) + + sqs = ( + SearchQuerySet(self.haystack_connection) + .models(self.model) + .auto_query(request.GET[SEARCH_VAR]) + + +## ... source file abbreviated to get to PermissionDenied examples ... + + + ) + + can_show_all = result_count <= self.list_max_show_all + multi_page = result_count > self.list_per_page + + try: + result_list = paginator.page(self.page_num + 1).object_list + result_list = [result.object for result in result_list] + except InvalidPage: + result_list = () + + self.result_count = result_count + self.full_result_count = full_result_count + self.result_list = result_list + self.can_show_all = can_show_all + self.multi_page = multi_page + self.paginator = paginator + + +class SearchModelAdminMixin(object): + haystack_connection = DEFAULT_ALIAS + + @csrf_protect_m + def changelist_view(self, request, extra_context=None): + if not self.has_change_permission(request, None): +~~ raise PermissionDenied + + if SEARCH_VAR not in request.GET: + return super(SearchModelAdminMixin, self).changelist_view( + request, extra_context + ) + + indexed_models = ( + connections[self.haystack_connection] + .get_unified_index() + .get_indexed_models() + ) + + if self.model not in indexed_models: + return super(SearchModelAdminMixin, self).changelist_view( + request, extra_context + ) + + list_display = list(self.list_display) + + kwargs = { + "haystack_connection": self.haystack_connection, + "request": request, + "model": self.model, + "list_display": list_display, + + +## ... source file continues with no further PermissionDenied examples... + +``` + + +## Example 8 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / admin.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./admin.py) + +```python +# admin.py +from datetime import datetime + +import django +from django import forms +from django.conf import settings +from django.conf.urls import url +from django.contrib import admin, messages +from django.contrib.admin.models import ADDITION, CHANGE, DELETION, LogEntry +from django.contrib.auth import get_permission_codename +from django.contrib.contenttypes.models import ContentType +~~from django.core.exceptions import PermissionDenied +from django.http import HttpResponse, HttpResponseRedirect +from django.template.response import TemplateResponse +from django.urls import reverse +from django.utils.decorators import method_decorator +from django.utils.encoding import force_str +from django.utils.module_loading import import_string +from django.utils.translation import gettext_lazy as _ +from django.views.decorators.http import require_POST + +from .formats.base_formats import DEFAULT_FORMATS +from .forms import ConfirmImportForm, ExportForm, ImportForm, export_action_form_factory +from .resources import modelresource_factory +from .results import RowResult +from .signals import post_export, post_import +from .tmp_storages import TempFolderStorage + +SKIP_ADMIN_LOG = getattr(settings, 'IMPORT_EXPORT_SKIP_ADMIN_LOG', False) +TMP_STORAGE_CLASS = getattr(settings, 'IMPORT_EXPORT_TMP_STORAGE_CLASS', + TempFolderStorage) + + +if isinstance(TMP_STORAGE_CLASS, str): + TMP_STORAGE_CLASS = import_string(TMP_STORAGE_CLASS) + + + +## ... source file abbreviated to get to PermissionDenied examples ... + + + name='%s_%s_import' % info), + ] + return my_urls + urls + + def get_resource_kwargs(self, request, *args, **kwargs): + return {} + + def get_import_resource_kwargs(self, request, *args, **kwargs): + return self.get_resource_kwargs(request, *args, **kwargs) + + def get_resource_class(self): + if not self.resource_class: + return modelresource_factory(self.model) + else: + return self.resource_class + + def get_import_resource_class(self): + return self.get_resource_class() + + def get_import_formats(self): + return [f for f in self.formats if f().can_import()] + + @method_decorator(require_POST) + def process_import(self, request, *args, **kwargs): + if not self.has_import_permission(request): +~~ raise PermissionDenied + + form_type = self.get_confirm_import_form() + confirm_form = form_type(request.POST) + if confirm_form.is_valid(): + import_formats = self.get_import_formats() + input_format = import_formats[ + int(confirm_form.cleaned_data['input_format']) + ]() + tmp_storage = self.get_tmp_storage_class()(name=confirm_form.cleaned_data['import_file_name']) + data = tmp_storage.read(input_format.get_read_mode()) + if not input_format.is_binary() and self.from_encoding: + data = force_str(data, self.from_encoding) + dataset = input_format.create_dataset(data) + + result = self.process_dataset(dataset, confirm_form, request, *args, **kwargs) + + tmp_storage.remove() + + return self.process_result(result, request) + + def process_dataset(self, dataset, confirm_form, request, *args, **kwargs): + + res_kwargs = self.get_import_resource_kwargs(request, form=confirm_form, *args, **kwargs) + resource = self.get_import_resource_class()(**res_kwargs) + + +## ... source file abbreviated to get to PermissionDenied examples ... + + + + def get_confirm_import_form(self): + return ConfirmImportForm + + def get_form_kwargs(self, form, *args, **kwargs): + return kwargs + + def get_import_data_kwargs(self, request, *args, **kwargs): + form = kwargs.get('form') + if form: + kwargs.pop('form') + return kwargs + return {} + + def write_to_tmp_storage(self, import_file, input_format): + tmp_storage = self.get_tmp_storage_class()() + data = bytes() + for chunk in import_file.chunks(): + data += chunk + + tmp_storage.save(data, input_format.get_read_mode()) + return tmp_storage + + def import_action(self, request, *args, **kwargs): + if not self.has_import_permission(request): +~~ raise PermissionDenied + + context = self.get_import_context_data() + + import_formats = self.get_import_formats() + form_type = self.get_import_form() + form_kwargs = self.get_form_kwargs(form_type, *args, **kwargs) + form = form_type(import_formats, + request.POST or None, + request.FILES or None, + **form_kwargs) + + if request.POST and form.is_valid(): + input_format = import_formats[ + int(form.cleaned_data['input_format']) + ]() + import_file = form.cleaned_data['import_file'] + tmp_storage = self.write_to_tmp_storage(import_file, input_format) + + try: + data = tmp_storage.read(input_format.get_read_mode()) + if not input_format.is_binary() and self.from_encoding: + data = force_str(data, self.from_encoding) + dataset = input_format.create_dataset(data) + except UnicodeDecodeError as e: + + +## ... source file abbreviated to get to PermissionDenied examples ... + + + + ChangeList = self.get_changelist(request) + changelist_kwargs = { + 'request': request, + 'model': self.model, + 'list_display': list_display, + 'list_display_links': list_display_links, + 'list_filter': list_filter, + 'date_hierarchy': self.date_hierarchy, + 'search_fields': search_fields, + 'list_select_related': self.list_select_related, + 'list_per_page': self.list_per_page, + 'list_max_show_all': self.list_max_show_all, + 'list_editable': self.list_editable, + 'model_admin': self, + } + if django.VERSION >= (2, 1): + changelist_kwargs['sortable_by'] = self.sortable_by + cl = ChangeList(**changelist_kwargs) + + return cl.get_queryset(request) + + def get_export_data(self, file_format, queryset, *args, **kwargs): + request = kwargs.pop("request") + if not self.has_export_permission(request): +~~ raise PermissionDenied + + resource_class = self.get_export_resource_class() + data = resource_class(**self.get_export_resource_kwargs(request)).export(queryset, *args, **kwargs) + export_data = file_format.export_data(data) + return export_data + + def get_export_context_data(self, **kwargs): + return self.get_context_data(**kwargs) + + def get_context_data(self, **kwargs): + return {} + + def export_action(self, request, *args, **kwargs): + if not self.has_export_permission(request): +~~ raise PermissionDenied + + formats = self.get_export_formats() + form = ExportForm(formats, request.POST or None) + if form.is_valid(): + file_format = formats[ + int(form.cleaned_data['file_format']) + ]() + + queryset = self.get_export_queryset(request) + export_data = self.get_export_data(file_format, queryset, request=request) + content_type = file_format.get_content_type() + response = HttpResponse(export_data, content_type=content_type) + response['Content-Disposition'] = 'attachment; filename="%s"' % ( + self.get_export_filename(request, queryset, file_format), + ) + + post_export.send(sender=None, model=self.model) + return response + + context = self.get_export_context_data() + + context.update(self.admin_site.each_context(request)) + + context['title'] = _("Export") + + +## ... source file continues with no further PermissionDenied examples... + +``` + + +## Example 9 from django-loginas +[django-loginas](https://github.com/skorokithakis/django-loginas) +([PyPI package information](https://pypi.org/project/django-loginas/)) +is [Django](/django.html) code library for admins to log into an application +as another user, typically for debugging purposes. + +django-loginas is open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/skorokithakis/django-loginas/blob/master/LICENSE). + +[**django-loginas / loginas / views.py**](https://github.com/skorokithakis/django-loginas/blob/master/loginas/./views.py) + +```python +# views.py +from django.contrib import messages +from django.contrib.admin.utils import unquote +~~from django.core.exceptions import ImproperlyConfigured, PermissionDenied +from django.shortcuts import redirect +from django.utils.translation import gettext_lazy as _ +from django.views.decorators.csrf import csrf_protect +from django.views.decorators.http import require_POST + +from . import settings as la_settings +from .utils import login_as, restore_original_login + +try: + from importlib import import_module +except ImportError: + from django.utils.importlib import import_module # type: ignore + + +try: + from django.contrib.auth import get_user_model + + User = get_user_model() +except ImportError: + from django.contrib.auth.models import User # type: ignore + + +def _load_module(path): + + + +## ... source file abbreviated to get to PermissionDenied examples ... + + + except ValueError: + raise ImproperlyConfigured("Error importing CAN_LOGIN_AS" " function. Is CAN_LOGIN_AS a" " string?") + + try: + can_login_as = getattr(mod, attr) + except AttributeError: + raise ImproperlyConfigured("Module {0} does not define a {1} " "function.".format(module, attr)) + return can_login_as + + +@csrf_protect +@require_POST +def user_login(request, user_id): + user = User.objects.get(pk=unquote(user_id)) + + if isinstance(la_settings.CAN_LOGIN_AS, str): + can_login_as = _load_module(la_settings.CAN_LOGIN_AS) + elif hasattr(la_settings.CAN_LOGIN_AS, "__call__"): + can_login_as = la_settings.CAN_LOGIN_AS + else: + raise ImproperlyConfigured("The CAN_LOGIN_AS setting is neither a valid module nor callable.") + no_permission_error = None + try: + if not can_login_as(request, user): + no_permission_error = _("You do not have permission to do that.") +~~ except PermissionDenied as e: + no_permission_error = str(e) + if no_permission_error is not None: + messages.error(request, no_permission_error, extra_tags=la_settings.MESSAGE_EXTRA_TAGS, fail_silently=True) + return redirect(request.META.get("HTTP_REFERER", "/")) + + try: + login_as(user, request) + except ImproperlyConfigured as e: + messages.error(request, str(e), extra_tags=la_settings.MESSAGE_EXTRA_TAGS, fail_silently=True) + return redirect(request.META.get("HTTP_REFERER", "/")) + + return redirect(la_settings.LOGIN_REDIRECT) + + +def user_logout(request): + restore_original_login(request) + + return redirect(la_settings.LOGOUT_REDIRECT) + + + +## ... source file continues with no further PermissionDenied examples... + +``` + + +## Example 10 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / metadata.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./metadata.py) + +```python +# metadata.py +from collections import OrderedDict + +~~from django.core.exceptions import PermissionDenied +from django.http import Http404 +from django.utils.encoding import force_str + +from rest_framework import exceptions, serializers +from rest_framework.request import clone_request +from rest_framework.utils.field_mapping import ClassLookupDict + + +class BaseMetadata: + def determine_metadata(self, request, view): + raise NotImplementedError(".determine_metadata() must be overridden.") + + +class SimpleMetadata(BaseMetadata): + label_lookup = ClassLookupDict({ + serializers.Field: 'field', + serializers.BooleanField: 'boolean', + serializers.NullBooleanField: 'boolean', + serializers.CharField: 'string', + serializers.UUIDField: 'string', + serializers.URLField: 'url', + serializers.EmailField: 'email', + serializers.RegexField: 'regex', + serializers.SlugField: 'slug', + + +## ... source file continues with no further PermissionDenied examples... + +``` + + +## Example 11 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / admin / auth.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/admin/auth.py) + +```python +# auth.py +import types +from functools import wraps + +import l18n + +from django.contrib.auth import get_user_model +from django.contrib.auth.views import redirect_to_login as auth_redirect_to_login +~~from django.core.exceptions import PermissionDenied +from django.db.models import Q +from django.shortcuts import redirect +from django.urls import reverse +from django.utils.timezone import activate as activate_tz +from django.utils.translation import gettext as _ +from django.utils.translation import override + +from wagtail.admin import messages +from wagtail.core.models import GroupPagePermission + + +def users_with_page_permission(page, permission_type, include_superusers=True): + User = get_user_model() + + ancestors_and_self = list(page.get_ancestors()) + [page] + perm = GroupPagePermission.objects.filter(permission_type=permission_type, page__in=ancestors_and_self) + q = Q(groups__page_permissions__in=perm) + + if include_superusers: + q |= Q(is_superuser=True) + + return User.objects.filter(is_active=True).filter(q).distinct() + + +def permission_denied(request): + if request.is_ajax(): +~~ raise PermissionDenied + + from wagtail.admin import messages + + messages.error(request, _('Sorry, you do not have permission to access this area.')) + return redirect('wagtailadmin_home') + + +def user_passes_test(test): + def decorator(view_func): + + @wraps(view_func) + def wrapped_view_func(request, *args, **kwargs): + if test(request.user): + return view_func(request, *args, **kwargs) + else: + return permission_denied(request) + + return wrapped_view_func + + return decorator + + +def permission_required(permission_name): + def test(user): + + +## ... source file abbreviated to get to PermissionDenied examples ... + + + return user_passes_test(test) + + def require_any(self, *actions): + def test(user): + return self.policy.user_has_any_permission(user, actions) + + return user_passes_test(test) + + +def user_has_any_page_permission(user): + if not user.is_active: + return False + + if user.is_superuser: + return True + + if GroupPagePermission.objects.filter(group__in=user.groups.all()).exists(): + return True + + + return False + + +def reject_request(request): + if request.is_ajax(): +~~ raise PermissionDenied + + return auth_redirect_to_login( + request.get_full_path(), login_url=reverse('wagtailadmin_login')) + + +def require_admin_access(view_func): + def decorated_view(request, *args, **kwargs): + + user = request.user + + if user.is_anonymous: + return reject_request(request) + + if user.has_perms(['wagtailadmin.access_admin']): + preferred_language = None + if hasattr(user, 'wagtail_userprofile'): + preferred_language = user.wagtail_userprofile.get_preferred_language() + l18n.set_language(preferred_language) + time_zone = user.wagtail_userprofile.get_current_time_zone() + activate_tz(time_zone) + if preferred_language: + with override(preferred_language): + response = view_func(request, *args, **kwargs) + if hasattr(response, "render"): + + +## ... source file continues with no further PermissionDenied examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions-suspiciousfileoperation.markdown b/content/pages/examples/django/django-core-exceptions-suspiciousfileoperation.markdown new file mode 100644 index 000000000..a660aef52 --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions-suspiciousfileoperation.markdown @@ -0,0 +1,73 @@ +title: django.core.exceptions SuspiciousFileOperation Example Code +category: page +slug: django-core-exceptions-suspiciousfileoperation-examples +sortorder: 500011106 +toc: False +sidebartitle: django.core.exceptions SuspiciousFileOperation +meta: Python example code for the SuspiciousFileOperation class from the django.core.exceptions module of the Django project. + + +SuspiciousFileOperation is a class within the django.core.exceptions module of the Django project. + + +## Example 1 from django-markdown-view +[django-markdown-view](https://github.com/rgs258/django-markdown-view) +([PyPI package information](https://pypi.org/project/django-markdown-view/)) +is a Django extension for serving [Markdown](/markdown.html) files as +[Django templates](/django-templates.html). The project is open +sourced under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/rgs258/django-markdown-view/blob/master/LICENSE). + +[**django-markdown-view / markdown_view / loaders.py**](https://github.com/rgs258/django-markdown-view/blob/master/markdown_view/./loaders.py) + +```python +# loaders.py +from django.conf import settings +~~from django.core.exceptions import SuspiciousFileOperation +from django.template import Origin +from django.template.loaders.filesystem import Loader as FilesystemLoader +from django.template.utils import get_app_template_dirs +from django.utils._os import safe_join + + +class MarkdownLoader(FilesystemLoader): + + def get_dirs(self): + base_dir = getattr( + settings, + "MARKDOWN_VIEW_BASE_DIR", + getattr( + settings, + "BASE_DIR", + None) + ) + dirs = [*get_app_template_dirs('')] + if base_dir: + dirs.extend([base_dir]) + return dirs + + def get_template_sources(self, template_name): + if template_name.endswith('.md'): + template_split = template_name.split("/") + template_split.reverse() + template_app_dir = template_split.pop() + template_split.reverse() + for template_dir in self.get_dirs(): + if template_dir.endswith(template_app_dir): + try: + name = safe_join(template_dir, *template_split) +~~ except SuspiciousFileOperation: + continue + + yield Origin( + name=name, + template_name=template_name, + loader=self, + ) + + + +## ... source file continues with no further SuspiciousFileOperation examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions-suspiciousmultipartform.markdown b/content/pages/examples/django/django-core-exceptions-suspiciousmultipartform.markdown new file mode 100644 index 000000000..c1ce0e7a4 --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions-suspiciousmultipartform.markdown @@ -0,0 +1,56 @@ +title: django.core.exceptions SuspiciousMultipartForm Example Code +category: page +slug: django-core-exceptions-suspiciousmultipartform-examples +sortorder: 500011107 +toc: False +sidebartitle: django.core.exceptions SuspiciousMultipartForm +meta: Python example code for the SuspiciousMultipartForm class from the django.core.exceptions module of the Django project. + + +SuspiciousMultipartForm is a class within the django.core.exceptions module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / views / upload.py**](https://github.com/jrief/django-angular/blob/master/djng/views/upload.py) + +```python +# upload.py +~~from django.core.exceptions import SuspiciousMultipartForm +from django.core import signing +from django.views.generic import View +from django.http import JsonResponse + +from djng import app_settings +from djng.forms.fields import FileField, ImageField + + +class FileUploadView(View): + storage = app_settings.upload_storage + thumbnail_size = app_settings.THUMBNAIL_OPTIONS + signer = signing.Signer() + + def post(self, request, *args, **kwargs): + if request.POST.get('filetype') == 'file': + field = FileField + elif request.POST.get('filetype') == 'image': + field = ImageField + else: +~~ raise SuspiciousMultipartForm("Missing attribute 'filetype' in form data.") + data = {} + for name, file_obj in request.FILES.items(): + data[name] = field.preview(file_obj) + return JsonResponse(data) + + + +## ... source file continues with no further SuspiciousMultipartForm examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions-validationerror.markdown b/content/pages/examples/django/django-core-exceptions-validationerror.markdown new file mode 100644 index 000000000..8c255d787 --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions-validationerror.markdown @@ -0,0 +1,2128 @@ +title: django.core.exceptions ValidationError Example Code +category: page +slug: django-core-exceptions-validationerror-examples +sortorder: 500011108 +toc: False +sidebartitle: django.core.exceptions ValidationError +meta: Python example code for the ValidationError class from the django.core.exceptions module of the Django project. + + +ValidationError is a class within the django.core.exceptions module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog_tests / tests.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog_tests/tests.py) + +```python +# tests.py +import datetime +import django +from django.conf import settings +from django.contrib import auth +from django.contrib.auth.models import User, AnonymousUser +~~from django.core.exceptions import ValidationError +from django.db.models.signals import pre_save +from django.http import HttpResponse +from django.test import TestCase, RequestFactory +from django.utils import dateformat, formats, timezone +from dateutil.tz import gettz + +from auditlog.middleware import AuditlogMiddleware +from auditlog.models import LogEntry +from auditlog.registry import auditlog +from auditlog_tests.models import SimpleModel, AltPrimaryKeyModel, UUIDPrimaryKeyModel, \ + ProxyModel, SimpleIncludeModel, SimpleExcludeModel, SimpleMappingModel, RelatedModel, \ + ManyRelatedModel, AdditionalDataIncludedModel, DateTimeFieldModel, ChoicesFieldModel, \ + CharfieldTextfieldModel, PostgresArrayFieldModel, NoDeleteHistoryModel +from auditlog import compat + + +class SimpleModelTest(TestCase): + def setUp(self): + self.obj = SimpleModel.objects.create(text='I am not difficult.') + + def test_create(self): + obj = self.obj + + self.assertTrue(obj.history.count() == 1, msg="There is one log entry") + + +## ... source file abbreviated to get to ValidationError examples ... + + + def test_request(self): + request = self.factory.get('/') + request.user = self.user + self.middleware.process_request(request) + + self.assertTrue(pre_save.has_listeners(LogEntry)) + + self.middleware.process_exception(request, None) + + def test_response(self): + request = self.factory.get('/') + request.user = self.user + + self.middleware.process_request(request) + self.assertTrue(pre_save.has_listeners(LogEntry)) # The signal should be present before trying to disconnect it. + self.middleware.process_response(request, HttpResponse()) + + self.assertFalse(pre_save.has_listeners(LogEntry)) + + def test_exception(self): + request = self.factory.get('/') + request.user = self.user + + self.middleware.process_request(request) + self.assertTrue(pre_save.has_listeners(LogEntry)) # The signal should be present before trying to disconnect it. +~~ self.middleware.process_exception(request, ValidationError("Test")) + + self.assertFalse(pre_save.has_listeners(LogEntry)) + + +class SimpeIncludeModelTest(TestCase): + + def test_register_include_fields(self): + sim = SimpleIncludeModel(label='Include model', text='Looong text') + sim.save() + self.assertTrue(sim.history.count() == 1, msg="There is one log entry") + + sim.label = 'Changed label' + sim.save() + self.assertTrue(sim.history.count() == 2, msg="There are two log entries") + + sim.text = 'Short text' + sim.save() + self.assertTrue(sim.history.count() == 2, msg="There are two log entries") + + +class SimpeExcludeModelTest(TestCase): + + def test_register_exclude_fields(self): + sem = SimpleExcludeModel(label='Exclude model', text='Looong text') + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 2 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / chair_mail / forms.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/chair_mail/forms.py) + +```python +# forms.py +from django import forms +from django.conf import settings +~~from django.core.exceptions import ValidationError +from django.core.mail import send_mail +from django.template import Template, Context +from django.utils import timezone +from html2text import html2text +from markdown import markdown + +from chair_mail.context import get_conference_context, get_user_context, \ + get_submission_context +from chair_mail.mailing_lists import find_list +from chair_mail.utility import get_object_model +from submissions.models import Submission +from users.models import User +from .models import EmailFrame, MSG_TYPE_USER, MSG_TYPE_SUBMISSION, \ + SystemNotification + + +def parse_mailing_lists(names_string, separator=','): + names = names_string.split(separator) + names = [name for name in names if name.strip()] + return [find_list(name) for name in names] + + +def parse_objects(obj_class, pks_string, separator=','): + int_pks = [s for s in pks_string.split(separator) if s.strip()] + + +## ... source file abbreviated to get to ValidationError examples ... + + + from_email=settings.DEFAULT_FROM_EMAIL, + recipient_list=[user.email], + html_message=html, + ) + + +class MessageForm(forms.Form): + subject = forms.CharField() + body = forms.CharField(widget=forms.Textarea(), required=False) + lists = forms.CharField( + required=False, max_length=1000, widget=forms.HiddenInput) + objects = forms.CharField( + required=False, max_length=10000, widget=forms.HiddenInput) + + def __init__(self, *args, msg_type=None, **kwargs): + super().__init__(*args, **kwargs) + self.msg_type = msg_type + self.object_type = get_object_model(msg_type) + self.cleaned_lists = [] + self.cleaned_objects = [] + + def clean_lists(self): + _lists = parse_mailing_lists(self.cleaned_data['lists']) + for ml in _lists: + if ml.type != self.msg_type: +~~ raise ValidationError( + f'unexpected {ml.type} mailing list {ml.name}') + self.cleaned_lists = _lists + return self.cleaned_data['lists'] + + def clean_objects(self): + self.cleaned_objects = parse_objects( + self.object_type, self.cleaned_data['objects'], ',') + return self.cleaned_data['objects'] + + def clean(self): + if not self.cleaned_lists and not self.cleaned_objects: +~~ raise ValidationError('You must specify at least one recipient') + return self.cleaned_data + + +class PreviewMessageForm(forms.Form): + subject = forms.CharField( + required=False, + widget=forms.TextInput(attrs={ + 'hidden': True + }) + ) + + body = forms.CharField( + required=False, + widget=forms.Textarea(attrs={ + 'hidden': True + }) + ) + + def get_context(self, conference): + raise NotImplementedError + + def render_html(self, conference): + ctx_data = self.get_context(conference) + context = Context(ctx_data, autoescape=False) + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 3 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / socialaccount / fields.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/fields.py) + +```python +# fields.py +import json + +import django +~~from django.core.exceptions import ValidationError +from django.db import models + + +class JSONField(models.TextField): + if django.VERSION < (3, 0): + def from_db_value(self, value, expression, connection, context): + return self.to_python(value) + else: + def from_db_value(self, value, expression, connection): + return self.to_python(value) + + def to_python(self, value): + if self.blank and not value: + return None + if isinstance(value, str): + try: + return json.loads(value) + except Exception as e: +~~ raise ValidationError(str(e)) + else: + return value + + def validate(self, value, model_instance): + if isinstance(value, str): + super(JSONField, self).validate(value, model_instance) + try: + json.loads(value) + except Exception as e: +~~ raise ValidationError(str(e)) + + def get_prep_value(self, value): + try: + return json.dumps(value) + except Exception as e: +~~ raise ValidationError(str(e)) + + def value_from_object(self, obj): + val = super(JSONField, self).value_from_object(obj) + return self.get_prep_value(val) + + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 4 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / forms / angular_base.py**](https://github.com/jrief/django-angular/blob/master/djng/forms/angular_base.py) + +```python +# angular_base.py +from base64 import b64encode +from collections import UserList +import json +import warnings + +from django.forms import forms +from django.http import QueryDict +from django.utils.html import format_html, format_html_join, escape, conditional_escape +from django.utils.encoding import force_text +from django.utils.module_loading import import_string +from django.utils.safestring import mark_safe, SafeText, SafeData +~~from django.core.exceptions import ValidationError, ImproperlyConfigured + +from .fields import DefaultFieldMixin + + +class SafeTuple(SafeData, tuple): + + +class TupleErrorList(UserList, list): + def __init__(self, initlist=None, error_class=None): + super(TupleErrorList, self).__init__(initlist) + + if error_class is None: + self.error_class = 'errorlist' + else: + self.error_class = 'errorlist {}'.format(error_class) + + def as_data(self): +~~ return ValidationError(self.data).error_list + + def get_json_data(self, escape_html=False): + errors = [] + for error in self.as_data(): + message = list(error)[0] + errors.append({ + 'message': escape(message) if escape_html else message, + 'code': error.code or '', + }) + return errors + + def as_json(self, escape_html=False): + return json.dumps(self.get_json_data(escape_html)) + + def extend(self, iterable): + for item in iterable: + if not isinstance(item, str): + self.append(item) + return None + + def as_ul(self): + if not self: + return SafeText() + first = self[0] + + +## ... source file abbreviated to get to ValidationError examples ... + + + return '' + if isinstance(self[0], tuple): + return '\n'.join(['* %s' % force_text(e[5]) for e in self if bool(e[5])]) + return '\n'.join(['* %s' % force_text(e) for e in self]) + + def __str__(self): + return self.as_ul() + + def __repr__(self): + if self and isinstance(self[0], tuple): + return repr([force_text(e[5]) for e in self]) + return repr([force_text(e) for e in self]) + + def __contains__(self, item): + return item in list(self) + + def __eq__(self, other): + return list(self) == other + + def __ne__(self, other): + return list(self) != other + + def __getitem__(self, i): + error = self.data[i] + if isinstance(error, tuple): +~~ if isinstance(error[5], ValidationError): + error[5] = list(error[5])[0] + return error +~~ if isinstance(error, ValidationError): + return list(error)[0] + return force_text(error) + + +class NgWidgetMixin(object): + def get_context(self, name, value, attrs): + context = super(NgWidgetMixin, self).get_context(name, value, attrs) + if callable(getattr(self._field, 'update_widget_rendering_context', None)): + self._field.update_widget_rendering_context(context) + return context + + +class NgBoundField(forms.BoundField): + @property + def errors(self): + if not hasattr(self, '_errors_cache'): + self._errors_cache = self.form.get_field_errors(self) + return self._errors_cache + + def css_classes(self, extra_classes=None): + if hasattr(extra_classes, 'split'): + extra_classes = extra_classes.split() + extra_classes = set(extra_classes or []) + field_css_classes = getattr(self.form, 'field_css_classes', None) + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 5 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / api.py**](https://github.com/divio/django-cms/blob/develop/cms/./api.py) + +```python +# api.py +import datetime + +from django.contrib.auth import get_user_model +from django.contrib.sites.models import Site +from django.core.exceptions import FieldError +from django.core.exceptions import PermissionDenied +~~from django.core.exceptions import ValidationError +from django.db import transaction +from django.template.defaultfilters import slugify +from django.template.loader import get_template +from django.utils.translation import activate + +from six import string_types + +from cms import constants +from cms.app_base import CMSApp +from cms.apphook_pool import apphook_pool +from cms.constants import TEMPLATE_INHERITANCE_MAGIC +from cms.models.pagemodel import Page +from cms.models.permissionmodels import (PageUser, PagePermission, GlobalPagePermission, + ACCESS_PAGE_AND_DESCENDANTS) +from cms.models.placeholdermodel import Placeholder +from cms.models.pluginmodel import CMSPlugin +from cms.models.titlemodels import Title +from cms.plugin_base import CMSPluginBase +from cms.plugin_pool import plugin_pool +from cms.utils import copy_plugins, get_current_site +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import get_language_list +from cms.utils.page import get_available_slug +from cms.utils.permissions import _thread_locals, current_user + + +## ... source file abbreviated to get to ValidationError examples ... + + + + + + +def _verify_apphook(apphook, namespace): + apphook_pool.discover_apps() + if isinstance(apphook, CMSApp): + try: + assert apphook.__class__ in [app.__class__ for app in apphook_pool.apps.values()] + except AssertionError: + print(apphook_pool.apps.values()) + raise + apphook_name = apphook.__class__.__name__ + elif hasattr(apphook, '__module__') and issubclass(apphook, CMSApp): + return apphook.__name__ + elif isinstance(apphook, string_types): + try: + assert apphook in apphook_pool.apps + except AssertionError: + print(apphook_pool.apps.values()) + raise + apphook_name = apphook + else: + raise TypeError("apphook must be string or CMSApp instance") + if apphook_pool.apps[apphook_name].app_name and not namespace: +~~ raise ValidationError('apphook with app_name must define a namespace') + return apphook_name + + +def _verify_plugin_type(plugin_type): + if (hasattr(plugin_type, '__module__') and + issubclass(plugin_type, CMSPluginBase)): + plugin_model = plugin_type.model + assert plugin_type in plugin_pool.plugins.values() + plugin_type = plugin_type.__name__ + elif isinstance(plugin_type, string_types): + try: + plugin_model = plugin_pool.get_plugin(plugin_type).model + except KeyError: + raise TypeError( + 'plugin_type must be CMSPluginBase subclass or string' + ) + else: + raise TypeError('plugin_type must be CMSPluginBase subclass or string') + return plugin_model, plugin_type + + + +@transaction.atomic +def create_page(title, template, language, menu_title=None, slug=None, + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 6 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / validators.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/./validators.py) + +```python +# validators.py +import unicodedata +import binascii + + +~~from django.core.exceptions import ValidationError +from django.utils.deconstruct import deconstructible +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + + +@deconstructible +class NoControlCharactersValidator: + message = _("Control Characters like new lines or tabs are not allowed.") + code = "no_control_characters" + whitelist = None + + def __init__(self, message=None, code=None, whitelist=None): + if message: + self.message = message + if code: + self.code = code + if whitelist: + self.whitelist = whitelist + + def __call__(self, value): + value = force_str(value) + whitelist = self.whitelist + category = unicodedata.category + for character in value: + if whitelist and character in whitelist: + continue + if category(character)[0] == "C": + params = {'value': value, 'whitelist': whitelist} +~~ raise ValidationError(self.message, code=self.code, params=params) + + def __eq__(self, other): + return ( + isinstance(other, NoControlCharactersValidator) and + (self.whitelist == other.whitelist) and + (self.message == other.message) and + (self.code == other.code) + ) + + +@deconstructible +class NoWhitespaceValidator: + message = _("Leading and Trailing whitespaces are not allowed.") + code = "no_whitespace" + + def __init__(self, message=None, code=None, whitelist=None): + if message: + self.message = message + if code: + self.code = code + + def __call__(self, value): + value = force_str(value) + if value != value.strip(): + params = {'value': value} +~~ raise ValidationError(self.message, code=self.code, params=params) + + def __eq__(self, other): + return ( + isinstance(other, NoWhitespaceValidator) and + (self.message == other.message) and + (self.code == other.code) + ) + + +@deconstructible +class HexValidator: + messages = { + 'invalid': _("Only a hex string is allowed."), + 'length': _("Invalid length. Must be %(length)d characters."), + 'min_length': _("Ensure that there are more than %(min)s characters."), + 'max_length': _("Ensure that there are no more than %(max)s characters."), + } + code = "hex_only" + + def __init__(self, length=None, min_length=None, max_length=None, message=None, code=None): + self.length = length + self.min_length = min_length + self.max_length = max_length + if message: + self.message = message + if code: + self.code = code + + def __call__(self, value): + value = force_str(value) + if self.length and len(value) != self.length: +~~ raise ValidationError(self.messages['length'], code='hex_only_length', params={'length': self.length}) + if self.min_length and len(value) < self.min_length: +~~ raise ValidationError(self.messages['min_length'], code='hex_only_min_length', params={'min': self.min_length}) + if self.max_length and len(value) < self.max_length: +~~ raise ValidationError(self.messages['max_length'], code='hex_only_max_length', params={'max': self.max_length}) + + try: + binascii.unhexlify(value) + except (TypeError, binascii.Error): +~~ raise ValidationError(self.messages['invalid'], code='hex_only') + + def __eq__(self, other): + return ( + isinstance(other, HexValidator) and + (self.message == other.message) and + (self.code == other.code) + ) + + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 7 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / forms.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/forms.py) + +```python +# forms.py +from __future__ import absolute_import + +from django import forms +from django.conf import settings +from django.contrib.admin import widgets +~~from django.core.exceptions import ValidationError +from django.db import models +from django.utils.translation import ugettext as _ + +from ..models import ThumbnailOption +from ..utils.files import get_valid_filename + + +class AsPWithHelpMixin(object): + def as_p_with_help(self): + "Returns this form rendered as HTML

s with help text formated for admin." + return self._html_output( + normal_row='%(label)s %(field)s

%(help_text)s', + error_row='%s', + row_ender='

', + help_text_html='

%s

', + errors_on_separate_row=True) + + +class CopyFilesAndFoldersForm(forms.Form, AsPWithHelpMixin): + suffix = forms.CharField(required=False, help_text=_("Suffix which will be appended to filenames of copied files.")) + + def clean_suffix(self): + valid = get_valid_filename(self.cleaned_data['suffix']) + if valid != self.cleaned_data['suffix']: + + +## ... source file abbreviated to get to ValidationError examples ... + + + } + except KeyError as e: + raise forms.ValidationError(_('Unknown rename format value key "%(key)s".') % {'key': e.args[0]}) + except Exception as e: + raise forms.ValidationError(_('Invalid rename format: %(error)s.') % {'error': e}) + return self.cleaned_data['rename_format'] + + +class ResizeImagesForm(forms.Form, AsPWithHelpMixin): + if 'cmsplugin_filer_image' in settings.INSTALLED_APPS: + thumbnail_option = models.ForeignKey( + ThumbnailOption, + null=True, + blank=True, + verbose_name=_("thumbnail option"), + on_delete=models.CASCADE, + ).formfield() + width = models.PositiveIntegerField(_("width"), null=True, blank=True).formfield(widget=widgets.AdminIntegerFieldWidget) + height = models.PositiveIntegerField(_("height"), null=True, blank=True).formfield(widget=widgets.AdminIntegerFieldWidget) + crop = models.BooleanField(_("crop"), default=True).formfield() + upscale = models.BooleanField(_("upscale"), default=True).formfield() + + def clean(self): + if not (self.cleaned_data.get('thumbnail_option') or ((self.cleaned_data.get('width') or 0) + (self.cleaned_data.get('height') or 0))): + if 'cmsplugin_filer_image' in settings.INSTALLED_APPS: +~~ raise ValidationError(_('Thumbnail option or resize parameters must be choosen.')) + else: +~~ raise ValidationError(_('Resize parameters must be choosen.')) + return self.cleaned_data + + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 8 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / models / models.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/models/models.py) + +```python +# models.py +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +~~from django.core.exceptions import ValidationError +from django.db import models +from django.utils.translation import gettext_lazy as _ +from guardian.compat import user_model_label +from guardian.ctypes import get_content_type +from guardian.managers import GroupObjectPermissionManager, UserObjectPermissionManager + + +class BaseObjectPermission(models.Model): + permission = models.ForeignKey(Permission, on_delete=models.CASCADE) + + class Meta: + abstract = True + + def __str__(self): + return '{} | {} | {}'.format( + str(self.content_object), + str(getattr(self, 'user', False) or self.group), + str(self.permission.codename)) + + def save(self, *args, **kwargs): + content_type = get_content_type(self.content_object) + if content_type != self.permission.content_type: +~~ raise ValidationError("Cannot persist permission not designed for " + "this class (permission's type is %r and object's type is %r)" + % (self.permission.content_type, content_type)) + return super().save(*args, **kwargs) + + +class BaseGenericObjectPermission(models.Model): + content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) + object_pk = models.CharField(_('object ID'), max_length=255) + content_object = GenericForeignKey(fk_field='object_pk') + + class Meta: + abstract = True + indexes = [ + models.Index(fields=['content_type', 'object_pk']), + ] + + +class UserObjectPermissionBase(BaseObjectPermission): + user = models.ForeignKey(user_model_label, on_delete=models.CASCADE) + + objects = UserObjectPermissionManager() + + class Meta: + abstract = True + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 9 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / resources.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./resources.py) + +```python +# resources.py +import functools +import logging +import tablib +import traceback +from collections import OrderedDict +from copy import deepcopy + +from diff_match_patch import diff_match_patch + +import django +from django.conf import settings +~~from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.core.management.color import no_style +from django.core.paginator import Paginator +from django.db import DEFAULT_DB_ALIAS, connections +from django.db.models.fields.related import ForeignObjectRel +from django.db.models.query import QuerySet +from django.db.transaction import ( + TransactionManagementError, + atomic, + savepoint, + savepoint_commit, + savepoint_rollback +) +from django.utils.encoding import force_str +from django.utils.safestring import mark_safe + +from . import widgets +from .fields import Field +from .instance_loaders import ModelInstanceLoader +from .results import Error, Result, RowResult +from .utils import atomic_if_using_transaction + +if django.VERSION[0] >= 3: + from django.core.exceptions import FieldDoesNotExist +else: + + +## ... source file abbreviated to get to ValidationError examples ... + + + else: + delete_ids = [o.pk for o in self.delete_instances] + self._meta.model.objects.filter(pk__in=delete_ids).delete() + except Exception as e: + logger.exception(e) + if raise_errors: + raise e + finally: + self.delete_instances.clear() + + def validate_instance(self, instance, import_validation_errors=None, validate_unique=True): + if import_validation_errors is None: + errors = {} + else: + errors = import_validation_errors.copy() + if self._meta.clean_model_instances: + try: + instance.full_clean( + exclude=errors.keys(), + validate_unique=validate_unique, + ) +~~ except ValidationError as e: + errors = e.update_error_dict(errors) + + if errors: +~~ raise ValidationError(errors) + + def save_instance(self, instance, using_transactions=True, dry_run=False): + self.before_save_instance(instance, using_transactions, dry_run) + if self._meta.use_bulk: + if instance.pk: + self.update_instances.append(instance) + else: + self.create_instances.append(instance) + else: + if not using_transactions and dry_run: + pass + else: + instance.save() + self.after_save_instance(instance, using_transactions, dry_run) + + def before_save_instance(self, instance, using_transactions, dry_run): + pass + + def after_save_instance(self, instance, using_transactions, dry_run): + pass + + def delete_instance(self, instance, using_transactions=True, dry_run=False): + self.before_delete_instance(instance, dry_run) + if self._meta.use_bulk: + + +## ... source file abbreviated to get to ValidationError examples ... + + + else: + instance.delete() + self.after_delete_instance(instance, dry_run) + + def before_delete_instance(self, instance, dry_run): + pass + + def after_delete_instance(self, instance, dry_run): + pass + + def import_field(self, field, obj, data, is_m2m=False): + if field.attribute and field.column_name in data: + field.save(obj, data, is_m2m) + + def get_import_fields(self): + return self.get_fields() + + def import_obj(self, obj, data, dry_run): + errors = {} + for field in self.get_import_fields(): + if isinstance(field.widget, widgets.ManyToManyWidget): + continue + try: + self.import_field(field, obj, data) + except ValueError as e: +~~ errors[field.attribute] = ValidationError( + force_str(e), code="invalid") + if errors: +~~ raise ValidationError(errors) + + def save_m2m(self, obj, data, using_transactions, dry_run): + if (not using_transactions and dry_run) or self._meta.use_bulk: + pass + else: + for field in self.get_import_fields(): + if not isinstance(field.widget, widgets.ManyToManyWidget): + continue + self.import_field(field, obj, data, True) + + def for_delete(self, row, instance): + return False + + def skip_row(self, instance, original): + if not self._meta.skip_unchanged or self._meta.skip_diff: + return False + for field in self.get_import_fields(): + try: + if list(field.get_value(instance).all()) != list(field.get_value(original).all()): + return False + except AttributeError: + if field.get_value(instance) != field.get_value(original): + return False + return True + try: + if len(self.delete_instances) > 0: + if not using_transactions and dry_run: + pass + + +## ... source file abbreviated to get to ValidationError examples ... + + + self.before_import_row(row, **kwargs) + instance, new = self.get_or_init_instance(instance_loader, row) + self.after_import_instance(instance, new, **kwargs) + if new: + row_result.import_type = RowResult.IMPORT_TYPE_NEW + else: + row_result.import_type = RowResult.IMPORT_TYPE_UPDATE + row_result.new_record = new + if not skip_diff: + original = deepcopy(instance) + diff = self.get_diff_class()(self, original, new) + if self.for_delete(row, instance): + if new: + row_result.import_type = RowResult.IMPORT_TYPE_SKIP + if not skip_diff: + diff.compare_with(self, None, dry_run) + else: + row_result.import_type = RowResult.IMPORT_TYPE_DELETE + self.delete_instance(instance, using_transactions, dry_run) + if not skip_diff: + diff.compare_with(self, None, dry_run) + else: + import_validation_errors = {} + try: + self.import_obj(instance, row, dry_run) +~~ except ValidationError as e: + import_validation_errors = e.update_error_dict(import_validation_errors) + if self.skip_row(instance, original): + row_result.import_type = RowResult.IMPORT_TYPE_SKIP + else: + self.validate_instance(instance, import_validation_errors) + self.save_instance(instance, using_transactions, dry_run) + self.save_m2m(instance, row, using_transactions, dry_run) + row_result.object_id = instance.pk + row_result.object_repr = force_str(instance) + if not skip_diff: + diff.compare_with(self, instance, dry_run) + + if not skip_diff: + row_result.diff = diff.as_html() + self.after_import_row(row, row_result, **kwargs) + +~~ except ValidationError as e: + row_result.import_type = RowResult.IMPORT_TYPE_INVALID + row_result.validation_error = e + except Exception as e: + row_result.import_type = RowResult.IMPORT_TYPE_ERROR + if not isinstance(e, TransactionManagementError): + logger.debug(e, exc_info=e) + tb_info = traceback.format_exc() + row_result.errors.append(self.get_error_result_class()(e, tb_info, row)) + + if self._meta.use_bulk: + if len(self.create_instances) == self._meta.batch_size: + self.bulk_create(using_transactions, dry_run, raise_errors, batch_size=self._meta.batch_size) + if len(self.update_instances) == self._meta.batch_size: + self.bulk_update(using_transactions, dry_run, raise_errors, batch_size=self._meta.batch_size) + if len(self.delete_instances) == self._meta.batch_size: + self.bulk_delete(using_transactions, dry_run, raise_errors) + + return row_result + + def import_data(self, dataset, dry_run=False, raise_errors=False, + use_transactions=None, collect_failed_rows=False, **kwargs): + + if use_transactions is None: + use_transactions = self.get_use_transactions() + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 10 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / forms.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./forms.py) + +```python +# forms.py +import json +from django import forms +from django.contrib.auth.models import Permission +from django.contrib.contenttypes.models import ContentType +~~from django.core.exceptions import ValidationError +from django.db.models import Q +import operator + +from jet.models import Bookmark, PinnedApplication +from jet.utils import get_model_instance_label, user_is_authenticated +from functools import reduce + +try: + from django.apps import apps + get_model = apps.get_model +except ImportError: + from django.db.models.loading import get_model + + +class AddBookmarkForm(forms.ModelForm): + def __init__(self, request, *args, **kwargs): + self.request = request + super(AddBookmarkForm, self).__init__(*args, **kwargs) + + class Meta: + model = Bookmark + fields = ['url', 'title'] + + def clean(self): + data = super(AddBookmarkForm, self).clean() + if not user_is_authenticated(self.request.user) or not self.request.user.is_staff: +~~ raise ValidationError('error') + if not self.request.user.has_perm('jet.change_bookmark'): +~~ raise ValidationError('error') + return data + + def save(self, commit=True): + self.instance.user = self.request.user.pk + return super(AddBookmarkForm, self).save(commit) + + +class RemoveBookmarkForm(forms.ModelForm): + def __init__(self, request, *args, **kwargs): + self.request = request + super(RemoveBookmarkForm, self).__init__(*args, **kwargs) + + class Meta: + model = Bookmark + fields = [] + + def clean(self): + data = super(RemoveBookmarkForm, self).clean() + if not user_is_authenticated(self.request.user) or not self.request.user.is_staff: +~~ raise ValidationError('error') + if self.instance.user != self.request.user.pk: +~~ raise ValidationError('error') + return data + + def save(self, commit=True): + if commit: + self.instance.delete() + + +class ToggleApplicationPinForm(forms.ModelForm): + def __init__(self, request, *args, **kwargs): + self.request = request + super(ToggleApplicationPinForm, self).__init__(*args, **kwargs) + + class Meta: + model = PinnedApplication + fields = ['app_label'] + + def clean(self): + data = super(ToggleApplicationPinForm, self).clean() + if not user_is_authenticated(self.request.user) or not self.request.user.is_staff: +~~ raise ValidationError('error') + return data + + def save(self, commit=True): + if commit: + try: + pinned_app = PinnedApplication.objects.get( + app_label=self.cleaned_data['app_label'], + user=self.request.user.pk + ) + pinned_app.delete() + return False + except PinnedApplication.DoesNotExist: + PinnedApplication.objects.create( + app_label=self.cleaned_data['app_label'], + user=self.request.user.pk + ) + return True + + +class ModelLookupForm(forms.Form): + app_label = forms.CharField() + model = forms.CharField() + q = forms.CharField(required=False) + page = forms.IntegerField(required=False) + page_size = forms.IntegerField(required=False, min_value=1, max_value=1000) + object_id = forms.IntegerField(required=False) + model_cls = None + + def __init__(self, request, *args, **kwargs): + self.request = request + super(ModelLookupForm, self).__init__(*args, **kwargs) + + def clean(self): + data = super(ModelLookupForm, self).clean() + + if not user_is_authenticated(self.request.user) or not self.request.user.is_staff: +~~ raise ValidationError('error') + + try: + self.model_cls = get_model(data['app_label'], data['model']) + except: +~~ raise ValidationError('error') + + content_type = ContentType.objects.get_for_model(self.model_cls) + permission = Permission.objects.filter(content_type=content_type, codename__startswith='change_').first() + + if not self.request.user.has_perm('{}.{}'.format(data['app_label'], permission.codename)): +~~ raise ValidationError('error') + + return data + + def lookup(self): + qs = self.model_cls.objects + + if self.cleaned_data['q']: + if getattr(self.model_cls, 'autocomplete_search_fields', None): + search_fields = self.model_cls.autocomplete_search_fields() + filter_data = [Q((field + '__icontains', self.cleaned_data['q'])) for field in search_fields] + qs = qs.filter(reduce(operator.or_, filter_data)).distinct() + else: + qs = qs.none() + + limit = self.cleaned_data['page_size'] or 100 + page = self.cleaned_data['page'] or 1 + offset = (page - 1) * limit + + items = list(map( + lambda instance: {'id': instance.pk, 'text': get_model_instance_label(instance)}, + qs.all()[offset:offset + limit] + )) + total = qs.count() + + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 11 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / fields.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./fields.py) + +```python +# fields.py +import uuid +from django.db import models +from django.conf import settings +~~from django.core.exceptions import ValidationError +from django.utils.timezone import now + +DEFAULT_CHOICES_NAME = 'STATUS' + + +class AutoCreatedField(models.DateTimeField): + + def __init__(self, *args, **kwargs): + kwargs.setdefault('editable', False) + kwargs.setdefault('default', now) + super().__init__(*args, **kwargs) + + +class AutoLastModifiedField(AutoCreatedField): + def get_default(self): + if not hasattr(self, "_default"): + self._default = self._get_default() + return self._default + + def pre_save(self, model_instance, add): + value = now() + if add: + current_value = getattr(model_instance, self.attname, self.get_default()) + if current_value != self.get_default(): + + +## ... source file abbreviated to get to ValidationError examples ... + + + excerpt = get_excerpt(value.content) + setattr(model_instance, _excerpt_field_name(self.attname), excerpt) + return value.content + + def value_to_string(self, obj): + value = self.value_from_object(obj) + return value.content + + def get_prep_value(self, value): + try: + return value.content + except AttributeError: + return value + + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + kwargs['no_excerpt_field'] = True + return name, path, args, kwargs + + +class UUIDField(models.UUIDField): + + def __init__(self, primary_key=True, version=4, editable=False, *args, **kwargs): + + if version == 2: +~~ raise ValidationError( + 'UUID version 2 is not supported.') + + if version < 1 or version > 5: +~~ raise ValidationError( + 'UUID version is not valid.') + + if version == 1: + default = uuid.uuid1 + elif version == 3: + default = uuid.uuid3 + elif version == 4: + default = uuid.uuid4 + elif version == 5: + default = uuid.uuid5 + + kwargs.setdefault('primary_key', primary_key) + kwargs.setdefault('editable', editable) + kwargs.setdefault('default', default) + super().__init__(*args, **kwargs) + + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 12 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / models.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./models.py) + +```python +# models.py +import logging +from datetime import timedelta +from urllib.parse import parse_qsl, urlparse + +from django.apps import apps +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db import models, transaction +from django.urls import reverse +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ + +from .generators import generate_client_id, generate_client_secret +from .scopes import get_scopes_backend +from .settings import oauth2_settings +from .validators import RedirectURIValidator, WildcardSet + + +logger = logging.getLogger(__name__) + + +class AbstractApplication(models.Model): + CLIENT_CONFIDENTIAL = "confidential" + CLIENT_PUBLIC = "public" + CLIENT_TYPES = ( + (CLIENT_CONFIDENTIAL, _("Confidential")), + (CLIENT_PUBLIC, _("Public")), + ) + + GRANT_AUTHORIZATION_CODE = "authorization-code" + GRANT_IMPLICIT = "implicit" + GRANT_PASSWORD = "password" + GRANT_CLIENT_CREDENTIALS = "client-credentials" + GRANT_TYPES = ( + (GRANT_AUTHORIZATION_CODE, _("Authorization code")), + + +## ... source file abbreviated to get to ValidationError examples ... + + + + assert False, ( + "If you are using implicit, authorization_code" + "or all-in-one grant_type, you must define " + "redirect_uris field in your Application model" + ) + + def redirect_uri_allowed(self, uri): + parsed_uri = urlparse(uri) + uqs_set = set(parse_qsl(parsed_uri.query)) + for allowed_uri in self.redirect_uris.split(): + parsed_allowed_uri = urlparse(allowed_uri) + + if (parsed_allowed_uri.scheme == parsed_uri.scheme and + parsed_allowed_uri.netloc == parsed_uri.netloc and + parsed_allowed_uri.path == parsed_uri.path): + + aqs_set = set(parse_qsl(parsed_allowed_uri.query)) + + if aqs_set.issubset(uqs_set): + return True + + return False + + def clean(self): +~~ from django.core.exceptions import ValidationError + + grant_types = ( + AbstractApplication.GRANT_AUTHORIZATION_CODE, + AbstractApplication.GRANT_IMPLICIT, + ) + + redirect_uris = self.redirect_uris.strip().split() + allowed_schemes = set(s.lower() for s in self.get_allowed_schemes()) + + if redirect_uris: + validator = RedirectURIValidator(WildcardSet()) + for uri in redirect_uris: + validator(uri) + scheme = urlparse(uri).scheme + if scheme not in allowed_schemes: +~~ raise ValidationError(_( + "Unauthorized redirect scheme: {scheme}" + ).format(scheme=scheme)) + + elif self.authorization_grant_type in grant_types: +~~ raise ValidationError(_( + "redirect_uris cannot be empty with grant_type {grant_type}" + ).format(grant_type=self.authorization_grant_type)) + + def get_absolute_url(self): + return reverse("oauth2_provider:detail", args=[str(self.id)]) + + def get_allowed_schemes(self): + return oauth2_settings.ALLOWED_REDIRECT_URI_SCHEMES + + def allows_grant_type(self, *grant_types): + return self.authorization_grant_type in grant_types + + def is_usable(self, request): + return True + + +class ApplicationManager(models.Manager): + def get_by_natural_key(self, client_id): + return self.get(client_id=client_id) + + +class Application(AbstractApplication): + objects = ApplicationManager() + + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 13 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / fields.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./fields.py) + +```python +# fields.py +import copy +import datetime +import decimal +import functools +import inspect +import re +import uuid +import warnings +from collections import OrderedDict +from collections.abc import Mapping + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +~~from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import ( + EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator, + MinValueValidator, ProhibitNullCharactersValidator, RegexValidator, + URLValidator, ip_address_validators +) +from django.forms import FilePathField as DjangoFilePathField +from django.forms import ImageField as DjangoImageField +from django.utils import timezone +from django.utils.dateparse import ( + parse_date, parse_datetime, parse_duration, parse_time +) +from django.utils.duration import duration_string +from django.utils.encoding import is_protected_type, smart_str +from django.utils.formats import localize_input, sanitize_separators +from django.utils.ipv6 import clean_ipv6_address +from django.utils.timezone import utc +from django.utils.translation import gettext_lazy as _ +from pytz.exceptions import InvalidTimeError + +from rest_framework import ( + ISO_8601, RemovedInDRF313Warning, RemovedInDRF314Warning +) +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.settings import api_settings + + +## ... source file abbreviated to get to ValidationError examples ... + + + def run_validators(self, value): + errors = [] + for validator in self.validators: + if hasattr(validator, 'set_context'): + warnings.warn( + "Method `set_context` on validators is deprecated and will " + "no longer be called starting with 3.13. Instead set " + "`requires_context = True` on the class, and accept the " + "context as an additional argument.", + RemovedInDRF313Warning, stacklevel=2 + ) + validator.set_context(self) + + try: + if getattr(validator, 'requires_context', False): + validator(value, self) + else: + validator(value) +~~ except ValidationError as exc: + if isinstance(exc.detail, dict): + raise + errors.extend(exc.detail) + except DjangoValidationError as exc: + errors.extend(get_error_detail(exc)) + if errors: +~~ raise ValidationError(errors) + + def to_internal_value(self, data): + raise NotImplementedError( + '{cls}.to_internal_value() must be implemented for field ' + '{field_name}. If you do not need to support write operations ' + 'you probably want to subclass `ReadOnlyField` instead.'.format( + cls=self.__class__.__name__, + field_name=self.field_name, + ) + ) + + def to_representation(self, value): + raise NotImplementedError( + '{cls}.to_representation() must be implemented for field {field_name}.'.format( + cls=self.__class__.__name__, + field_name=self.field_name, + ) + ) + + def fail(self, key, **kwargs): + try: + msg = self.error_messages[key] + except KeyError: + class_name = self.__class__.__name__ + msg = MISSING_ERROR_MESSAGE.format(class_name=class_name, key=key) + raise AssertionError(msg) + message_string = msg.format(**kwargs) +~~ raise ValidationError(message_string, code=key) + + @property + def root(self): + root = self + while root.parent is not None: + root = root.parent + return root + + @property + def context(self): + return getattr(self.root, '_context', {}) + + def __new__(cls, *args, **kwargs): + instance = super().__new__(cls) + instance._args = args + instance._kwargs = kwargs + return instance + + def __deepcopy__(self, memo): + args = [ + copy.deepcopy(item) if not isinstance(item, REGEX_TYPE) else item + for item in self._args + ] + kwargs = { + + +## ... source file abbreviated to get to ValidationError examples ... + + + + def to_internal_value(self, data): + if html.is_html_input(data): + data = html.parse_html_list(data, default=[]) + if isinstance(data, (str, Mapping)) or not hasattr(data, '__iter__'): + self.fail('not_a_list', input_type=type(data).__name__) + if not self.allow_empty and len(data) == 0: + self.fail('empty') + return self.run_child_validation(data) + + def to_representation(self, data): + return [self.child.to_representation(item) if item is not None else None for item in data] + + def run_child_validation(self, data): + result = [] + errors = OrderedDict() + + for idx, item in enumerate(data): + try: + result.append(self.child.run_validation(item)) +~~ except ValidationError as e: + errors[idx] = e.detail + + if not errors: + return result +~~ raise ValidationError(errors) + + +class DictField(Field): + child = _UnvalidatedField() + initial = {} + default_error_messages = { + 'not_a_dict': _('Expected a dictionary of items but got type "{input_type}".'), + 'empty': _('This dictionary may not be empty.'), + } + + def __init__(self, *args, **kwargs): + self.child = kwargs.pop('child', copy.deepcopy(self.child)) + self.allow_empty = kwargs.pop('allow_empty', True) + + assert not inspect.isclass(self.child), '`child` has not been instantiated.' + assert self.child.source is None, ( + "The `source` argument is not meaningful when applied to a `child=` field. " + "Remove `source=` from the field declaration." + ) + + super().__init__(*args, **kwargs) + self.child.bind(field_name='', parent=self) + + def get_value(self, dictionary): + + +## ... source file abbreviated to get to ValidationError examples ... + + + if not self.allow_empty and len(data) == 0: + self.fail('empty') + + return self.run_child_validation(data) + + def to_representation(self, value): + return { + str(key): self.child.to_representation(val) if val is not None else None + for key, val in value.items() + } + + def run_child_validation(self, data): + result = {} + errors = OrderedDict() + + for key, value in data.items(): + key = str(key) + + try: + result[key] = self.child.run_validation(value) +~~ except ValidationError as e: + errors[key] = e.detail + + if not errors: + return result +~~ raise ValidationError(errors) + + +class HStoreField(DictField): + child = CharField(allow_blank=True, allow_null=True) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + assert isinstance(self.child, CharField), ( + "The `child` argument must be an instance of `CharField`, " + "as the hstore extension stores values as strings." + ) + + +class JSONField(Field): + default_error_messages = { + 'invalid': _('Value must be valid JSON.') + } + + def __init__(self, *args, **kwargs): + self.binary = kwargs.pop('binary', False) + self.encoder = kwargs.pop('encoder', None) + super().__init__(*args, **kwargs) + + def get_value(self, dictionary): + (is_empty_value, data) = self.validate_empty_values(data) + if is_empty_value: + return data + value = self.to_internal_value(data) + self.run_validators(value) + return value + + + +## ... source file abbreviated to get to ValidationError examples ... + + + if len(val) > 0: + return val + return html.parse_html_list(dictionary, prefix=self.field_name, default=empty) + + return dictionary.get(self.field_name, empty) + + +## ... source file abbreviated to get to ValidationError examples ... + + + def to_internal_value(self, data): + if html.is_html_input(data): + data = html.parse_html_dict(data) + if not isinstance(data, dict): + self.fail('not_a_dict', input_type=type(data).__name__) + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 14 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / models / urlpath.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/models/urlpath.py) + +```python +# urlpath.py +import logging +import warnings + +from django.contrib.contenttypes.fields import GenericRelation +from django.contrib.contenttypes.models import ContentType +from django.contrib.sites.models import Site +~~from django.core.exceptions import ValidationError +from django.db import models +from django.db import transaction +from django.db.models.signals import post_save +from django.db.models.signals import pre_delete +from django.urls import reverse +from django.utils.translation import gettext +from django.utils.translation import gettext_lazy as _ +from mptt.fields import TreeForeignKey +from mptt.models import MPTTModel +from wiki import managers +from wiki.conf import settings +from wiki.core.exceptions import MultipleRootURLs +from wiki.core.exceptions import NoRootURL +from wiki.decorators import disable_signal_for_loaddata +from wiki.models.article import Article +from wiki.models.article import ArticleForObject +from wiki.models.article import ArticleRevision + +__all__ = [ + "URLPath", +] + + +log = logging.getLogger(__name__) + + +## ... source file abbreviated to get to ValidationError examples ... + + + raise NoRootURL("You need to create a root article on site '%s'" % site) + if no_paths > 1: + raise MultipleRootURLs("Somehow you have multiple roots on %s" % site) + return root_nodes[0] + + class MPTTMeta: + pass + + def __str__(self): + path = self.path + return path if path else gettext("(root)") + + def delete(self, *args, **kwargs): + assert not ( + self.parent and self.get_children() + ), "You cannot delete a root article with children." + super().delete(*args, **kwargs) + + class Meta: + verbose_name = _("URL path") + verbose_name_plural = _("URL paths") + unique_together = ("site", "parent", "slug") + + def clean(self, *args, **kwargs): + if self.slug and not self.parent: +~~ raise ValidationError( + _("Sorry but you cannot have a root article with a slug.") + ) + if not self.slug and self.parent: +~~ raise ValidationError(_("A non-root note must always have a slug.")) + if not self.parent: + if URLPath.objects.root_nodes().filter(site=self.site).exclude(id=self.id): +~~ raise ValidationError( + _("There is already a root node on %s") % self.site + ) + + @classmethod + def get_by_path(cls, path, select_related=False): + + + path = path.lstrip("/") + path = path.rstrip("/") + + if not path: + return cls.root() + + slugs = path.split("/") + level = 1 + parent = cls.root() + for slug in slugs: + if settings.URL_CASE_SENSITIVE: + child = parent.get_children().select_related_common().get(slug=slug) + child.cached_ancestors = parent.cached_ancestors + [parent] + parent = child + else: + child = ( + parent.get_children().select_related_common().get(slug__iexact=slug) + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 15 from register +[register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is +open source under the +[GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). +This web application makes it easier for people to register as organ donors. +You can see the application live at +[https://register.organize.org/](https://register.organize.org/). + +[**register / registration / forms.py**](https://github.com/ORGAN-IZE/register/blob/master/registration/./forms.py) + +```python +# forms.py +from __future__ import unicode_literals + +import logging +import re +import collections +import datetime + +import django.forms +import django.forms.utils +import django.forms.widgets +import django.core.validators +~~import django.core.exceptions +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ +from django.utils.safestring import mark_safe + +import form_utils.forms +import requests +import dateutil.parser +import validate_email + +logger = logging.getLogger(__name__) + + +REGISTRATION_CONFIGURATION_NAME = 'registration_configuration' + +RE_NON_DECIMAL = re.compile(r'[^\d]+') +RE_NON_ALPHA = re.compile('[\W]+') +RE_POSTAL_CODE = re.compile(r'^[0-9]{5}$') +validate_postal_code = django.core.validators.RegexValidator( + RE_POSTAL_CODE, _("Enter a valid postal code consisting 5 numbers."), 'invalid') + + +CHOICES_GENDER = ( + ('M', _('Male')), + ('F', _('Female')), +) + + +class MultiEmailField(django.forms.CharField): + message = _('Enter valid email addresses.') + code = 'invalid' + widget = django.forms.widgets.TextInput + + def to_python(self, value): + "Normalize data to a list of strings." + if not value: + return [] + return [v.strip() for v in re.findall(validate_email.ADDR_SPEC, value)] + + def validate(self, value): + "Check if value consists only of valid emails." + + super(MultiEmailField, self).validate(value) + try: + for email in value: + django.core.validators.validate_email(email) + except django.core.exceptions.ValidationError: +~~ raise django.core.exceptions.ValidationError(self.message, code=self.code) + + + + + +class StateLookupForm(django.forms.Form): + email = django.forms.EmailField(label=_('Email'), help_text=_('so we can send you confirmation of your registration')) + postal_code = django.forms.CharField( + label=_('Postal Code'), + max_length=5, min_length=5, validators=[validate_postal_code], + help_text=_('to determine which series of state-based questions we will ask next')) + + def clean_email(self): + email = self.cleaned_data['email'] + if settings.DISABLE_EMAIL_VALIDATION: + logger.warning('Email validation disabled: DISABLE_EMAIL_VALIDATION ' + 'is set') + return email + if not hasattr(settings, 'MAILGUN_PUBLIC_API_KEY'): + logger.warning( + 'Cannot validate email: MAILGUN_PUBLIC_API_KEY not set') + return email + r = requests.get( + 'https://api.mailgun.net/v2/address/validate', + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 16 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / snippets / tests.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/snippets/tests.py) + +```python +# tests.py +import json + +from django.contrib.admin.utils import quote +from django.contrib.auth import get_user_model +from django.contrib.auth.models import AnonymousUser, Permission +from django.core import checks +~~from django.core.exceptions import ValidationError +from django.core.files.base import ContentFile +from django.core.files.uploadedfile import SimpleUploadedFile +from django.http import HttpRequest, HttpResponse +from django.test import RequestFactory, TestCase +from django.test.utils import override_settings +from django.urls import reverse +from taggit.models import Tag + +from wagtail.admin.edit_handlers import FieldPanel +from wagtail.admin.forms import WagtailAdminModelForm +from wagtail.core.models import Page +from wagtail.snippets.blocks import SnippetChooserBlock +from wagtail.snippets.edit_handlers import SnippetChooserPanel +from wagtail.snippets.models import SNIPPET_MODELS, register_snippet +from wagtail.snippets.views.snippets import get_snippet_edit_handler +from wagtail.tests.snippets.forms import FancySnippetForm +from wagtail.tests.snippets.models import ( + AlphaSnippet, FancySnippet, FileUploadSnippet, RegisterDecorator, RegisterFunction, + SearchableSnippet, StandardSnippet, StandardSnippetWithCustomPrimaryKey, ZuluSnippet) +from wagtail.tests.testapp.models import ( + Advert, AdvertWithCustomPrimaryKey, AdvertWithCustomUUIDPrimaryKey, AdvertWithTabbedInterface, + SnippetChooserModel, SnippetChooserModelWithCustomPrimaryKey) +from wagtail.tests.utils import WagtailTestUtils + + + +## ... source file abbreviated to get to ValidationError examples ... + + + self.assertInHTML('', empty_form_html) + self.assertIn('createSnippetChooser("advert", "tests/advert");', empty_form_html) + + test_advert = Advert.objects.get(text='test_advert') + test_advert_form_html = block.render_form(test_advert, 'advert') + expected_html = '' % test_advert.id + self.assertInHTML(expected_html, test_advert_form_html) + self.assertIn("pick an advert, any advert", test_advert_form_html) + + def test_form_response(self): + block = SnippetChooserBlock(Advert) + test_advert = Advert.objects.get(text='test_advert') + + value = block.value_from_datadict({'advert': str(test_advert.id)}, {}, 'advert') + self.assertEqual(value, test_advert) + + empty_value = block.value_from_datadict({'advert': ''}, {}, 'advert') + self.assertEqual(empty_value, None) + + def test_clean(self): + required_block = SnippetChooserBlock(Advert) + nonrequired_block = SnippetChooserBlock(Advert, required=False) + test_advert = Advert.objects.get(text='test_advert') + + self.assertEqual(required_block.clean(test_advert), test_advert) +~~ with self.assertRaises(ValidationError): + required_block.clean(None) + + self.assertEqual(nonrequired_block.clean(test_advert), test_advert) + self.assertEqual(nonrequired_block.clean(None), None) + + +class TestSnippetListViewWithCustomPrimaryKey(TestCase, WagtailTestUtils): + def setUp(self): + self.login() + + self.snippet_a = StandardSnippetWithCustomPrimaryKey.objects.create(snippet_id="snippet/01", text="Hello") + self.snippet_b = StandardSnippetWithCustomPrimaryKey.objects.create(snippet_id="snippet/02", text="Hello") + self.snippet_c = StandardSnippetWithCustomPrimaryKey.objects.create(snippet_id="snippet/03", text="Hello") + + def get(self, params={}): + return self.client.get(reverse('wagtailsnippets:list', + args=('snippetstests', 'standardsnippetwithcustomprimarykey')), + params) + + def test_simple(self): + response = self.get() + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'wagtailsnippets/snippets/type_index.html') + + + +## ... source file abbreviated to get to ValidationError examples ... + + + self.assertInHTML('', empty_form_html) + self.assertIn('createSnippetChooser("advertwithcustomprimarykey", "tests/advertwithcustomprimarykey");', empty_form_html) + + test_advert = AdvertWithCustomPrimaryKey.objects.get(pk='advert/01') + test_advert_form_html = block.render_form(test_advert, 'advertwithcustomprimarykey') + expected_html = '' % test_advert.pk + self.assertInHTML(expected_html, test_advert_form_html) + self.assertIn("pick an advert, any advert", test_advert_form_html) + + def test_form_response(self): + block = SnippetChooserBlock(AdvertWithCustomPrimaryKey) + test_advert = AdvertWithCustomPrimaryKey.objects.get(pk='advert/01') + + value = block.value_from_datadict({'advertwithcustomprimarykey': str(test_advert.pk)}, {}, 'advertwithcustomprimarykey') + self.assertEqual(value, test_advert) + + empty_value = block.value_from_datadict({'advertwithcustomprimarykey': ''}, {}, 'advertwithcustomprimarykey') + self.assertEqual(empty_value, None) + + def test_clean(self): + required_block = SnippetChooserBlock(AdvertWithCustomPrimaryKey) + nonrequired_block = SnippetChooserBlock(AdvertWithCustomPrimaryKey, required=False) + test_advert = AdvertWithCustomPrimaryKey.objects.get(pk='advert/01') + + self.assertEqual(required_block.clean(test_advert), test_advert) +~~ with self.assertRaises(ValidationError): + required_block.clean(None) + + self.assertEqual(nonrequired_block.clean(test_advert), test_advert) + self.assertEqual(nonrequired_block.clean(None), None) + + +class TestSnippetChooserPanelWithCustomPrimaryKey(TestCase, WagtailTestUtils): + fixtures = ['test.json'] + + def setUp(self): + self.request = RequestFactory().get('/') + user = AnonymousUser() # technically, Anonymous users cannot access the admin + self.request.user = user + + model = SnippetChooserModelWithCustomPrimaryKey + self.advert_text = 'Test advert text' + test_snippet = model.objects.create( + advertwithcustomprimarykey=AdvertWithCustomPrimaryKey.objects.create( + advert_id="advert/02", + text=self.advert_text + ) + ) + + self.edit_handler = get_snippet_edit_handler(model) + + +## ... source file continues with no further ValidationError examples... + +``` + diff --git a/content/pages/examples/django/django-core-exceptions.markdown b/content/pages/examples/django/django-core-exceptions.markdown new file mode 100644 index 000000000..b1aa162cf --- /dev/null +++ b/content/pages/examples/django/django-core-exceptions.markdown @@ -0,0 +1,183 @@ +title: django.core exceptions code examples +category: page +slug: django-core-exceptions-examples +sortorder: 500011080 +toc: False +sidebartitle: django.core exceptions +meta: Python example code for the exceptions function from the django.core module of the Django project. + + +exceptions is a function within the django.core module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / forms.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/forms.py) + +```python +# forms.py +from __future__ import absolute_import + +import warnings +from importlib import import_module + +from django import forms +from django.contrib.auth.tokens import PasswordResetTokenGenerator +from django.contrib.sites.shortcuts import get_current_site +~~from django.core import exceptions, validators +from django.urls import reverse +from django.utils.translation import gettext, gettext_lazy as _, pgettext + +from ..utils import ( + build_absolute_uri, + get_username_max_length, + set_form_field_order, +) +from . import app_settings +from .adapter import get_adapter +from .app_settings import AuthenticationMethod +from .models import EmailAddress +from .utils import ( + filter_users_by_email, + get_user_model, + perform_login, + setup_user_email, + sync_user_email_addresses, + url_str_to_user_pk, + user_email, + user_pk_to_url_str, + user_username, +) + + + +## ... source file abbreviated to get to exceptions examples ... + + + credentials["email"] = login + elif ( + app_settings.AUTHENTICATION_METHOD == + AuthenticationMethod.USERNAME): + credentials["username"] = login + else: + if self._is_login_email(login): + credentials["email"] = login + credentials["username"] = login + credentials["password"] = self.cleaned_data["password"] + return credentials + + def clean_login(self): + login = self.cleaned_data['login'] + return login.strip() + + def _is_login_email(self, login): + try: + validators.validate_email(login) + ret = True +~~ except exceptions.ValidationError: + ret = False + return ret + + def clean(self): + super(LoginForm, self).clean() + if self._errors: + return + credentials = self.user_credentials() + user = get_adapter(self.request).authenticate( + self.request, + **credentials) + if user: + self.user = user + else: + auth_method = app_settings.AUTHENTICATION_METHOD + if auth_method == app_settings.AuthenticationMethod.USERNAME_EMAIL: + login = self.cleaned_data['login'] + if self._is_login_email(login): + auth_method = app_settings.AuthenticationMethod.EMAIL + else: + auth_method = app_settings.AuthenticationMethod.USERNAME + raise forms.ValidationError( + self.error_messages['%s_password_mismatch' % auth_method]) + return self.cleaned_data + + +## ... source file abbreviated to get to exceptions examples ... + + + remember = self.cleaned_data['remember'] + if remember: + request.session.set_expiry(app_settings.SESSION_COOKIE_AGE) + else: + request.session.set_expiry(0) + return ret + + +class _DummyCustomSignupForm(forms.Form): + + def signup(self, request, user): + pass + + +def _base_signup_form_class(): + if not app_settings.SIGNUP_FORM_CLASS: + return _DummyCustomSignupForm + try: + fc_module, fc_classname = app_settings.SIGNUP_FORM_CLASS.rsplit('.', 1) + except ValueError: +~~ raise exceptions.ImproperlyConfigured('%s does not point to a form' + ' class' + % app_settings.SIGNUP_FORM_CLASS) + try: + mod = import_module(fc_module) + except ImportError as e: +~~ raise exceptions.ImproperlyConfigured('Error importing form class %s:' + ' "%s"' % (fc_module, e)) + try: + fc_class = getattr(mod, fc_classname) + except AttributeError: +~~ raise exceptions.ImproperlyConfigured('Module "%s" does not define a' + ' "%s" class' % (fc_module, + fc_classname)) + if not hasattr(fc_class, 'signup'): + if hasattr(fc_class, 'save'): + warnings.warn("The custom signup form must offer" + " a `def signup(self, request, user)` method", + DeprecationWarning) + else: +~~ raise exceptions.ImproperlyConfigured( + 'The custom signup form must implement a "signup" method') + return fc_class + + +class BaseSignupForm(_base_signup_form_class()): + username = forms.CharField(label=_("Username"), + min_length=app_settings.USERNAME_MIN_LENGTH, + widget=forms.TextInput( + attrs={'placeholder': + _('Username'), + 'autofocus': 'autofocus'})) + email = forms.EmailField(widget=forms.TextInput( + attrs={'type': 'email', + 'placeholder': _('E-mail address')})) + + def __init__(self, *args, **kwargs): + email_required = kwargs.pop('email_required', + app_settings.EMAIL_REQUIRED) + self.username_required = kwargs.pop('username_required', + app_settings.USERNAME_REQUIRED) + super(BaseSignupForm, self).__init__(*args, **kwargs) + username_field = self.fields['username'] + username_field.max_length = get_username_max_length() + username_field.validators.append( + + +## ... source file continues with no further exceptions examples... + +``` + diff --git a/content/pages/examples/django/django-core-mail.markdown b/content/pages/examples/django/django-core-mail.markdown new file mode 100644 index 000000000..bb83122b4 --- /dev/null +++ b/content/pages/examples/django/django-core-mail.markdown @@ -0,0 +1,348 @@ +title: django.core mail code examples +category: page +slug: django-core-mail-examples +sortorder: 500011081 +toc: False +sidebartitle: django.core mail +meta: Python example code for the mail function from the django.core module of the Django project. + + +mail is a function within the django.core module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / tests.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/tests.py) + +```python +# tests.py +from __future__ import absolute_import + +import json +import uuid +from datetime import timedelta + +from django import forms +from django.conf import settings +from django.contrib.auth.models import AbstractUser, AnonymousUser +from django.contrib.sites.models import Site +~~from django.core import mail, validators +from django.core.exceptions import ValidationError +from django.db import models +from django.http import HttpResponseRedirect +from django.template import Context, Template +from django.test.client import Client, RequestFactory +from django.test.utils import override_settings +from django.urls import reverse +from django.utils.timezone import now + +from allauth.account.forms import BaseSignupForm, ResetPasswordForm, SignupForm +from allauth.account.models import ( + EmailAddress, + EmailConfirmation, + EmailConfirmationHMAC, +) +from allauth.tests import Mock, TestCase, patch +from allauth.utils import get_user_model, get_username_max_length + +from . import app_settings +from .adapter import get_adapter +from .auth_backends import AuthenticationBackend +from .signals import user_logged_in, user_logged_out +from .utils import ( + filter_users_by_username, + + +## ... source file abbreviated to get to mail examples ... + + + + def _password_set_or_change_redirect(self, urlname, usable_password): + self._create_user_and_login(usable_password) + return self.client.get(reverse(urlname)) + + def test_ajax_password_change(self): + self._create_user_and_login() + resp = self.client.post( + reverse('account_change_password'), + data={'oldpassword': 'doe', + 'password1': 'AbCdEf!123', + 'password2': 'AbCdEf!123456'}, + HTTP_X_REQUESTED_WITH='XMLHttpRequest') + self.assertEqual(resp['content-type'], 'application/json') + data = json.loads(resp.content.decode('utf8')) + assert ('same password' in + data['form']['fields']['password2']['errors'][0]) + + def test_password_forgotten_username_hint(self): + user = self._request_new_password() +~~ body = mail.outbox[0].body + assert user.username in body + + @override_settings( + ACCOUNT_AUTHENTICATION_METHOD=app_settings.AuthenticationMethod.EMAIL) + def test_password_forgotten_no_username_hint(self): + user = self._request_new_password() +~~ body = mail.outbox[0].body + assert user.username not in body + + def _request_new_password(self): + user = get_user_model().objects.create( + username='john', email="john@example.org", is_active=True) + user.set_password('doe') + user.save() + self.client.post( + reverse('account_reset_password'), + data={'email': 'john@example.org'}) + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].to, ["john@example.org"]) + return user + + def test_password_reset_flow_with_empty_session(self): + self._request_new_password() +~~ body = mail.outbox[0].body + self.assertGreater(body.find('https://'), 0) + + url = body[body.find('/password/reset/'):].split()[0] + resp = self.client.get(url) + + reset_pass_url = resp.url + + resp = self.client_class().get(reset_pass_url) + + self.assertTemplateUsed( + resp, + 'account/password_reset_from_key.%s' % + app_settings.TEMPLATE_EXTENSION) + + self.assertTrue(resp.context_data['token_fail']) + + def test_password_reset_flow(self): + user = self._request_new_password() +~~ body = mail.outbox[0].body + self.assertGreater(body.find('https://'), 0) + + url = body[body.find('/password/reset/'):].split()[0] + resp = self.client.get(url) + url = resp.url + resp = self.client.get(url) + self.assertTemplateUsed( + resp, + 'account/password_reset_from_key.%s' % + app_settings.TEMPLATE_EXTENSION) + self.assertFalse('token_fail' in resp.context_data) + + resp = self.client.post(url, + {'password1': 'newpass123', + 'password2': 'newpass123'}) + self.assertRedirects(resp, + reverse('account_reset_password_from_key_done')) + + user = get_user_model().objects.get(pk=user.pk) + self.assertTrue(user.check_password('newpass123')) + + resp = self.client.post(url, + {'password1': 'newpass123', + 'password2': 'newpass123'}) + + +## ... source file abbreviated to get to mail examples ... + + + app_settings.TEMPLATE_EXTENSION) + self.assertTrue(resp.context_data['token_fail']) + + response = self.client.get(url) + self.assertTemplateUsed( + response, + 'account/password_reset_from_key.%s' % + app_settings.TEMPLATE_EXTENSION) + self.assertTrue(response.context_data['token_fail']) + + response = self.client.post(url, + {'password1': 'newpass123', + 'password2': 'newpass123'}, + HTTP_X_REQUESTED_WITH='XMLHttpRequest') + self.assertEqual(response.status_code, 400) + data = json.loads(response.content.decode('utf8')) + assert 'invalid' in data['form']['errors'][0] + + def test_password_reset_flow_with_email_changed(self): + user = self._request_new_password() +~~ body = mail.outbox[0].body + self.assertGreater(body.find('https://'), 0) + EmailAddress.objects.create( + user=user, + email='other@email.org') + url = body[body.find('/password/reset/'):].split()[0] + resp = self.client.get(url) + self.assertTemplateUsed( + resp, + 'account/password_reset_from_key.%s' % + app_settings.TEMPLATE_EXTENSION) + self.assertTrue('token_fail' in resp.context_data) + + @override_settings(ACCOUNT_LOGIN_ON_PASSWORD_RESET=True) + def test_password_reset_ACCOUNT_LOGIN_ON_PASSWORD_RESET(self): + user = self._request_new_password() +~~ body = mail.outbox[0].body + url = body[body.find('/password/reset/'):].split()[0] + resp = self.client.get(url) + resp = self.client.post( + resp.url, + {'password1': 'newpass123', + 'password2': 'newpass123'}) + self.assertTrue(user.is_authenticated) + self.assertRedirects(resp, '/confirm-email/') + + @override_settings(ACCOUNT_EMAIL_CONFIRMATION_HMAC=False) + def test_email_verification_mandatory(self): + c = Client() + resp = c.post(reverse('account_signup'), + {'username': 'johndoe', + 'email': 'john@example.com', + 'password1': 'johndoe', + 'password2': 'johndoe'}, + follow=True) + self.assertEqual(resp.status_code, 200) + self.assertEqual(mail.outbox[0].to, ['john@example.com']) + self.assertGreater(mail.outbox[0].body.find('https://'), 0) + self.assertEqual(len(mail.outbox), 1) + self.assertTemplateUsed( + resp, + + +## ... source file continues with no further mail examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / tests / test_mail.py**](https://github.com/divio/django-cms/blob/develop/cms/tests/test_mail.py) + +```python +# test_mail.py +from django.contrib.auth import get_user_model +~~from django.core import mail + +from cms.api import create_page_user +from cms.test_utils.testcases import CMSTestCase +from cms.utils.mail import mail_page_user_change + + +class MailTestCase(CMSTestCase): + def setUp(self): +~~ mail.outbox = [] # reset outbox + + def test_mail_page_user_change(self): + user = get_user_model().objects.create_superuser("username", "username@django-cms.org", "username") + user = create_page_user(user, user, grant_all=True) + mail_page_user_change(user) + self.assertEqual(len(mail.outbox), 1) + + + +## ... source file continues with no further mail examples... + +``` + + +## Example 3 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / tests / test_tasks.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/tests/test_tasks.py) + +```python +# test_tasks.py +from django.test import TestCase +from explorer.app_settings import EXPLORER_DEFAULT_CONNECTION as CONN +from explorer.tasks import execute_query, snapshot_queries, truncate_querylogs, build_schema_cache_async +from explorer.tests.factories import SimpleQueryFactory +~~from django.core import mail +from mock import Mock, patch +from six import StringIO +from explorer.models import QueryLog +from datetime import datetime, timedelta + + +class TestTasks(TestCase): + + @patch('explorer.tasks.s3_upload') + def test_async_results(self, mocked_upload): + mocked_upload.return_value = 'http://s3.com/your-file.csv' + + q = SimpleQueryFactory(sql='select 1 "a", 2 "b", 3 "c";', title="testquery") + execute_query(q.id, 'cc@epantry.com') + + output = StringIO() + output.write('a,b,c\r\n1,2,3\r\n') + + self.assertEqual(len(mail.outbox), 2) +~~ self.assertIn('[SQL Explorer] Your query is running', mail.outbox[0].subject) +~~ self.assertIn('[SQL Explorer] Report ', mail.outbox[1].subject) + self.assertEqual(mocked_upload.call_args[0][1].getvalue(), output.getvalue()) + self.assertEqual(mocked_upload.call_count, 1) + + @patch('explorer.tasks.s3_upload') + def test_async_results_fails_with_message(self, mocked_upload): + mocked_upload.return_value = 'http://s3.com/your-file.csv' + + q = SimpleQueryFactory(sql='select x from foo;', title="testquery") + execute_query(q.id, 'cc@epantry.com') + + output = StringIO() + output.write('a,b,c\r\n1,2,3\r\n') + + self.assertEqual(len(mail.outbox), 2) +~~ self.assertIn('[SQL Explorer] Error ', mail.outbox[1].subject) + self.assertEqual(mocked_upload.call_count, 0) + + @patch('explorer.tasks.s3_upload') + def test_snapshots(self, mocked_upload): + mocked_upload.return_value = 'http://s3.com/your-file.csv' + + SimpleQueryFactory(snapshot=True) + SimpleQueryFactory(snapshot=True) + SimpleQueryFactory(snapshot=True) + SimpleQueryFactory(snapshot=False) + + snapshot_queries() + self.assertEqual(mocked_upload.call_count, 3) + + def test_truncating_querylogs(self): + QueryLog(sql='foo').save() + QueryLog.objects.filter(sql='foo').update(run_at=datetime.now() - timedelta(days=30)) + QueryLog(sql='bar').save() + QueryLog.objects.filter(sql='bar').update(run_at=datetime.now() - timedelta(days=29)) + truncate_querylogs(30) + self.assertEqual(QueryLog.objects.count(), 1) + + @patch('explorer.schema.build_schema_info') + def test_build_schema_cache_async(self, mocked_build): + + +## ... source file continues with no further mail examples... + +``` + diff --git a/content/pages/examples/django/django-core-management.markdown b/content/pages/examples/django/django-core-management.markdown new file mode 100644 index 000000000..2f6a72bf9 --- /dev/null +++ b/content/pages/examples/django/django-core-management.markdown @@ -0,0 +1,568 @@ +title: django.core management code examples +category: page +slug: django-core-management-examples +sortorder: 500011082 +toc: False +sidebartitle: django.core management +meta: Python example code for the management function from the django.core module of the Django project. + + +management is a function within the django.core module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / tests / test_management.py**](https://github.com/divio/django-cms/blob/develop/cms/tests/test_management.py) + +```python +# test_management.py +from __future__ import unicode_literals +import uuid +from cms.test_utils.project.sampleapp.cms_apps import SampleApp +from cms.test_utils.util.context_managers import apphooks + +from six.moves import StringIO + +from django.conf import settings +from django.contrib.sites.models import Site +~~from django.core import management +from django.core.management import CommandError +from django.test.utils import override_settings + +from cms.api import create_page, add_plugin, create_title +from cms.management.commands.subcommands.list import plugin_report +from cms.models import Page, StaticPlaceholder +from cms.models.placeholdermodel import Placeholder +from cms.models.pluginmodel import CMSPlugin +from cms.test_utils.fixtures.navextenders import NavextendersFixture +from cms.test_utils.testcases import CMSTestCase +from djangocms_text_ckeditor.cms_plugins import TextPlugin + + +APPHOOK = "SampleApp" +PLUGIN = "TextPlugin" + +TEST_INSTALLED_APPS = [ + "django.contrib.auth", + "cms", + "menus", + "sekizai", + "treebeard", +] + settings.PLUGIN_APPS +if settings.AUTH_USER_MODEL == "emailuserapp.EmailUser": + TEST_INSTALLED_APPS.append("cms.test_utils.project.emailuserapp") +if settings.AUTH_USER_MODEL == "customuserapp.User": + TEST_INSTALLED_APPS.append("cms.test_utils.project.customuserapp") + + +class ManagementTestCase(CMSTestCase): + @override_settings(INSTALLED_APPS=TEST_INSTALLED_APPS) + def test_list_apphooks(self): + with apphooks(SampleApp): + out = StringIO() + create_page('Hello Title', "nav_playground.html", "en", apphook=APPHOOK) + self.assertEqual(Page.objects.filter(application_urls=APPHOOK).count(), 1) +~~ management.call_command( + "cms", + "list", + "apphooks", + interactive=False, + stdout=out, + ) + self.assertEqual(out.getvalue(), "SampleApp (draft)\n") + + def test_uninstall_apphooks_without_apphook(self): + with apphooks(): + out = StringIO() +~~ management.call_command( + "cms", + "uninstall", + "apphooks", + APPHOOK, + interactive=False, + stdout=out, + ) + self.assertEqual(out.getvalue(), "no 'SampleApp' apphooks found\n") + + def test_fix_tree(self): + create_page("home", "nav_playground.html", "en") + page1 = create_page("page", "nav_playground.html", "en") + page1.node.depth = 3 + page1.node.numchild = 4 + page1.node.path = "00100010" + page1.node.save() + out = StringIO() +~~ management.call_command('cms', 'fix-tree', interactive=False, stdout=out) + self.assertEqual(out.getvalue(), 'fixing page tree\nfixing plugin tree\nall done\n') + page1 = page1.reload() + self.assertEqual(page1.node.path, "0002") + self.assertEqual(page1.node.depth, 1) + self.assertEqual(page1.node.numchild, 0) + + def test_fix_tree_regression_5641(self): + alpha = create_page("Alpha", "nav_playground.html", "en", published=True) + beta = create_page("Beta", "nav_playground.html", "en", published=False) + gamma = create_page("Gamma", "nav_playground.html", "en", published=False) + delta = create_page("Delta", "nav_playground.html", "en", published=True) + theta = create_page("Theta", "nav_playground.html", "en", published=True) + + beta.move_page(alpha.node, position='last-child') + gamma.move_page(beta.node, position='last-child') + delta.move_page(gamma.node, position='last-child') + theta.move_page(delta.node, position='last-child') + + out = StringIO() +~~ management.call_command('cms', 'fix-tree', interactive=False, stdout=out) + + tree = [ + (alpha, '0001'), + (beta, '00010001'), + (gamma, '000100010001'), + (delta, '0001000100010001'), + (theta, '00010001000100010001'), + ] + + for page, path in tree: + self.assertEqual(page.node.path, path) + + @override_settings(INSTALLED_APPS=TEST_INSTALLED_APPS) + def test_uninstall_apphooks_with_apphook(self): + with apphooks(SampleApp): + out = StringIO() + create_page('Hello Title', "nav_playground.html", "en", apphook=APPHOOK) + self.assertEqual(Page.objects.filter(application_urls=APPHOOK).count(), 1) +~~ management.call_command( + "cms", + "uninstall", + "apphooks", + APPHOOK, + interactive=False, + stdout=out, + ) + self.assertEqual(out.getvalue(), "1 'SampleApp' apphooks uninstalled\n") + self.assertEqual(Page.objects.filter(application_urls=APPHOOK).count(), 0) + + @override_settings(INSTALLED_APPS=TEST_INSTALLED_APPS) + def test_list_plugins(self): + out = StringIO() + placeholder = Placeholder.objects.create(slot="test") + add_plugin(placeholder, TextPlugin, "en", body="en body") + add_plugin(placeholder, TextPlugin, "en", body="en body") + link_plugin = add_plugin(placeholder, "LinkPlugin", "en", + name="A Link", external_link="https://www.django-cms.org") + self.assertEqual( + CMSPlugin.objects.filter(plugin_type=PLUGIN).count(), + 2) + self.assertEqual( + CMSPlugin.objects.filter(plugin_type="LinkPlugin").count(), + 1) + + instanceless_plugin = CMSPlugin(language="en", plugin_type="TextPlugin") + instanceless_plugin.save() + + bogus_plugin = CMSPlugin(language="en", plugin_type="BogusPlugin") + bogus_plugin.save() + +~~ management.call_command('cms', 'list', 'plugins', interactive=False, stdout=out) + report = plugin_report() + + self.assertEqual( + len(report), + 3) + + bogus_plugins_report = report[0] + self.assertEqual( + bogus_plugins_report["model"], + None) + + self.assertEqual( + bogus_plugins_report["type"], + u'BogusPlugin') + + self.assertEqual( + bogus_plugins_report["instances"][0], + bogus_plugin) + + link_plugins_report = report[1] + self.assertEqual( + link_plugins_report["model"], + link_plugin.__class__) + + + +## ... source file abbreviated to get to management examples ... + + + bogus_plugins_report = report[0] + self.assertEqual( + len(bogus_plugins_report["instances"]), + 1) + + link_plugins_report = report[1] + self.assertEqual( + len(link_plugins_report["instances"]), + 1) + + text_plugins_report = report[2] + self.assertEqual( + len(text_plugins_report["instances"]), + 3) + + self.assertEqual( + len(text_plugins_report["unsaved_instances"]), + 1) + + out = StringIO() +~~ management.call_command('cms', 'delete-orphaned-plugins', interactive=False, stdout=out) + report = plugin_report() + + self.assertEqual( + len(report), + 2) + + link_plugins_report = report[0] + self.assertEqual( + len(link_plugins_report["instances"]), + 1) + + text_plugins_report = report[1] + self.assertEqual( + len(text_plugins_report["instances"]), + 2) + + self.assertEqual( + len(text_plugins_report["unsaved_instances"]), + 0) + + def test_uninstall_plugins_without_plugin(self): + out = StringIO() +~~ management.call_command('cms', 'uninstall', 'plugins', PLUGIN, interactive=False, stdout=out) + self.assertEqual(out.getvalue(), "no 'TextPlugin' plugins found\n") + + @override_settings(INSTALLED_APPS=TEST_INSTALLED_APPS) + def test_uninstall_plugins_with_plugin(self): + out = StringIO() + placeholder = Placeholder.objects.create(slot="test") + add_plugin(placeholder, TextPlugin, "en", body="en body") + self.assertEqual(CMSPlugin.objects.filter(plugin_type=PLUGIN).count(), 1) +~~ management.call_command('cms', 'uninstall', 'plugins', PLUGIN, interactive=False, stdout=out) + self.assertEqual(out.getvalue(), "1 'TextPlugin' plugins uninstalled\n") + self.assertEqual(CMSPlugin.objects.filter(plugin_type=PLUGIN).count(), 0) + + def test_publisher_public(self): + admin = self.get_superuser() + create_page( + 'home', + published=True, + language='de', + template='nav_playground.html', + created_by=admin, + ) + page_1 = create_page( + 'página 1', + published=True, + language='de', + template='nav_playground.html', + created_by=admin, + ) + page_1.unpublish('de') + + page_2 = create_page( + 'página 2', + published=True, + language='de', + template='nav_playground.html', + created_by=admin, + ) + page_2.unpublish('de') + +~~ management.call_command( + 'cms', + 'publisher-publish', + '-l de', + '--unpublished', + interactive=False, + ) + + self.assertEqual(Page.objects.public().count(), 3) + + +class PageFixtureManagementTestCase(NavextendersFixture, CMSTestCase): + + def _fill_page_body(self, page, lang): + ph_en = page.placeholders.get(slot="body") + mcol1 = add_plugin(ph_en, "MultiColumnPlugin", lang, position="first-child") + add_plugin(ph_en, "ColumnPlugin", lang, position="first-child", target=mcol1) + col2 = add_plugin(ph_en, "ColumnPlugin", lang, position="first-child", target=mcol1) + mcol2 = add_plugin(ph_en, "MultiColumnPlugin", lang, position="first-child", target=col2) + add_plugin(ph_en, "ColumnPlugin", lang, position="first-child", target=mcol2) + col4 = add_plugin(ph_en, "ColumnPlugin", lang, position="first-child", target=mcol2) + add_plugin(ph_en, "LinkPlugin", lang, target=col4, + name="A Link", external_link="https://www.django-cms.org") + static_placeholder = StaticPlaceholder(code=str(uuid.uuid4()), site_id=1) + static_placeholder.save() + add_plugin(static_placeholder.draft, "TextPlugin", lang, body="example content") + + def setUp(self): + pages = Page.objects.drafts() + for page in pages: + self._fill_page_body(page, "en") + + def test_copy_langs(self): + site = 1 + number_start_plugins = CMSPlugin.objects.all().count() + + out = StringIO() +~~ management.call_command( + 'cms', 'copy', 'lang', '--from-lang=en', '--to-lang=de', interactive=False, stdout=out + ) + pages = Page.objects.on_site(site).drafts() + for page in pages: + self.assertEqual(set((u'en', u'de')), set(page.get_languages())) + self.assertEqual(CMSPlugin.objects.all().count(), number_start_plugins*2) + self.assertEqual(CMSPlugin.objects.filter(language='en').count(), number_start_plugins) + self.assertEqual(CMSPlugin.objects.filter(language='de').count(), number_start_plugins) + + root_page = Page.objects.get_home(site) + root_plugins = CMSPlugin.objects.filter(placeholder=root_page.placeholders.get(slot="body")) + + first_plugin_en, _ = root_plugins.get(language='en', parent=None).get_plugin_instance() + first_plugin_de, _ = root_plugins.get(language='de', parent=None).get_plugin_instance() + + self.assertEqual(first_plugin_en.plugin_type, first_plugin_de.plugin_type) + + link_en, _ = root_plugins.get(language='en', plugin_type='LinkPlugin').get_plugin_instance() + link_de, _ = root_plugins.get(language='de', plugin_type='LinkPlugin').get_plugin_instance() + + self.assertEqual(link_en.external_link, link_de.external_link) + self.assertEqual(link_en.get_position_in_placeholder(), link_de.get_position_in_placeholder()) + + stack_plugins = CMSPlugin.objects.filter(placeholder=StaticPlaceholder.objects.order_by('?')[0].draft) + + stack_text_en, _ = stack_plugins.get(language='en', plugin_type='TextPlugin').get_plugin_instance() + stack_text_de, _ = stack_plugins.get(language='de', plugin_type='TextPlugin').get_plugin_instance() + + self.assertEqual(stack_text_en.plugin_type, stack_text_de.plugin_type) + self.assertEqual(stack_text_en.body, stack_text_de.body) + + def test_copy_langs_no_content(self): + site = 1 + number_start_plugins = CMSPlugin.objects.all().count() + + out = StringIO() +~~ management.call_command( + 'cms', 'copy', 'lang', '--from-lang=en', '--to-lang=de', '--skip-content', + interactive=False, stdout=out + ) + pages = Page.objects.on_site(site).drafts() + for page in pages: + self.assertEqual(set((u'en', u'de')), set(page.get_languages())) + self.assertEqual(CMSPlugin.objects.all().count(), number_start_plugins) + self.assertEqual(CMSPlugin.objects.filter(language='en').count(), number_start_plugins) + self.assertEqual(CMSPlugin.objects.filter(language='de').count(), 0) + + root_page = Page.objects.get_home(site) + root_plugins = CMSPlugin.objects.filter( + placeholder=root_page.placeholders.get(slot="body")) + + first_plugin_en, _ = root_plugins.get(language='en', parent=None).get_plugin_instance() + first_plugin_de = None + with self.assertRaises(CMSPlugin.DoesNotExist): + first_plugin_de, _ = root_plugins.get(language='de', parent=None).get_plugin_instance() + + self.assertIsNone(first_plugin_de) + + stack_plugins = CMSPlugin.objects.filter( + placeholder=StaticPlaceholder.objects.order_by('?')[0].draft) + + stack_text_en, _ = stack_plugins.get(language='en', + plugin_type='TextPlugin').get_plugin_instance() + with self.assertRaises(CMSPlugin.DoesNotExist): + stack_text_de, _ = stack_plugins.get(language='de', + plugin_type='TextPlugin').get_plugin_instance() + + def test_copy_sites(self): + site_1_pk = 1 + site_1 = Site.objects.get(pk=site_1_pk) + site_2 = Site.objects.create(name='site 2') + site_2_pk = site_2.pk + phs = [] + for page in Page.objects.on_site(site_1_pk).drafts(): + phs.extend(page.placeholders.values_list('pk', flat=True)) + number_start_plugins = CMSPlugin.objects.filter(placeholder__in=phs).count() + + out = StringIO() +~~ management.call_command( + 'cms', 'copy', 'site', '--from-site=%s' % site_1_pk, '--to-site=%s' % site_2_pk, + stdout=out + ) + for page in Page.objects.on_site(site_1_pk).drafts(): + page.publish('en') + for page in Page.objects.on_site(site_2_pk).drafts(): + page.publish('en') + + pages_1 = list(Page.objects.drafts().on_site(site_1).select_related('node').order_by('node__path')) + pages_2 = list(Page.objects.drafts().on_site(site_2).select_related('node').order_by('node__path')) + for index, page in enumerate(pages_1): + self.assertEqual(page.get_title('en'), pages_2[index].get_title('en')) + self.assertEqual(page.node.depth, pages_2[index].node.depth) + + phs_1 = [] + phs_2 = [] + for page in Page.objects.on_site(site_1_pk).drafts(): + phs_1.extend(page.placeholders.values_list('pk', flat=True)) + for page in Page.objects.on_site(site_2_pk).drafts(): + phs_2.extend(page.placeholders.values_list('pk', flat=True)) + + self.assertEqual(CMSPlugin.objects.filter(placeholder__in=phs_1).count(), number_start_plugins) + self.assertEqual(CMSPlugin.objects.filter(placeholder__in=phs_2).count(), number_start_plugins) + + + +## ... source file abbreviated to get to management examples ... + + + + first_plugin_1, _ = root_plugins_1.get(language='en', parent=None).get_plugin_instance() + first_plugin_2, _ = root_plugins_2.get(language='en', parent=None).get_plugin_instance() + + self.assertEqual(first_plugin_1.plugin_type, first_plugin_2.plugin_type) + + link_1, _ = root_plugins_1.get(language='en', plugin_type='LinkPlugin').get_plugin_instance() + link_2, _ = root_plugins_2.get(language='en', plugin_type='LinkPlugin').get_plugin_instance() + + self.assertEqual(link_1.external_link, link_2.external_link) + self.assertEqual(link_1.get_position_in_placeholder(), link_2.get_position_in_placeholder()) + + def test_copy_existing_title(self): + site = 1 + number_start_plugins = CMSPlugin.objects.all().count() + + root_page = Page.objects.get_home(site) + create_title("de", "root page de", root_page) + + out = StringIO() +~~ management.call_command( + 'cms', 'copy', 'lang', '--from-lang=en', '--to-lang=de', interactive=False, stdout=out + ) + pages = Page.objects.on_site(site).drafts() + for page in pages: + self.assertEqual(set((u'en', u'de')), set(page.get_languages())) + + self.assertEqual("root page de", Page.objects.get_home(site).get_title("de")) + + self.assertEqual(CMSPlugin.objects.all().count(), number_start_plugins*2) + self.assertEqual(CMSPlugin.objects.filter(language='en').count(), number_start_plugins) + self.assertEqual(CMSPlugin.objects.filter(language='de').count(), number_start_plugins) + + def test_copy_filled_placeholder(self): + site = 1 + number_start_plugins = CMSPlugin.objects.all().count() + + root_page = Page.objects.get_home(site) + create_title("de", "root page de", root_page) + ph = root_page.placeholders.get(slot="body") + add_plugin(ph, "TextPlugin", "de", body="Hello World") + + out = StringIO() +~~ management.call_command( + 'cms', 'copy', 'lang', '--from-lang=en', '--to-lang=de', interactive=False, stdout=out + ) + + self.assertEqual(CMSPlugin.objects.filter(language='en').count(), number_start_plugins) + self.assertEqual(CMSPlugin.objects.filter(language='de').count(), number_start_plugins-6) + + def test_copy_filled_placeholder_force_copy(self): + site = 1 + number_start_plugins = CMSPlugin.objects.all().count() + + root_page = Page.objects.get_home(site) + create_title("de", "root page de", root_page) + ph = root_page.placeholders.get(slot="body") + add_plugin(ph, "TextPlugin", "de", body="Hello World") + + root_plugins = CMSPlugin.objects.filter(placeholder=ph) + text_de_orig, _ = root_plugins.get(language='de', plugin_type='TextPlugin').get_plugin_instance() + + out = StringIO() +~~ management.call_command( + 'cms', 'copy', 'lang', '--from-lang=en', '--to-lang=de', '--force', interactive=False, + stdout=out + ) + + CMSPlugin.objects.filter(placeholder=root_page.placeholders.get(slot="body")) + + self.assertEqual(CMSPlugin.objects.filter(language='en').count(), number_start_plugins) + self.assertEqual(CMSPlugin.objects.filter(language='de').count(), number_start_plugins+1) + + def test_copy_from_non_existing_lang(self): + site = 1 + out = StringIO() +~~ management.call_command( + 'cms', 'copy', 'lang', '--from-lang=de', '--to-lang=fr', verbosity=3, + interactive=False, stdout=out + ) + text = out.getvalue() + page_count = Page.objects.on_site(site).drafts().count() + 1 + for idx in range(1, page_count): + self.assertTrue("Skipping page page%d, language de not defined" % idx in text) + + def test_copy_site_safe(self): + site_other = 1 + site_active = 2 + origina_site1_langs = {} + + number_start_plugins = CMSPlugin.objects.all().count() + site_obj = Site.objects.create(domain="sample2.com", name="sample2.com", pk=site_active) + + for page in Page.objects.on_site(1).drafts(): + origina_site1_langs[page.pk] = set(page.get_languages()) + + p1 = create_page('page1', published=True, in_navigation=True, language='de', template='nav_playground.html', site=site_obj) + create_page('page4', published=True, in_navigation=True, language='de', template='nav_playground.html', site=site_obj) + create_page('page2', published=True, in_navigation=True, parent=p1, language='de', template='nav_playground.html', site=site_obj) + + for page in Page.objects.on_site(site_active).drafts(): + self._fill_page_body(page, 'de') + + number_site2_plugins = CMSPlugin.objects.all().count() - number_start_plugins + + out = StringIO() +~~ management.call_command( + 'cms', 'copy', 'lang', '--from-lang=de', '--to-lang=fr', '--site=%s' % site_active, + interactive=False, stdout=out + ) + + for page in Page.objects.on_site(site_other).drafts(): + self.assertEqual(origina_site1_langs[page.pk], set(page.get_languages())) + + for page in Page.objects.on_site(site_active).drafts(): + self.assertEqual(set(('de', 'fr')), set(page.get_languages())) + + self.assertEqual(CMSPlugin.objects.filter(language='en').count(), number_start_plugins) + self.assertEqual(CMSPlugin.objects.filter(language='de').count(), number_site2_plugins) + self.assertEqual(CMSPlugin.objects.filter(language='fr').count(), number_site2_plugins) + self.assertEqual(CMSPlugin.objects.all().count(), number_start_plugins + number_site2_plugins*2) + + def test_copy_bad_languages(self): + out = StringIO() + with self.assertRaises(CommandError) as command_error: +~~ management.call_command( + 'cms', 'copy', 'lang', '--from-lang=it', '--to-lang=fr', interactive=False, + stdout=out + ) + + self.assertEqual(str(command_error.exception), 'Both languages have to be present in settings.LANGUAGES and settings.CMS_LANGUAGES') + + + +## ... source file continues with no further management examples... + +``` + diff --git a/content/pages/examples/django/django-core-serializers.markdown b/content/pages/examples/django/django-core-serializers.markdown new file mode 100644 index 000000000..e6d03713a --- /dev/null +++ b/content/pages/examples/django/django-core-serializers.markdown @@ -0,0 +1,111 @@ +title: django.core serializers code examples +category: page +slug: django-core-serializers-examples +sortorder: 500011083 +toc: False +sidebartitle: django.core serializers +meta: Python example code for the serializers function from the django.core module of the Django project. + + +serializers is a function within the django.core module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / views / crud.py**](https://github.com/jrief/django-angular/blob/master/djng/views/crud.py) + +```python +# crud.py +import json + +from django.core.exceptions import ValidationError +~~from django.core import serializers +from django.forms.models import modelform_factory +from django.views.generic import FormView + +from djng.views.mixins import JSONBaseMixin, JSONResponseException + + +class NgMissingParameterError(ValueError): + pass + + +class NgCRUDView(JSONBaseMixin, FormView): + model = None + fields = None + form_class = None + slug_field = 'slug' + serializer_name = 'python' + serialize_natural_keys = False + + allowed_methods = ['GET', 'POST', 'DELETE'] + exclude_methods = [] + + def get_allowed_methods(self): + return [method for method in self.allowed_methods if method not in self.exclude_methods] + + + +## ... source file abbreviated to get to serializers examples ... + + + def get_form_class(self): + return self.form_class or modelform_factory(self.model, exclude=[]) + + def build_json_response(self, data, **kwargs): + return self.json_response(self.serialize_queryset(data), separators=(',', ':'), **kwargs) + + def error_json_response(self, message, status_code=400, detail=None): + response_data = { + "message": message, + "detail": detail, + } + return self.json_response(response_data, status=status_code, separators=(',', ':')) + + def serialize_queryset(self, queryset): + object_data = [] + is_queryset = False + query_fields = self.get_fields() + try: + iter(queryset) + is_queryset = True +~~ raw_data = serializers.serialize(self.serializer_name, queryset, fields=query_fields, + use_natural_keys=self.serialize_natural_keys) + except TypeError: # Not iterable +~~ raw_data = serializers.serialize(self.serializer_name, [queryset, ], fields=query_fields, + use_natural_keys=self.serialize_natural_keys) + + for obj in raw_data: # Add pk to fields + obj['fields']['pk'] = obj['pk'] + object_data.append(obj['fields']) + + if is_queryset: + return object_data + return object_data[0] # If there's only one object + + def get_form_kwargs(self): + kwargs = super(NgCRUDView, self).get_form_kwargs() + kwargs['data'] = json.loads(self.request.body.decode('utf-8')) + + if 'pk' in self.request.GET or self.slug_field in self.request.GET: + kwargs['instance'] = self.get_object() + return kwargs + + def get_object(self): + if 'pk' in self.request.GET: + return self.model.objects.get(pk=self.request.GET['pk']) + elif self.slug_field in self.request.GET: + return self.model.objects.get(**{self.slug_field: self.request.GET[self.slug_field]}) + raise NgMissingParameterError( + + +## ... source file continues with no further serializers examples... + +``` + diff --git a/content/pages/examples/django/django-core-signals.markdown b/content/pages/examples/django/django-core-signals.markdown new file mode 100644 index 000000000..409f32a45 --- /dev/null +++ b/content/pages/examples/django/django-core-signals.markdown @@ -0,0 +1,164 @@ +title: django.core signals code examples +category: page +slug: django-core-signals-examples +sortorder: 500011084 +toc: False +sidebartitle: django.core signals +meta: Python example code for the signals function from the django.core module of the Django project. + + +signals is a function within the django.core module of the Django project. + + +## Example 1 from django-webtest +[django-webtest](https://github.com/django-webtest/django-webtest) +([PyPI package information](https://pypi.org/project/django-webtest/)) +is a [Django](/django.html) extension that makes it easier to use +[WebTest](http://docs.pylonsproject.org/projects/webtest/) with +your projects. + +The project is open sourced under the +[MIT license](https://github.com/django-webtest/django-webtest/blob/master/LICENSE.txt). + +[**django-webtest / django_webtest / __init__.py**](https://github.com/django-webtest/django-webtest/blob/master/django_webtest/./__init__.py) + +```python +# __init__.py +import copy + +from django.conf import settings +from django.test.signals import template_rendered +from django.core.handlers.wsgi import WSGIHandler +from django.test import TestCase, TransactionTestCase +from django.test.client import store_rendered_templates + +from functools import partial + +try: + from importlib import import_module +except ImportError: + from django.utils.importlib import import_module + +~~from django.core import signals +try: + from django.db import close_old_connections +except ImportError: + from django.db import close_connection + close_old_connections = None +try: + from django.core.servers.basehttp import ( + AdminMediaHandler as StaticFilesHandler) +except ImportError: + from django.contrib.staticfiles.handlers import StaticFilesHandler + +from webtest import TestApp +try: + from webtest.utils import NoDefault +except ImportError: + NoDefault = '' + +from django_webtest.response import DjangoWebtestResponse +from django_webtest.compat import to_string, to_wsgi_safe_string + + +_notgiven = object() + + + + +## ... source file abbreviated to get to signals examples ... + + + def set_user(self, user): + if user is None and 'WEBTEST_USER' in self.extra_environ: + del self.extra_environ['WEBTEST_USER'] + if user is not None: + self.extra_environ = self._update_environ(self.extra_environ, user) + + def _update_environ(self, environ, user=_notgiven): + environ = environ or {} + + if user is not _notgiven: + if user is None: + environ['WEBTEST_USER'] = '' + else: + username = _get_username(user) + environ['WEBTEST_USER'] = to_wsgi_safe_string(username) + + return environ + + def do_request(self, req, status, expect_errors): + if close_old_connections is not None: # Django 1.6+ +~~ signals.request_started.disconnect(close_old_connections) +~~ signals.request_finished.disconnect(close_old_connections) + else: # Django < 1.6 +~~ signals.request_finished.disconnect(close_connection) + + try: + req.environ.setdefault('REMOTE_ADDR', '127.0.0.1') + + req.environ['REMOTE_ADDR'] = to_string(req.environ['REMOTE_ADDR']) + req.environ['PATH_INFO'] = to_string(req.environ['PATH_INFO']) + + data = {} + on_template_render = partial(store_rendered_templates, data) + template_rendered.connect(on_template_render) + + response = super(DjangoTestApp, self).do_request(req, status, + expect_errors) + + def flattend(detail): + if len(data[detail]) == 1: + return data[detail][0] + return data[detail] + + response.context = None + response.template = None + response.templates = data.get('templates', None) + + if data.get('context'): + response.context = flattend('context') + + if data.get('template'): + response.template = flattend('template') + elif data.get('templates'): + response.template = flattend('templates') + + response.__class__ = self.response_class + return response + finally: + if close_old_connections: # Django 1.6+ +~~ signals.request_started.connect(close_old_connections) +~~ signals.request_finished.connect(close_old_connections) + else: # Django < 1.6 +~~ signals.request_finished.connect(close_connection) + + def get(self, url, *args, **kwargs): + extra_environ = kwargs.get('extra_environ') + user = kwargs.pop('user', _notgiven) + auto_follow = kwargs.pop('auto_follow', False) + + kwargs['extra_environ'] = self._update_environ(extra_environ, user) + response = super(DjangoTestApp, self).get(url, *args, **kwargs) + + def is_redirect(r): + return r.status_int >= 300 and r.status_int < 400 + while auto_follow and is_redirect(response): + response = response.follow(**kwargs) + + return response + + def post(self, url, *args, **kwargs): + extra_environ = kwargs.get('extra_environ') + user = kwargs.pop('user', _notgiven) + kwargs['extra_environ'] = self._update_environ(extra_environ, user) + return super(DjangoTestApp, self).post(url, *args, **kwargs) + + def put(self, url, *args, **kwargs): + extra_environ = kwargs.get('extra_environ') + + +## ... source file continues with no further signals examples... + +``` + diff --git a/content/pages/examples/django/django-core-signing.markdown b/content/pages/examples/django/django-core-signing.markdown new file mode 100644 index 000000000..3d3050903 --- /dev/null +++ b/content/pages/examples/django/django-core-signing.markdown @@ -0,0 +1,310 @@ +title: django.core signing code examples +category: page +slug: django-core-signing-examples +sortorder: 500011085 +toc: False +sidebartitle: django.core signing +meta: Python example code for the signing function from the django.core module of the Django project. + + +signing is a function within the django.core module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / models.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/models.py) + +```python +# models.py +from __future__ import unicode_literals + +import datetime + +~~from django.core import signing +from django.db import models, transaction +from django.utils import timezone +from django.utils.crypto import get_random_string +from django.utils.translation import gettext_lazy as _ + +from .. import app_settings as allauth_app_settings +from . import app_settings, signals +from .adapter import get_adapter +from .managers import EmailAddressManager, EmailConfirmationManager +from .utils import user_email + + +class EmailAddress(models.Model): + + user = models.ForeignKey(allauth_app_settings.USER_MODEL, + verbose_name=_('user'), + on_delete=models.CASCADE) + email = models.EmailField(unique=app_settings.UNIQUE_EMAIL, + max_length=app_settings.EMAIL_MAX_LENGTH, + verbose_name=_('e-mail address')) + verified = models.BooleanField(verbose_name=_('verified'), default=False) + primary = models.BooleanField(verbose_name=_('primary'), default=False) + + objects = EmailAddressManager() + + +## ... source file abbreviated to get to signing examples ... + + + email_address=email_address) + return email_address + + def send(self, request=None, signup=False): + get_adapter(request).send_confirmation_mail(request, self, signup) + self.sent = timezone.now() + self.save() + signals.email_confirmation_sent.send(sender=self.__class__, + request=request, + confirmation=self, + signup=signup) + + +class EmailConfirmationHMAC: + + def __init__(self, email_address): + self.email_address = email_address + + @property + def key(self): +~~ return signing.dumps( + obj=self.email_address.pk, + salt=app_settings.SALT) + + @classmethod + def from_key(cls, key): + try: + max_age = ( + 60 * 60 * 24 * app_settings.EMAIL_CONFIRMATION_EXPIRE_DAYS) +~~ pk = signing.loads( + key, + max_age=max_age, + salt=app_settings.SALT) + ret = EmailConfirmationHMAC(EmailAddress.objects.get(pk=pk)) + except (signing.SignatureExpired, +~~ signing.BadSignature, + EmailAddress.DoesNotExist): + ret = None + return ret + + def confirm(self, request): + if not self.email_address.verified: + email_address = self.email_address + get_adapter(request).confirm_email(request, email_address) + signals.email_confirmed.send(sender=self.__class__, + request=request, + email_address=email_address) + return email_address + + def send(self, request=None, signup=False): + get_adapter(request).send_confirmation_mail(request, self, signup) + signals.email_confirmation_sent.send(sender=self.__class__, + request=request, + confirmation=self, + signup=signup) + + + +## ... source file continues with no further signing examples... + +``` + + +## Example 2 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / forms / fields.py**](https://github.com/jrief/django-angular/blob/master/djng/forms/fields.py) + +```python +# fields.py +import re +import mimetypes + +from django.conf import settings +from django.contrib.staticfiles.storage import staticfiles_storage +~~from django.core import signing +from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.core.files.storage import default_storage +from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile +from django.urls import reverse_lazy +from django.forms import fields, models as model_fields, widgets +from django.utils.html import format_html +from django.utils.module_loading import import_string +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext_lazy as _, ungettext_lazy + +from djng import app_settings +from .widgets import DropFileWidget, DropImageWidget + + +class DefaultFieldMixin(object): + render_label = True + + def has_subwidgets(self): + return False + + def get_potential_errors(self): + return self.get_input_required_errors() + + def get_input_required_errors(self): + + +## ... source file abbreviated to get to signing examples ... + + + pass + + +class TypedMultipleChoiceField(MultipleFieldMixin, fields.TypedMultipleChoiceField): + pass + + +class UUIDField(DefaultFieldMixin, fields.UUIDField): + def get_potential_errors(self): + errors = self.get_input_required_errors() + errors.extend(self.get_min_max_length_errors()) + return errors + + +class FileFieldMixin(DefaultFieldMixin): + def to_python(self, value): + try: + current_file = None + if ':' in value['current_file']: + current_file = self.signer.unsign(value['current_file']) +~~ except signing.BadSignature: + raise ValidationError("Got bogus upstream data") + except (KeyError, TypeError): + pass + + try: + obj = '' + if ':' in value['temp_name']: + temp_name = self.signer.unsign(value['temp_name']) + temp_file = self.storage.open(temp_name, 'rb') + file_size = self.storage.size(temp_name) + if file_size < settings.FILE_UPLOAD_MAX_MEMORY_SIZE: + obj = InMemoryUploadedFile( + file=temp_file, + field_name=None, + name=value['file_name'], + charset=value['charset'], + content_type=value['content_type'], + content_type_extra=value['content_type_extra'], + size=file_size, + ) + else: + obj = TemporaryUploadedFile( + value['file_name'], + value['content_type'], + 0, + value['charset'], + content_type_extra=value['content_type_extra'], + ) + while True: + chunk = temp_file.read(0x10000) + if not chunk: + break + obj.file.write(chunk) + obj.file.seek(0) + obj.file.size = file_size + self.storage.delete(temp_name) + self.remove_current(current_file) + elif value['temp_name'] == 'delete': + self.remove_current(current_file) +~~ except signing.BadSignature: + raise ValidationError("Got bogus upstream data") + except (IOError, KeyError, TypeError): + obj = current_file + except Exception as excp: + raise ValidationError("File upload failed. {}: {}".format(excp.__class__.__name__, excp)) + return obj + + def remove_current(self, filename): + if filename: + default_storage.delete(filename) + + +class FileField(FileFieldMixin, fields.FileField): + storage = app_settings.upload_storage +~~ signer = signing.Signer() + + def __init__(self, *args, **kwargs): + accept = kwargs.pop('accept', '*/*') + fileupload_url = kwargs.pop('fileupload_url', reverse_lazy('fileupload')) + area_label = kwargs.pop('area_label', _("Drop file here or click to upload")) + attrs = { + 'accept': accept, + 'ngf-pattern': accept, + } + kwargs.update(widget=DropFileWidget(area_label, fileupload_url, attrs=attrs)) + super(FileField, self).__init__(*args, **kwargs) + + @classmethod + def preview(cls, file_obj): + available_name = cls.storage.get_available_name(file_obj.name) + temp_name = cls.storage.save(available_name, file_obj) + extension = mimetypes.guess_extension(file_obj.content_type) + if extension: + extension = extension[1:] + else: + extension = '_blank' + icon_url = staticfiles_storage.url('djng/icons/{}.png'.format(extension)) + return { + 'url': 'url({})'.format(icon_url), + 'temp_name': cls.signer.sign(temp_name), + 'file_name': file_obj.name, + 'file_size': file_obj.size, + 'charset': file_obj.charset, + 'content_type': file_obj.content_type, + 'content_type_extra': file_obj.content_type_extra, + } + + +class ImageField(FileFieldMixin, fields.ImageField): + storage = app_settings.upload_storage +~~ signer = signing.Signer() + + def __init__(self, *args, **kwargs): + if 'easy_thumbnails' not in settings.INSTALLED_APPS: + raise ImproperlyConfigured("'djng.forms.fields.ImageField' requires 'easy-thubnails' to be installed") + accept = kwargs.pop('accept', 'image/*') + fileupload_url = kwargs.pop('fileupload_url', reverse_lazy('fileupload')) + area_label = kwargs.pop('area_label', _("Drop image here or click to upload")) + attrs = { + 'accept': accept, + 'ngf-pattern': accept, + } + kwargs.update(widget=DropImageWidget(area_label, fileupload_url, attrs=attrs)) + super(ImageField, self).__init__(*args, **kwargs) + + def remove_current(self, image_name): + from easy_thumbnails.models import Source, Thumbnail + + try: + source = Source.objects.get(name=image_name) + for thumb in Thumbnail.objects.filter(source=source): + default_storage.delete(thumb.name) + thumb.delete() + source.delete() + except Source.DoesNotExist: + + +## ... source file continues with no further signing examples... + +``` + diff --git a/content/pages/examples/django/django-core-validators.markdown b/content/pages/examples/django/django-core-validators.markdown new file mode 100644 index 000000000..3d795e521 --- /dev/null +++ b/content/pages/examples/django/django-core-validators.markdown @@ -0,0 +1,436 @@ +title: django.core validators code examples +category: page +slug: django-core-validators-examples +sortorder: 500011086 +toc: False +sidebartitle: django.core validators +meta: Python example code for the validators function from the django.core module of the Django project. + + +validators is a function within the django.core module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / forms.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/forms.py) + +```python +# forms.py +from __future__ import absolute_import + +import warnings +from importlib import import_module + +from django import forms +from django.contrib.auth.tokens import PasswordResetTokenGenerator +from django.contrib.sites.shortcuts import get_current_site +~~from django.core import exceptions, validators +from django.urls import reverse +from django.utils.translation import gettext, gettext_lazy as _, pgettext + +from ..utils import ( + build_absolute_uri, + get_username_max_length, + set_form_field_order, +) +from . import app_settings +from .adapter import get_adapter +from .app_settings import AuthenticationMethod +from .models import EmailAddress +from .utils import ( + filter_users_by_email, + get_user_model, + perform_login, + setup_user_email, + sync_user_email_addresses, + url_str_to_user_pk, + user_email, + user_pk_to_url_str, + user_username, +) + + + +## ... source file abbreviated to get to validators examples ... + + + login = self.cleaned_data["login"] + if app_settings.AUTHENTICATION_METHOD == AuthenticationMethod.EMAIL: + credentials["email"] = login + elif ( + app_settings.AUTHENTICATION_METHOD == + AuthenticationMethod.USERNAME): + credentials["username"] = login + else: + if self._is_login_email(login): + credentials["email"] = login + credentials["username"] = login + credentials["password"] = self.cleaned_data["password"] + return credentials + + def clean_login(self): + login = self.cleaned_data['login'] + return login.strip() + + def _is_login_email(self, login): + try: +~~ validators.validate_email(login) + ret = True + except exceptions.ValidationError: + ret = False + return ret + + def clean(self): + super(LoginForm, self).clean() + if self._errors: + return + credentials = self.user_credentials() + user = get_adapter(self.request).authenticate( + self.request, + **credentials) + if user: + self.user = user + else: + auth_method = app_settings.AUTHENTICATION_METHOD + if auth_method == app_settings.AuthenticationMethod.USERNAME_EMAIL: + login = self.cleaned_data['login'] + if self._is_login_email(login): + auth_method = app_settings.AuthenticationMethod.EMAIL + else: + auth_method = app_settings.AuthenticationMethod.USERNAME + raise forms.ValidationError( + + +## ... source file abbreviated to get to validators examples ... + + +class BaseSignupForm(_base_signup_form_class()): + username = forms.CharField(label=_("Username"), + min_length=app_settings.USERNAME_MIN_LENGTH, + widget=forms.TextInput( + attrs={'placeholder': + _('Username'), + 'autofocus': 'autofocus'})) + email = forms.EmailField(widget=forms.TextInput( + attrs={'type': 'email', + 'placeholder': _('E-mail address')})) + + def __init__(self, *args, **kwargs): + email_required = kwargs.pop('email_required', + app_settings.EMAIL_REQUIRED) + self.username_required = kwargs.pop('username_required', + app_settings.USERNAME_REQUIRED) + super(BaseSignupForm, self).__init__(*args, **kwargs) + username_field = self.fields['username'] + username_field.max_length = get_username_max_length() + username_field.validators.append( +~~ validators.MaxLengthValidator(username_field.max_length)) + username_field.widget.attrs['maxlength'] = str( + username_field.max_length) + + default_field_order = [ + 'email', + 'email2', # ignored when not present + 'username', + 'password1', + 'password2' # ignored when not present + ] + if app_settings.SIGNUP_EMAIL_ENTER_TWICE: + self.fields["email2"] = forms.EmailField( + label=_("E-mail (again)"), + widget=forms.TextInput( + attrs={ + 'type': 'email', + 'placeholder': _('E-mail address confirmation') + } + ) + ) + if email_required: + self.fields['email'].label = gettext("E-mail") + self.fields['email'].required = True + else: + + +## ... source file continues with no further validators examples... + +``` + + +## Example 2 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / utils / field_mapping.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/utils/field_mapping.py) + +```python +# field_mapping.py +import inspect + +~~from django.core import validators +from django.db import models +from django.utils.text import capfirst + +from rest_framework.compat import postgres_fields +from rest_framework.validators import UniqueValidator + +NUMERIC_FIELD_TYPES = ( + models.IntegerField, models.FloatField, models.DecimalField, models.DurationField, +) + + +class ClassLookupDict: + def __init__(self, mapping): + self.mapping = mapping + + def __getitem__(self, key): + if hasattr(key, '_proxy_class'): + base_class = key._proxy_class + else: + base_class = key.__class__ + + for cls in inspect.getmro(base_class): + if cls in self.mapping: + return self.mapping[cls] + + +## ... source file abbreviated to get to validators examples ... + + + if isinstance(model_field, models.FilePathField): + kwargs['path'] = model_field.path + + if model_field.match is not None: + kwargs['match'] = model_field.match + + if model_field.recursive is not False: + kwargs['recursive'] = model_field.recursive + + if model_field.allow_files is not True: + kwargs['allow_files'] = model_field.allow_files + + if model_field.allow_folders is not False: + kwargs['allow_folders'] = model_field.allow_folders + + if model_field.choices: + kwargs['choices'] = model_field.choices + else: + max_value = next(( + validator.limit_value for validator in validator_kwarg +~~ if isinstance(validator, validators.MaxValueValidator) + ), None) + if max_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): + kwargs['max_value'] = max_value + validator_kwarg = [ + validator for validator in validator_kwarg +~~ if not isinstance(validator, validators.MaxValueValidator) + ] + + min_value = next(( + validator.limit_value for validator in validator_kwarg +~~ if isinstance(validator, validators.MinValueValidator) + ), None) + if min_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): + kwargs['min_value'] = min_value + validator_kwarg = [ + validator for validator in validator_kwarg +~~ if not isinstance(validator, validators.MinValueValidator) + ] + + if isinstance(model_field, models.URLField): + validator_kwarg = [ + validator for validator in validator_kwarg +~~ if not isinstance(validator, validators.URLValidator) + ] + + if isinstance(model_field, models.EmailField): + validator_kwarg = [ + validator for validator in validator_kwarg +~~ if validator is not validators.validate_email + ] + + if isinstance(model_field, models.SlugField): + validator_kwarg = [ + validator for validator in validator_kwarg +~~ if validator is not validators.validate_slug + ] + + if isinstance(model_field, models.GenericIPAddressField): + validator_kwarg = [ + validator for validator in validator_kwarg +~~ if validator is not validators.validate_ipv46_address + ] + if isinstance(model_field, models.DecimalField): + validator_kwarg = [ + validator for validator in validator_kwarg +~~ if not isinstance(validator, validators.DecimalValidator) + ] + + max_length = getattr(model_field, 'max_length', None) + if max_length is not None and (isinstance(model_field, (models.CharField, models.TextField, models.FileField))): + kwargs['max_length'] = max_length + validator_kwarg = [ + validator for validator in validator_kwarg +~~ if not isinstance(validator, validators.MaxLengthValidator) + ] + + min_length = next(( + validator.limit_value for validator in validator_kwarg +~~ if isinstance(validator, validators.MinLengthValidator) + ), None) + if min_length is not None and isinstance(model_field, models.CharField): + kwargs['min_length'] = min_length + validator_kwarg = [ + validator for validator in validator_kwarg +~~ if not isinstance(validator, validators.MinLengthValidator) + ] + + if getattr(model_field, 'unique', False): + unique_error_message = model_field.error_messages.get('unique', None) + if unique_error_message: + unique_error_message = unique_error_message % { + 'model_name': model_field.model._meta.verbose_name, + 'field_label': model_field.verbose_name + } + validator = UniqueValidator( + queryset=model_field.model._default_manager, + message=unique_error_message) + validator_kwarg.append(validator) + + if validator_kwarg: + kwargs['validators'] = validator_kwarg + + return kwargs + + +def get_relation_kwargs(field_name, relation_info): + model_field, related_model, to_many, to_field, has_through_model, reverse = relation_info + kwargs = { + 'queryset': related_model._default_manager, + + +## ... source file continues with no further validators examples... + +``` + + +## Example 3 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / forms.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./forms.py) + +```python +# forms.py + "UserUpdateForm", + "WikiSlugField", + "SpamProtectionMixin", + "CreateRootForm", + "MoveForm", + "EditForm", + "SelectWidgetBootstrap", + "TextInputPrepend", + "CreateForm", + "DeleteForm", + "PermissionsForm", + "DirFilterForm", + "SearchForm", +] + +from datetime import timedelta + +from django import forms +from django.apps import apps +from django.contrib.auth import get_user_model +~~from django.core import validators +from django.core.validators import RegexValidator +from django.forms.widgets import HiddenInput +from django.shortcuts import get_object_or_404 +from django.urls import Resolver404, resolve +from django.utils import timezone +from django.utils.safestring import mark_safe +from django.utils.translation import gettext, gettext_lazy as _, pgettext_lazy +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.plugins.base import PluginSettingsFormMixin +from wiki.editors import getEditor + +from .forms_account_handling import UserCreationForm, UserUpdateForm + +validate_slug_numbers = RegexValidator( + r"^[0-9]+$", + _("A 'slug' cannot consist solely of numbers."), + "invalid", + inverse_match=True, +) + + +class WikiSlugField(forms.CharField): + + default_validators = [validators.validate_slug, validate_slug_numbers] + + def __init__(self, *args, **kwargs): + self.allow_unicode = kwargs.pop("allow_unicode", False) + if self.allow_unicode: + self.default_validators = [ +~~ validators.validate_unicode_slug, + validate_slug_numbers, + ] + super().__init__(*args, **kwargs) + + +def _clean_slug(slug, urlpath): + if slug.startswith("_"): + raise forms.ValidationError(gettext("A slug may not begin with an underscore.")) + if slug == "admin": + raise forms.ValidationError(gettext("'admin' is not a permitted slug name.")) + + if settings.URL_CASE_SENSITIVE: + already_existing_slug = models.URLPath.objects.filter(slug=slug, parent=urlpath) + else: + slug = slug.lower() + already_existing_slug = models.URLPath.objects.filter( + slug__iexact=slug, parent=urlpath + ) + if already_existing_slug: + already_urlpath = already_existing_slug[0] + if already_urlpath.article and already_urlpath.article.current_revision.deleted: + raise forms.ValidationError( + gettext('A deleted article with slug "%s" already exists.') + % already_urlpath.slug + + +## ... source file continues with no further validators examples... + +``` + diff --git a/content/pages/examples/django/django-db-backends-utils.markdown b/content/pages/examples/django/django-db-backends-utils.markdown new file mode 100644 index 000000000..0a182a01b --- /dev/null +++ b/content/pages/examples/django/django-db-backends-utils.markdown @@ -0,0 +1,148 @@ +title: django.db.backends utils Example Code +category: page +slug: django-db-backends-utils-examples +sortorder: 500011170 +toc: False +sidebartitle: django.db.backends utils +meta: Python example code for the utils callable from the django.db.backends module of the Django project. + + +utils is a callable within the django.db.backends module of the Django project. + + +## Example 1 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / management / debug_cursor.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/management/debug_cursor.py) + +```python +# debug_cursor.py +import six +import time +import traceback +from contextlib import contextmanager + +import django +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +~~from django.db.backends import utils + + +@contextmanager +def monkey_patch_cursordebugwrapper(print_sql=None, print_sql_location=False, truncate=None, logger=six.print_, confprefix="DJANGO_EXTENSIONS"): + if not print_sql: + yield + else: + truncate = getattr(settings, '%s_PRINT_SQL_TRUNCATE' % confprefix, 1000) + + sqlparse = None + if getattr(settings, '%s_SQLPARSE_ENABLED' % confprefix, True): + try: + import sqlparse + + sqlparse_format_kwargs_defaults = dict( + reindent_aligned=True, + truncate_strings=500, + ) + sqlparse_format_kwargs = getattr(settings, '%s_SQLPARSE_FORMAT_KWARGS' % confprefix, sqlparse_format_kwargs_defaults) + except ImportError: + sqlparse = None + + pygments = None + if getattr(settings, '%s_PYGMENTS_ENABLED' % confprefix, True): + try: + import pygments.lexers + import pygments.formatters + + pygments_formatter = getattr(settings, '%s_PYGMENTS_FORMATTER' % confprefix, pygments.formatters.TerminalFormatter) + pygments_formatter_kwargs = getattr(settings, '%s_PYGMENTS_FORMATTER_KWARGS' % confprefix, {}) + except ImportError: + pass + + class PrintQueryWrapperMixin: + def execute(self, sql, params=()): + starttime = time.time() + try: +~~ return utils.CursorWrapper.execute(self, sql, params) + finally: + execution_time = time.time() - starttime + raw_sql = self.db.ops.last_executed_query(self.cursor, sql, params) + if truncate: + raw_sql = raw_sql[:truncate] + + if sqlparse: + raw_sql = sqlparse.format(raw_sql, **sqlparse_format_kwargs) + + if pygments: + raw_sql = pygments.highlight( + raw_sql, + pygments.lexers.get_lexer_by_name("sql"), + pygments_formatter(**pygments_formatter_kwargs), + ) + + logger(raw_sql) + logger("Execution time: %.6fs [Database: %s]" % (execution_time, self.db.alias)) + if print_sql_location: + logger("Location of SQL Call:") + logger(''.join(traceback.format_stack())) + +~~ _CursorDebugWrapper = utils.CursorDebugWrapper + + class PrintCursorQueryWrapper(PrintQueryWrapperMixin, _CursorDebugWrapper): + pass + + try: + from django.db import connections + _force_debug_cursor = {} + for connection_name in connections: + _force_debug_cursor[connection_name] = connections[connection_name].force_debug_cursor + except Exception: + connections = None + +~~ utils.CursorDebugWrapper = PrintCursorQueryWrapper + + postgresql_base = None + if django.VERSION >= (3, 0): + try: + from django.db.backends.postgresql import base as postgresql_base + _PostgreSQLCursorDebugWrapper = postgresql_base.CursorDebugWrapper + + class PostgreSQLPrintCursorDebugWrapper(PrintQueryWrapperMixin, _PostgreSQLCursorDebugWrapper): + pass + except (ImproperlyConfigured, TypeError): + postgresql_base = None + + if postgresql_base: + postgresql_base.CursorDebugWrapper = PostgreSQLPrintCursorDebugWrapper + + if connections: + for connection_name in connections: + connections[connection_name].force_debug_cursor = True + + yield + +~~ utils.CursorDebugWrapper = _CursorDebugWrapper + + if postgresql_base: + postgresql_base.CursorDebugWrapper = _PostgreSQLCursorDebugWrapper + + if connections: + for connection_name in connections: + connections[connection_name].force_debug_cursor = _force_debug_cursor[connection_name] + + + +## ... source file continues with no further utils examples... + +``` + diff --git a/content/pages/examples/django/django-db-connection.markdown b/content/pages/examples/django/django-db-connection.markdown new file mode 100644 index 000000000..31ec9447d --- /dev/null +++ b/content/pages/examples/django/django-db-connection.markdown @@ -0,0 +1,486 @@ +title: django.db connection Example Code +category: page +slug: django-db-connection-examples +sortorder: 500011164 +toc: False +sidebartitle: django.db connection +meta: Python example code for the connection callable from the django.db module of the Django project. + + +connection is a callable within the django.db module of the Django project. + + +## Example 1 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / shortcuts.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./shortcuts.py) + +```python +# shortcuts.py +import warnings +from collections import defaultdict +from functools import partial +from itertools import groupby + +from django.apps import apps +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +~~from django.db import connection +from django.db.models import Count, Q, QuerySet +from django.shortcuts import _get_queryset +from django.db.models.expressions import Value +from django.db.models.functions import Cast, Replace +from django.db.models import ( + AutoField, + BigIntegerField, + CharField, + ForeignKey, + IntegerField, + PositiveIntegerField, + PositiveSmallIntegerField, + SmallIntegerField, + UUIDField, +) +from guardian.core import ObjectPermissionChecker +from guardian.ctypes import get_content_type +from guardian.exceptions import MixedContentTypeError, WrongAppError, MultipleIdentityAndObjectError +from guardian.utils import get_anonymous_user, get_group_obj_perms_model, get_identity, get_user_obj_perms_model +GroupObjectPermission = get_group_obj_perms_model() +UserObjectPermission = get_user_obj_perms_model() + + +def assign_perm(perm, user_or_group, obj=None): + + +## ... source file abbreviated to get to connection examples ... + + + + values = values.values_list(field_pk, flat=True) + return queryset.filter(pk__in=values) + + +def _handle_pk_field(queryset): + pk = queryset.model._meta.pk + + if isinstance(pk, ForeignKey): + return _handle_pk_field(pk.target_field) + + if isinstance( + pk, + ( + IntegerField, + AutoField, + BigIntegerField, + PositiveIntegerField, + PositiveSmallIntegerField, + SmallIntegerField, + ), + ): + return partial(Cast, output_field=BigIntegerField()) + + if isinstance(pk, UUIDField): +~~ if connection.features.has_native_uuid_field: + return partial(Cast, output_field=UUIDField()) + return partial( + Replace, + text=Value('-'), + replacement=Value(''), + output_field=CharField(), + ) + + return None + + + +## ... source file continues with no further connection examples... + +``` + + +## Example 2 from django-push-notifications +[django-push-notifications](https://github.com/jazzband/django-push-notifications) +is a [Django](/django.html) app for storing and interacting with +push notification services such as +[Google's Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/) +and +[Apple Notifications](https://developer.apple.com/notifications/). +The django-push-notification project's source code is available +open source under the +[MIT license](https://github.com/jazzband/django-push-notifications/blob/master/LICENSE). + +[**django-push-notifications / push_notifications / fields.py**](https://github.com/jazzband/django-push-notifications/blob/master/push_notifications/./fields.py) + +```python +# fields.py +import re +import struct + +from django import forms +from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator +~~from django.db import connection, models +from django.utils.translation import ugettext_lazy as _ + + +__all__ = ["HexadecimalField", "HexIntegerField"] + +UNSIGNED_64BIT_INT_MIN_VALUE = 0 +UNSIGNED_64BIT_INT_MAX_VALUE = 2 ** 64 - 1 + + +hex_re = re.compile(r"^(([0-9A-f])|(0x[0-9A-f]))+$") +signed_integer_engines = [ + "django.db.backends.postgresql", + "django.db.backends.postgresql_psycopg2", + "django.contrib.gis.db.backends.postgis", + "django.db.backends.sqlite3" +] + + +def _using_signed_storage(): +~~ return connection.settings_dict["ENGINE"] in signed_integer_engines + + +def _signed_to_unsigned_integer(value): + return struct.unpack("Q", struct.pack("q", value))[0] + + +def _unsigned_to_signed_integer(value): + return struct.unpack("q", struct.pack("Q", value))[0] + + +def _hex_string_to_unsigned_integer(value): + return int(value, 16) + + +def _unsigned_integer_to_hex_string(value): + return hex(value).rstrip("L") + + +class HexadecimalField(forms.CharField): + def __init__(self, *args, **kwargs): + self.default_validators = [ + RegexValidator(hex_re, _("Enter a valid hexadecimal number"), "invalid") + ] + super(HexadecimalField, self).__init__(*args, **kwargs) + + def prepare_value(self, value): + if value and not isinstance(value, str) \ +~~ and connection.vendor in ("mysql", "sqlite"): + value = _unsigned_integer_to_hex_string(value) + return super(forms.CharField, self).prepare_value(value) + + +class HexIntegerField(models.BigIntegerField): + + validators = [ + MinValueValidator(UNSIGNED_64BIT_INT_MIN_VALUE), + MaxValueValidator(UNSIGNED_64BIT_INT_MAX_VALUE) + ] + + def db_type(self, connection): +~~ engine = connection.settings_dict["ENGINE"] + if "mysql" in engine: + return "bigint unsigned" + elif "sqlite" in engine: + return "UNSIGNED BIG INT" + else: + return super(HexIntegerField, self).db_type(connection=connection) + + def get_prep_value(self, value): + if value is None or value == "": + return None + if isinstance(value, str): + value = _hex_string_to_unsigned_integer(value) + if _using_signed_storage(): + value = _unsigned_to_signed_integer(value) + return value + + def from_db_value(self, value, *args): + if value is None: + return value + if _using_signed_storage(): + value = _signed_to_unsigned_integer(value) + return value + + def to_python(self, value): + + +## ... source file continues with no further connection examples... + +``` + + +## Example 3 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / views.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./views.py) + +```python +# views.py +from django.conf import settings +from django.core.exceptions import PermissionDenied +~~from django.db import connection, models, transaction +from django.http import Http404 +from django.http.response import HttpResponseBase +from django.utils.cache import cc_delim_re, patch_vary_headers +from django.utils.encoding import smart_str +from django.views.decorators.csrf import csrf_exempt +from django.views.generic import View + +from rest_framework import exceptions, status +from rest_framework.request import Request +from rest_framework.response import Response +from rest_framework.schemas import DefaultSchema +from rest_framework.settings import api_settings +from rest_framework.utils import formatting + + +def get_view_name(view): + name = getattr(view, 'name', None) + if name is not None: + return name + + name = view.__class__.__name__ + name = formatting.remove_trailing_string(name, 'View') + name = formatting.remove_trailing_string(name, 'ViewSet') + name = formatting.camelcase_to_spaces(name) + + suffix = getattr(view, 'suffix', None) + if suffix: + name += ' ' + suffix + + return name + + +def get_view_description(view, html=False): + description = getattr(view, 'description', None) + if description is None: + description = view.__class__.__doc__ or '' + + description = formatting.dedent(smart_str(description)) + if html: + return formatting.markup_description(description) + return description + + +def set_rollback(): +~~ atomic_requests = connection.settings_dict.get('ATOMIC_REQUESTS', False) +~~ if atomic_requests and connection.in_atomic_block: + transaction.set_rollback(True) + + +def exception_handler(exc, context): + if isinstance(exc, Http404): + exc = exceptions.NotFound() + elif isinstance(exc, PermissionDenied): + exc = exceptions.PermissionDenied() + + if isinstance(exc, exceptions.APIException): + headers = {} + if getattr(exc, 'auth_header', None): + headers['WWW-Authenticate'] = exc.auth_header + if getattr(exc, 'wait', None): + headers['Retry-After'] = '%d' % exc.wait + + if isinstance(exc.detail, (list, dict)): + data = exc.detail + else: + data = {'detail': exc.detail} + + set_rollback() + return Response(data, status=exc.status_code, headers=headers) + + + +## ... source file continues with no further connection examples... + +``` + + +## Example 4 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / apps.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./apps.py) + +```python +# apps.py +from django.apps import AppConfig +~~from django.db import connections as djcs +from django.core.exceptions import ImproperlyConfigured + + +class ExplorerAppConfig(AppConfig): + + name = 'explorer' + + def ready(self): + from explorer.schema import build_async_schemas + _validate_connections() + build_async_schemas() + + +def _get_default(): + from explorer.app_settings import EXPLORER_DEFAULT_CONNECTION + return EXPLORER_DEFAULT_CONNECTION + + +def _get_explorer_connections(): + from explorer.app_settings import EXPLORER_CONNECTIONS + return EXPLORER_CONNECTIONS + + +def _validate_connections(): + + if _get_default() not in _get_explorer_connections().values(): + raise ImproperlyConfigured( + 'EXPLORER_DEFAULT_CONNECTION is %s, but that alias is not present in the values of EXPLORER_CONNECTIONS' + % _get_default()) + + for name, conn_name in _get_explorer_connections().items(): + if conn_name not in djcs: + raise ImproperlyConfigured( +~~ 'EXPLORER_CONNECTIONS contains (%s, %s), but %s is not a valid Django DB connection.' + % (name, conn_name, conn_name)) + + + +## ... source file continues with no further connection examples... + +``` + + +## Example 5 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / managers.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./managers.py) + +```python +# managers.py +import uuid +from operator import attrgetter + +from django import VERSION +from django.conf import settings +from django.contrib.contenttypes.fields import GenericRelation +from django.contrib.contenttypes.models import ContentType +~~from django.db import connections, models, router +from django.db.models import signals +from django.db.models.fields.related import ( + ManyToManyRel, + OneToOneRel, + RelatedField, + lazy_related_operation, +) +from django.db.models.query_utils import PathInfo +from django.utils.text import capfirst +from django.utils.translation import gettext_lazy as _ + +from taggit.forms import TagField +from taggit.models import ( + CommonGenericTaggedItemBase, + GenericUUIDTaggedItemBase, + TaggedItem, +) +from taggit.utils import require_instance_manager + + +class ExtraJoinRestriction: + + contains_aggregate = False + + + +## ... source file abbreviated to get to connection examples ... + + + kwargs = extra_filters if extra_filters else {} + return self.through.tags_for(self.model, self.instance, **kwargs) + + def get_prefetch_queryset(self, instances, queryset=None): + if queryset is not None: + raise ValueError("Custom queryset can't be used for this lookup.") + + instance = instances[0] + db = self._db or router.db_for_read(type(instance), instance=instance) + + fieldname = ( + "object_id" + if issubclass(self.through, CommonGenericTaggedItemBase) + else "content_object" + ) + fk = self.through._meta.get_field(fieldname) + query = { + "%s__%s__in" + % (self.through.tag_relname(), fk.name): { + obj._get_pk_val() for obj in instances + } + } + join_table = self.through._meta.db_table + source_col = fk.column + connection = connections[db] +~~ qn = connection.ops.quote_name + qs = ( + self.get_queryset(query) + .using(db) + .extra( + select={ + "_prefetch_related_val": "{}.{}".format( + qn(join_table), qn(source_col) + ) + } + ) + ) + + if issubclass(self.through, GenericUUIDTaggedItemBase): + + def uuid_rel_obj_attr(v): + value = attrgetter("_prefetch_related_val")(v) + if value is not None and not isinstance(value, uuid.UUID): + input_form = "int" if isinstance(value, int) else "hex" + value = uuid.UUID(**{input_form: value}) + return value + + rel_obj_attr = uuid_rel_obj_attr + else: + rel_obj_attr = attrgetter("_prefetch_related_val") + + +## ... source file continues with no further connection examples... + +``` + diff --git a/content/pages/examples/django/django-db-connections.markdown b/content/pages/examples/django/django-db-connections.markdown new file mode 100644 index 000000000..5bf5bfe44 --- /dev/null +++ b/content/pages/examples/django/django-db-connections.markdown @@ -0,0 +1,138 @@ +title: django.db connections Example Code +category: page +slug: django-db-connections-examples +sortorder: 500011165 +toc: False +sidebartitle: django.db connections +meta: Python example code for the connections callable from the django.db module of the Django project. + + +connections is a callable within the django.db module of the Django project. + + +## Example 1 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / management / debug_cursor.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/management/debug_cursor.py) + +```python +# debug_cursor.py +import six +import time +import traceback +from contextlib import contextmanager + +import django +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db.backends import utils + + +@contextmanager +def monkey_patch_cursordebugwrapper(print_sql=None, print_sql_location=False, truncate=None, logger=six.print_, confprefix="DJANGO_EXTENSIONS"): + if not print_sql: + yield + else: + truncate = getattr(settings, '%s_PRINT_SQL_TRUNCATE' % confprefix, 1000) + + sqlparse = None + if getattr(settings, '%s_SQLPARSE_ENABLED' % confprefix, True): + try: + import sqlparse + + sqlparse_format_kwargs_defaults = dict( + reindent_aligned=True, + truncate_strings=500, + ) + sqlparse_format_kwargs = getattr(settings, '%s_SQLPARSE_FORMAT_KWARGS' % confprefix, sqlparse_format_kwargs_defaults) + except ImportError: + sqlparse = None + + pygments = None + if getattr(settings, '%s_PYGMENTS_ENABLED' % confprefix, True): + try: + import pygments.lexers + + +## ... source file abbreviated to get to connections examples ... + + + if truncate: + raw_sql = raw_sql[:truncate] + + if sqlparse: + raw_sql = sqlparse.format(raw_sql, **sqlparse_format_kwargs) + + if pygments: + raw_sql = pygments.highlight( + raw_sql, + pygments.lexers.get_lexer_by_name("sql"), + pygments_formatter(**pygments_formatter_kwargs), + ) + + logger(raw_sql) + logger("Execution time: %.6fs [Database: %s]" % (execution_time, self.db.alias)) + if print_sql_location: + logger("Location of SQL Call:") + logger(''.join(traceback.format_stack())) + + _CursorDebugWrapper = utils.CursorDebugWrapper + + class PrintCursorQueryWrapper(PrintQueryWrapperMixin, _CursorDebugWrapper): + pass + + try: +~~ from django.db import connections + _force_debug_cursor = {} +~~ for connection_name in connections: + _force_debug_cursor[connection_name] = connections[connection_name].force_debug_cursor + except Exception: + connections = None + + utils.CursorDebugWrapper = PrintCursorQueryWrapper + + postgresql_base = None + if django.VERSION >= (3, 0): + try: + from django.db.backends.postgresql import base as postgresql_base + _PostgreSQLCursorDebugWrapper = postgresql_base.CursorDebugWrapper + + class PostgreSQLPrintCursorDebugWrapper(PrintQueryWrapperMixin, _PostgreSQLCursorDebugWrapper): + pass + except (ImproperlyConfigured, TypeError): + postgresql_base = None + + if postgresql_base: + postgresql_base.CursorDebugWrapper = PostgreSQLPrintCursorDebugWrapper + + if connections: +~~ for connection_name in connections: + connections[connection_name].force_debug_cursor = True + + yield + + utils.CursorDebugWrapper = _CursorDebugWrapper + + if postgresql_base: + postgresql_base.CursorDebugWrapper = _PostgreSQLCursorDebugWrapper + + if connections: +~~ for connection_name in connections: + connections[connection_name].force_debug_cursor = _force_debug_cursor[connection_name] + + + +## ... source file continues with no further connections examples... + +``` + diff --git a/content/pages/examples/django/django-db-databaseerror.markdown b/content/pages/examples/django/django-db-databaseerror.markdown new file mode 100644 index 000000000..3af45c352 --- /dev/null +++ b/content/pages/examples/django/django-db-databaseerror.markdown @@ -0,0 +1,95 @@ +title: django.db DatabaseError Example Code +category: page +slug: django-db-databaseerror-examples +sortorder: 500011160 +toc: False +sidebartitle: django.db DatabaseError +meta: Python example code for the DatabaseError class from the django.db module of the Django project. + + +DatabaseError is a class within the django.db module of the Django project. + + +## Example 1 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / tasks.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./tasks.py) + +```python +# tasks.py +from datetime import date, datetime, timedelta +import random +import string + +from django.core.mail import send_mail +from django.core.cache import cache +~~from django.db import DatabaseError + +from explorer import app_settings +from explorer.exporters import get_exporter_class +from explorer.models import Query, QueryLog + +if app_settings.ENABLE_TASKS: + from celery import task + from celery.utils.log import get_task_logger + from explorer.utils import s3_upload + logger = get_task_logger(__name__) +else: + from explorer.utils import noop_decorator as task + import logging + logger = logging.getLogger(__name__) + + +@task +def execute_query(query_id, email_address): + q = Query.objects.get(pk=query_id) + send_mail('[SQL Explorer] Your query is running...', + '%s is running and should be in your inbox soon!' % q.title, + app_settings.FROM_EMAIL, + [email_address]) + + exporter = get_exporter_class('csv')(q) + random_part = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(20)) + try: + url = s3_upload('%s.csv' % random_part, exporter.get_file_output()) + subj = '[SQL Explorer] Report "%s" is ready' % q.title + msg = 'Download results:\n\r%s' % url +~~ except DatabaseError as e: + subj = '[SQL Explorer] Error running report %s' % q.title + msg = 'Error: %s\nPlease contact an administrator' % e + logger.warning('%s: %s' % (subj, e)) + send_mail(subj, msg, app_settings.FROM_EMAIL, [email_address]) + + +@task +def snapshot_query(query_id): + try: + logger.info("Starting snapshot for query %s..." % query_id) + q = Query.objects.get(pk=query_id) + exporter = get_exporter_class('csv')(q) + k = 'query-%s/snap-%s.csv' % (q.id, date.today().strftime('%Y%m%d-%H:%M:%S')) + logger.info("Uploading snapshot for query %s as %s..." % (query_id, k)) + url = s3_upload(k, exporter.get_file_output()) + logger.info("Done uploading snapshot for query %s. URL: %s" % (query_id, url)) + except Exception as e: + logger.warning("Failed to snapshot query %s (%s). Retrying..." % (query_id, e)) + snapshot_query.retry() + + +@task +def snapshot_queries(): + logger.info("Starting query snapshots...") + + +## ... source file continues with no further DatabaseError examples... + +``` + diff --git a/content/pages/examples/django/django-db-dataerror.markdown b/content/pages/examples/django/django-db-dataerror.markdown new file mode 100644 index 000000000..70270fa35 --- /dev/null +++ b/content/pages/examples/django/django-db-dataerror.markdown @@ -0,0 +1,79 @@ +title: django.db DataError Example Code +category: page +slug: django-db-dataerror-examples +sortorder: 500011159 +toc: False +sidebartitle: django.db DataError +meta: Python example code for the DataError class from the django.db module of the Django project. + + +DataError is a class within the django.db module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / validators.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./validators.py) + +```python +# validators.py +~~from django.db import DataError +from django.utils.translation import gettext_lazy as _ + +from rest_framework.exceptions import ValidationError +from rest_framework.utils.representation import smart_repr + + +def qs_exists(queryset): + try: + return queryset.exists() +~~ except (TypeError, ValueError, DataError): + return False + + +def qs_filter(queryset, **kwargs): + try: + return queryset.filter(**kwargs) +~~ except (TypeError, ValueError, DataError): + return queryset.none() + + +class UniqueValidator: + message = _('This field must be unique.') + requires_context = True + + def __init__(self, queryset, message=None, lookup='exact'): + self.queryset = queryset + self.message = message or self.message + self.lookup = lookup + + def filter_queryset(self, value, queryset, field_name): + filter_kwargs = {'%s__%s' % (field_name, self.lookup): value} + return qs_filter(queryset, **filter_kwargs) + + def exclude_current_instance(self, queryset, instance): + if instance is not None: + return queryset.exclude(pk=instance.pk) + return queryset + + def __call__(self, value, serializer_field): + field_name = serializer_field.source_attrs[-1] + instance = getattr(serializer_field.parent, 'instance', None) + + +## ... source file continues with no further DataError examples... + +``` + diff --git a/content/pages/examples/django/django-db-default-db-alias.markdown b/content/pages/examples/django/django-db-default-db-alias.markdown new file mode 100644 index 000000000..762579708 --- /dev/null +++ b/content/pages/examples/django/django-db-default-db-alias.markdown @@ -0,0 +1,185 @@ +title: django.db DEFAULT_DB_ALIAS Example Code +category: page +slug: django-db-default-db-alias-examples +sortorder: 500011158 +toc: False +sidebartitle: django.db DEFAULT_DB_ALIAS +meta: Python example code for the DEFAULT_DB_ALIAS constant from the django.db module of the Django project. + + +DEFAULT_DB_ALIAS is a constant within the django.db module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog / models.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog/models.py) + +```python +# models.py +from __future__ import unicode_literals + +import json +import ast + +from django.conf import settings +from django.contrib.contenttypes.fields import GenericRelation +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import FieldDoesNotExist +~~from django.db import models, DEFAULT_DB_ALIAS +from django.db.models import QuerySet, Q +from django.utils import formats, timezone +from django.utils.encoding import python_2_unicode_compatible, smart_text +from django.utils.six import iteritems, integer_types +from django.utils.translation import ugettext_lazy as _ + +from jsonfield.fields import JSONField +from dateutil import parser +from dateutil.tz import gettz + + +class LogEntryManager(models.Manager): + + def log_create(self, instance, **kwargs): + changes = kwargs.get('changes', None) + pk = self._get_pk_value(instance) + + if changes is not None: + kwargs.setdefault('content_type', ContentType.objects.get_for_model(instance)) + kwargs.setdefault('object_pk', pk) + kwargs.setdefault('object_repr', smart_text(instance)) + + if isinstance(pk, integer_types): + kwargs.setdefault('object_id', pk) + + +## ... source file continues with no further DEFAULT_DB_ALIAS examples... + +``` + + +## Example 2 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / resources.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./resources.py) + +```python +# resources.py +import functools +import logging +import tablib +import traceback +from collections import OrderedDict +from copy import deepcopy + +from diff_match_patch import diff_match_patch + +import django +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.core.management.color import no_style +from django.core.paginator import Paginator +~~from django.db import DEFAULT_DB_ALIAS, connections +from django.db.models.fields.related import ForeignObjectRel +from django.db.models.query import QuerySet +from django.db.transaction import ( + TransactionManagementError, + atomic, + savepoint, + savepoint_commit, + savepoint_rollback +) +from django.utils.encoding import force_str +from django.utils.safestring import mark_safe + +from . import widgets +from .fields import Field +from .instance_loaders import ModelInstanceLoader +from .results import Error, Result, RowResult +from .utils import atomic_if_using_transaction + +if django.VERSION[0] >= 3: + from django.core.exceptions import FieldDoesNotExist +else: + from django.db.models.fields import FieldDoesNotExist + + + + +## ... source file continues with no further DEFAULT_DB_ALIAS examples... + +``` + + +## Example 3 from django-migration-linter +[django-migration-linter](https://github.com/3YOURMIND/django-migration-linter) +([PyPI package information](https://pypi.org/project/django-migration-linter/)) +checks for backwards-incompatible changes in [Django ORM](/django-orm.html) +schema migrations and warns you about them. The purpose of the project is +to save time in older and larger projects by detecting field migrations +that will be a problem so you do not run into issues later, and make it +easier to enable continuous [deployment](/deployment.html) configurations +with database changes. There is a +[blog post on keeping Django database migrations backward compatible](https://medium.com/3yourmind/keeping-django-database-migrations-backward-compatible-727820260dbb) +that goes into further detail on the tool. + +The django-migration-linter project is open sourced under the +[Apache 2.0 license](https://github.com/3YOURMIND/django-migration-linter/blob/master/LICENSE). + +[**django-migration-linter / django_migration_linter / migration_linter.py**](https://github.com/3YOURMIND/django-migration-linter/blob/master/django_migration_linter/./migration_linter.py) + +```python +# migration_linter.py +from __future__ import print_function + +import hashlib +import inspect +import logging +import os +import re +from subprocess import Popen, PIPE + +from django.conf import settings +from django.core.management import call_command +~~from django.db import DEFAULT_DB_ALIAS, connections, ProgrammingError +from django.db.migrations import RunPython +from enum import Enum, unique +from six import PY2 + +from .cache import Cache +from .constants import ( + DEFAULT_CACHE_PATH, + EXPECTED_DATA_MIGRATION_ARGS, + DJANGO_APPS_WITH_MIGRATIONS, +) +from .utils import clean_bytes_to_str, get_migration_abspath, split_migration_path +from .operations import IgnoreMigration +from .sql_analyser import analyse_sql_statements + +logger = logging.getLogger(__name__) + + +@unique +class MessageType(Enum): + OK = "ok" + IGNORE = "ignore" + WARNING = "warning" + ERROR = "error" + + + +## ... source file continues with no further DEFAULT_DB_ALIAS examples... + +``` + diff --git a/content/pages/examples/django/django-db-integrityerror.markdown b/content/pages/examples/django/django-db-integrityerror.markdown new file mode 100644 index 000000000..be8d2e5a2 --- /dev/null +++ b/content/pages/examples/django/django-db-integrityerror.markdown @@ -0,0 +1,97 @@ +title: django.db IntegrityError Example Code +category: page +slug: django-db-integrityerror-examples +sortorder: 500011161 +toc: False +sidebartitle: django.db IntegrityError +meta: Python example code for the IntegrityError class from the django.db module of the Django project. + + +IntegrityError is a class within the django.db module of the Django project. + + +## Example 1 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / models.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./models.py) + +```python +# models.py +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +~~from django.db import IntegrityError, models, router, transaction +from django.utils.text import slugify +from django.utils.translation import gettext, gettext_lazy as _ + +try: + from unidecode import unidecode +except ImportError: + + def unidecode(tag): + return tag + + +class TagBase(models.Model): + name = models.CharField(verbose_name=_("name"), unique=True, max_length=100) + slug = models.SlugField(verbose_name=_("slug"), unique=True, max_length=100) + + def __str__(self): + return self.name + + def __gt__(self, other): + return self.name.lower() > other.name.lower() + + def __lt__(self, other): + return self.name.lower() < other.name.lower() + + class Meta: + abstract = True + + def save(self, *args, **kwargs): + if self._state.adding and not self.slug: + self.slug = self.slugify(self.name) + using = kwargs.get("using") or router.db_for_write( + type(self), instance=self + ) + kwargs["using"] = using + try: + with transaction.atomic(using=using): + res = super().save(*args, **kwargs) + return res +~~ except IntegrityError: + pass + slugs = set( + type(self) + ._default_manager.filter(slug__startswith=self.slug) + .values_list("slug", flat=True) + ) + i = 1 + while True: + slug = self.slugify(self.name, i) + if slug not in slugs: + self.slug = slug + return super().save(*args, **kwargs) + i += 1 + else: + return super().save(*args, **kwargs) + + def slugify(self, tag, i=None): + slug = slugify(unidecode(tag)) + if i is not None: + slug += "_%d" % i + return slug + + +class Tag(TagBase): + + +## ... source file continues with no further IntegrityError examples... + +``` + diff --git a/content/pages/examples/django/django-db-migrations-autodetector-migrationautodetector.markdown b/content/pages/examples/django/django-db-migrations-autodetector-migrationautodetector.markdown new file mode 100644 index 000000000..70f3cd1d0 --- /dev/null +++ b/content/pages/examples/django/django-db-migrations-autodetector-migrationautodetector.markdown @@ -0,0 +1,74 @@ +title: django.db.migrations.autodetector MigrationAutodetector Example Code +category: page +slug: django-db-migrations-autodetector-migrationautodetector-examples +sortorder: 500011172 +toc: False +sidebartitle: django.db.migrations.autodetector MigrationAutodetector +meta: Python example code for the MigrationAutodetector class from the django.db.migrations.autodetector module of the Django project. + + +MigrationAutodetector is a class within the django.db.migrations.autodetector module of the Django project. + + +## Example 1 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / tests / test_models.py**](https://github.com/jazzband/django-axes/blob/master/axes/tests/test_models.py) + +```python +# test_models.py +from django.apps.registry import apps +from django.db import connection +~~from django.db.migrations.autodetector import MigrationAutodetector +from django.db.migrations.executor import MigrationExecutor +from django.db.migrations.state import ProjectState + +from axes.models import AccessAttempt, AccessLog +from axes.tests.base import AxesTestCase + + +class ModelsTestCase(AxesTestCase): + def setUp(self): + self.failures_since_start = 42 + + self.access_attempt = AccessAttempt( + failures_since_start=self.failures_since_start + ) + self.access_log = AccessLog() + + def test_access_attempt_str(self): + self.assertIn("Access", str(self.access_attempt)) + + def test_access_log_str(self): + self.assertIn("Access", str(self.access_log)) + + +class MigrationsTestCase(AxesTestCase): + def test_missing_migrations(self): + executor = MigrationExecutor(connection) +~~ autodetector = MigrationAutodetector( + executor.loader.project_state(), ProjectState.from_apps(apps) + ) + + changes = autodetector.changes(graph=executor.loader.graph) + + self.assertEqual({}, changes) + + + +## ... source file continues with no further MigrationAutodetector examples... + +``` + diff --git a/content/pages/examples/django/django-db-migrations-exceptions-irreversibleerror.markdown b/content/pages/examples/django/django-db-migrations-exceptions-irreversibleerror.markdown new file mode 100644 index 000000000..ecb9a015e --- /dev/null +++ b/content/pages/examples/django/django-db-migrations-exceptions-irreversibleerror.markdown @@ -0,0 +1,43 @@ +title: django.db.migrations.exceptions IrreversibleError Example Code +category: page +slug: django-db-migrations-exceptions-irreversibleerror-examples +sortorder: 500011173 +toc: False +sidebartitle: django.db.migrations.exceptions IrreversibleError +meta: Python example code for the IrreversibleError class from the django.db.migrations.exceptions module of the Django project. + + +IrreversibleError is a class within the django.db.migrations.exceptions module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / migrations / __init__.py**](https://github.com/divio/django-cms/blob/develop/cms/migrations/__init__.py) + +```python +# __init__.py +from django.db import migrations + +try: + IrreversibleError = migrations.Migration.IrreversibleError +except AttributeError: +~~ from django.db.migrations.exceptions import IrreversibleError + + +class IrreversibleMigration(migrations.Migration): + + def unapply(self, project_state, schema_editor, collect_sql=False): +~~ raise IrreversibleError('Migration %s is not reversible' % self.name) + + + +## ... source file continues with no further IrreversibleError examples... + +``` + diff --git a/content/pages/examples/django/django-db-migrations-executor-migrationexecutor.markdown b/content/pages/examples/django/django-db-migrations-executor-migrationexecutor.markdown new file mode 100644 index 000000000..2d2937edc --- /dev/null +++ b/content/pages/examples/django/django-db-migrations-executor-migrationexecutor.markdown @@ -0,0 +1,74 @@ +title: django.db.migrations.executor MigrationExecutor Example Code +category: page +slug: django-db-migrations-executor-migrationexecutor-examples +sortorder: 500011174 +toc: False +sidebartitle: django.db.migrations.executor MigrationExecutor +meta: Python example code for the MigrationExecutor class from the django.db.migrations.executor module of the Django project. + + +MigrationExecutor is a class within the django.db.migrations.executor module of the Django project. + + +## Example 1 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / tests / test_models.py**](https://github.com/jazzband/django-axes/blob/master/axes/tests/test_models.py) + +```python +# test_models.py +from django.apps.registry import apps +from django.db import connection +from django.db.migrations.autodetector import MigrationAutodetector +~~from django.db.migrations.executor import MigrationExecutor +from django.db.migrations.state import ProjectState + +from axes.models import AccessAttempt, AccessLog +from axes.tests.base import AxesTestCase + + +class ModelsTestCase(AxesTestCase): + def setUp(self): + self.failures_since_start = 42 + + self.access_attempt = AccessAttempt( + failures_since_start=self.failures_since_start + ) + self.access_log = AccessLog() + + def test_access_attempt_str(self): + self.assertIn("Access", str(self.access_attempt)) + + def test_access_log_str(self): + self.assertIn("Access", str(self.access_log)) + + +class MigrationsTestCase(AxesTestCase): + def test_missing_migrations(self): +~~ executor = MigrationExecutor(connection) + autodetector = MigrationAutodetector( + executor.loader.project_state(), ProjectState.from_apps(apps) + ) + + changes = autodetector.changes(graph=executor.loader.graph) + + self.assertEqual({}, changes) + + + +## ... source file continues with no further MigrationExecutor examples... + +``` + diff --git a/content/pages/examples/django/django-db-migrations-loader-migrationloader.markdown b/content/pages/examples/django/django-db-migrations-loader-migrationloader.markdown new file mode 100644 index 000000000..46a09f2ee --- /dev/null +++ b/content/pages/examples/django/django-db-migrations-loader-migrationloader.markdown @@ -0,0 +1,129 @@ +title: django.db.migrations.loader MigrationLoader Example Code +category: page +slug: django-db-migrations-loader-migrationloader-examples +sortorder: 500011176 +toc: False +sidebartitle: django.db.migrations.loader MigrationLoader +meta: Python example code for the MigrationLoader class from the django.db.migrations.loader module of the Django project. + + +MigrationLoader is a class within the django.db.migrations.loader module of the Django project. + + +## Example 1 from django-migration-linter +[django-migration-linter](https://github.com/3YOURMIND/django-migration-linter) +([PyPI package information](https://pypi.org/project/django-migration-linter/)) +checks for backwards-incompatible changes in [Django ORM](/django-orm.html) +schema migrations and warns you about them. The purpose of the project is +to save time in older and larger projects by detecting field migrations +that will be a problem so you do not run into issues later, and make it +easier to enable continuous [deployment](/deployment.html) configurations +with database changes. There is a +[blog post on keeping Django database migrations backward compatible](https://medium.com/3yourmind/keeping-django-database-migrations-backward-compatible-727820260dbb) +that goes into further detail on the tool. + +The django-migration-linter project is open sourced under the +[Apache 2.0 license](https://github.com/3YOURMIND/django-migration-linter/blob/master/LICENSE). + +[**django-migration-linter / django_migration_linter / migration_linter.py**](https://github.com/3YOURMIND/django-migration-linter/blob/master/django_migration_linter/./migration_linter.py) + +```python +# migration_linter.py +from __future__ import print_function + +import hashlib +import inspect +import logging +import os +import re +from subprocess import Popen, PIPE + +from django.conf import settings +from django.core.management import call_command +from django.db import DEFAULT_DB_ALIAS, connections, ProgrammingError +from django.db.migrations import RunPython +from enum import Enum, unique +from six import PY2 + +from .cache import Cache +from .constants import ( + DEFAULT_CACHE_PATH, + EXPECTED_DATA_MIGRATION_ARGS, + DJANGO_APPS_WITH_MIGRATIONS, +) +from .utils import clean_bytes_to_str, get_migration_abspath, split_migration_path +from .operations import IgnoreMigration +from .sql_analyser import analyse_sql_statements + +logger = logging.getLogger(__name__) + + +@unique +class MessageType(Enum): + OK = "ok" + IGNORE = "ignore" + WARNING = "warning" + ERROR = "error" + + +## ... source file abbreviated to get to MigrationLoader examples ... + + + exclude_migration_tests=None, + quiet=None, + warnings_as_errors=False, + ): + self.django_path = path + self.ignore_name_contains = ignore_name_contains + self.ignore_name = ignore_name or tuple() + self.include_apps = include_apps + self.exclude_apps = exclude_apps + self.exclude_migration_tests = exclude_migration_tests or [] + self.database = database or DEFAULT_DB_ALIAS + self.cache_path = cache_path or DEFAULT_CACHE_PATH + self.no_cache = no_cache + self.only_applied_migrations = only_applied_migrations + self.only_unapplied_migrations = only_unapplied_migrations + self.quiet = quiet or [] + self.warnings_as_errors = warnings_as_errors + + self.reset_counters() + + if self.should_use_cache(): + self.old_cache = Cache(self.django_path, self.database, self.cache_path) + self.new_cache = Cache(self.django_path, self.database, self.cache_path) + self.old_cache.load() + +~~ from django.db.migrations.loader import MigrationLoader + +~~ self.migration_loader = MigrationLoader( + connection=connections[self.database], load=True + ) + + def reset_counters(self): + self.nb_valid = 0 + self.nb_ignored = 0 + self.nb_warnings = 0 + self.nb_erroneous = 0 + self.nb_total = 0 + + def should_use_cache(self): + return self.django_path and not self.no_cache + + def lint_all_migrations(self, git_commit_id=None, migrations_file_path=None): + migrations_list = self.read_migrations_list(migrations_file_path) + if git_commit_id: + migrations = self._gather_migrations_git(git_commit_id, migrations_list) + else: + migrations = self._gather_all_migrations(migrations_list) + + sorted_migrations = sorted( + migrations, key=lambda migration: (migration.app_label, migration.name) + ) + for m in sorted_migrations: + + +## ... source file continues with no further MigrationLoader examples... + +``` + diff --git a/content/pages/examples/django/django-db-migrations-loader-migrations-module-name.markdown b/content/pages/examples/django/django-db-migrations-loader-migrations-module-name.markdown new file mode 100644 index 000000000..fddea6c62 --- /dev/null +++ b/content/pages/examples/django/django-db-migrations-loader-migrations-module-name.markdown @@ -0,0 +1,130 @@ +title: django.db.migrations.loader MIGRATIONS_MODULE_NAME Example Code +category: page +slug: django-db-migrations-loader-migrations-module-name-examples +sortorder: 500011175 +toc: False +sidebartitle: django.db.migrations.loader MIGRATIONS_MODULE_NAME +meta: Python example code for the MIGRATIONS_MODULE_NAME constant from the django.db.migrations.loader module of the Django project. + + +MIGRATIONS_MODULE_NAME is a constant within the django.db.migrations.loader module of the Django project. + + +## Example 1 from django-migration-linter +[django-migration-linter](https://github.com/3YOURMIND/django-migration-linter) +([PyPI package information](https://pypi.org/project/django-migration-linter/)) +checks for backwards-incompatible changes in [Django ORM](/django-orm.html) +schema migrations and warns you about them. The purpose of the project is +to save time in older and larger projects by detecting field migrations +that will be a problem so you do not run into issues later, and make it +easier to enable continuous [deployment](/deployment.html) configurations +with database changes. There is a +[blog post on keeping Django database migrations backward compatible](https://medium.com/3yourmind/keeping-django-database-migrations-backward-compatible-727820260dbb) +that goes into further detail on the tool. + +The django-migration-linter project is open sourced under the +[Apache 2.0 license](https://github.com/3YOURMIND/django-migration-linter/blob/master/LICENSE). + +[**django-migration-linter / django_migration_linter / migration_linter.py**](https://github.com/3YOURMIND/django-migration-linter/blob/master/django_migration_linter/./migration_linter.py) + +```python +# migration_linter.py +from __future__ import print_function + +import hashlib +import inspect +import logging +import os +import re +from subprocess import Popen, PIPE + +from django.conf import settings +from django.core.management import call_command +from django.db import DEFAULT_DB_ALIAS, connections, ProgrammingError +from django.db.migrations import RunPython +from enum import Enum, unique +from six import PY2 + +from .cache import Cache +from .constants import ( + DEFAULT_CACHE_PATH, + EXPECTED_DATA_MIGRATION_ARGS, + DJANGO_APPS_WITH_MIGRATIONS, +) +from .utils import clean_bytes_to_str, get_migration_abspath, split_migration_path +from .operations import IgnoreMigration +from .sql_analyser import analyse_sql_statements + +logger = logging.getLogger(__name__) + + +@unique +class MessageType(Enum): + OK = "ok" + IGNORE = "ignore" + WARNING = "warning" + ERROR = "error" + + +## ... source file abbreviated to get to MIGRATIONS_MODULE_NAME examples ... + + + "Calling sqlmigrate command {} {}".format(app_label, migration_name) + ) + dev_null = open(os.devnull, "w") + try: + sql_statement = call_command( + "sqlmigrate", + app_label, + migration_name, + database=self.database, + stdout=dev_null, + ) + except (ValueError, ProgrammingError): + logger.warning( + ( + "Error while executing sqlmigrate on (%s, %s). " + "Continuing execution with empty SQL." + ), + app_label, + migration_name, + ) + sql_statement = "" + return sql_statement.splitlines() + + @staticmethod + def is_migration_file(filename): +~~ from django.db.migrations.loader import MIGRATIONS_MODULE_NAME + + return ( +~~ re.search(r"/{0}/.*\.py".format(MIGRATIONS_MODULE_NAME), filename) + and "__init__" not in filename + ) + + @classmethod + def read_migrations_list(cls, migrations_file_path): + if not migrations_file_path: + return None + + migrations = [] + try: + with open(migrations_file_path, "r") as file: + for line in file: + if cls.is_migration_file(line): + app_label, name = split_migration_path(line) + migrations.append((app_label, name)) + except IOError: + logger.exception("Migrations list path not found %s", migrations_file_path) + raise Exception("Error while reading migrations list file") + + if not migrations: + logger.info( + "No valid migration paths found in the migrations file %s", + migrations_file_path, + ) + + +## ... source file continues with no further MIGRATIONS_MODULE_NAME examples... + +``` + diff --git a/content/pages/examples/django/django-db-migrations-operations-base-operation.markdown b/content/pages/examples/django/django-db-migrations-operations-base-operation.markdown new file mode 100644 index 000000000..151b91c0b --- /dev/null +++ b/content/pages/examples/django/django-db-migrations-operations-base-operation.markdown @@ -0,0 +1,57 @@ +title: django.db.migrations.operations.base Operation Example Code +category: page +slug: django-db-migrations-operations-base-operation-examples +sortorder: 500011177 +toc: False +sidebartitle: django.db.migrations.operations.base Operation +meta: Python example code for the Operation class from the django.db.migrations.operations.base module of the Django project. + + +Operation is a class within the django.db.migrations.operations.base module of the Django project. + + +## Example 1 from django-migration-linter +[django-migration-linter](https://github.com/3YOURMIND/django-migration-linter) +([PyPI package information](https://pypi.org/project/django-migration-linter/)) +checks for backwards-incompatible changes in [Django ORM](/django-orm.html) +schema migrations and warns you about them. The purpose of the project is +to save time in older and larger projects by detecting field migrations +that will be a problem so you do not run into issues later, and make it +easier to enable continuous [deployment](/deployment.html) configurations +with database changes. There is a +[blog post on keeping Django database migrations backward compatible](https://medium.com/3yourmind/keeping-django-database-migrations-backward-compatible-727820260dbb) +that goes into further detail on the tool. + +The django-migration-linter project is open sourced under the +[Apache 2.0 license](https://github.com/3YOURMIND/django-migration-linter/blob/master/LICENSE). + +[**django-migration-linter / django_migration_linter / operations.py**](https://github.com/3YOURMIND/django-migration-linter/blob/master/django_migration_linter/./operations.py) + +```python +# operations.py +~~from django.db.migrations.operations.base import Operation + + +~~class IgnoreMigration(Operation): + + reversible = True + reduces_to_sql = False + + def state_forwards(self, app_label, state): + pass + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + pass + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + pass + + def describe(self): + return "The Django migration linter will ignore this migration" + + + +## ... source file continues with no further Operation examples... + +``` + diff --git a/content/pages/examples/django/django-db-migrations-runpython.markdown b/content/pages/examples/django/django-db-migrations-runpython.markdown new file mode 100644 index 000000000..ed25366f5 --- /dev/null +++ b/content/pages/examples/django/django-db-migrations-runpython.markdown @@ -0,0 +1,129 @@ +title: django.db.migrations RunPython Example Code +category: page +slug: django-db-migrations-runpython-examples +sortorder: 500011171 +toc: False +sidebartitle: django.db.migrations RunPython +meta: Python example code for the RunPython class from the django.db.migrations module of the Django project. + + +RunPython is a class within the django.db.migrations module of the Django project. + + +## Example 1 from django-migration-linter +[django-migration-linter](https://github.com/3YOURMIND/django-migration-linter) +([PyPI package information](https://pypi.org/project/django-migration-linter/)) +checks for backwards-incompatible changes in [Django ORM](/django-orm.html) +schema migrations and warns you about them. The purpose of the project is +to save time in older and larger projects by detecting field migrations +that will be a problem so you do not run into issues later, and make it +easier to enable continuous [deployment](/deployment.html) configurations +with database changes. There is a +[blog post on keeping Django database migrations backward compatible](https://medium.com/3yourmind/keeping-django-database-migrations-backward-compatible-727820260dbb) +that goes into further detail on the tool. + +The django-migration-linter project is open sourced under the +[Apache 2.0 license](https://github.com/3YOURMIND/django-migration-linter/blob/master/LICENSE). + +[**django-migration-linter / django_migration_linter / migration_linter.py**](https://github.com/3YOURMIND/django-migration-linter/blob/master/django_migration_linter/./migration_linter.py) + +```python +# migration_linter.py +from __future__ import print_function + +import hashlib +import inspect +import logging +import os +import re +from subprocess import Popen, PIPE + +from django.conf import settings +from django.core.management import call_command +from django.db import DEFAULT_DB_ALIAS, connections, ProgrammingError +~~from django.db.migrations import RunPython +from enum import Enum, unique +from six import PY2 + +from .cache import Cache +from .constants import ( + DEFAULT_CACHE_PATH, + EXPECTED_DATA_MIGRATION_ARGS, + DJANGO_APPS_WITH_MIGRATIONS, +) +from .utils import clean_bytes_to_str, get_migration_abspath, split_migration_path +from .operations import IgnoreMigration +from .sql_analyser import analyse_sql_statements + +logger = logging.getLogger(__name__) + + +@unique +class MessageType(Enum): + OK = "ok" + IGNORE = "ignore" + WARNING = "warning" + ERROR = "error" + + @staticmethod + + +## ... source file abbreviated to get to RunPython examples ... + + + or (self.exclude_apps and app_label in self.exclude_apps) + or any(isinstance(o, IgnoreMigration) for o in operations) + or ( + self.ignore_name_contains + and self.ignore_name_contains in migration_name + ) + or (migration_name in self.ignore_name) + or ( + self.only_applied_migrations + and (app_label, migration_name) + not in self.migration_loader.applied_migrations + ) + or ( + self.only_unapplied_migrations + and (app_label, migration_name) + in self.migration_loader.applied_migrations + ) + ) + + def analyse_data_migration(self, migration): + errors = [] + ignored = [] + warnings = [] + + for operation in migration.operations: +~~ if isinstance(operation, RunPython): + op_errors, op_ignored, op_warnings = self.lint_runpython(operation) + if op_errors: + errors += op_errors + if op_ignored: + ignored += op_ignored + if op_warnings: + warnings += op_warnings + + return errors, ignored, warnings + + def lint_runpython(self, runpython): + function_name = runpython.code.__name__ + error = [] + ignored = [] + warning = [] + + if not runpython.reversible: + issue = { + "code": "REVERSIBLE_DATA_MIGRATION", + "msg": "'{}': RunPython data migration is not reversible".format( + function_name + ), + } + if issue["code"] in self.exclude_migration_tests: + + +## ... source file continues with no further RunPython examples... + +``` + diff --git a/content/pages/examples/django/django-db-migrations-state-projectstate.markdown b/content/pages/examples/django/django-db-migrations-state-projectstate.markdown new file mode 100644 index 000000000..6ae15a7dd --- /dev/null +++ b/content/pages/examples/django/django-db-migrations-state-projectstate.markdown @@ -0,0 +1,74 @@ +title: django.db.migrations.state ProjectState Example Code +category: page +slug: django-db-migrations-state-projectstate-examples +sortorder: 500011178 +toc: False +sidebartitle: django.db.migrations.state ProjectState +meta: Python example code for the ProjectState class from the django.db.migrations.state module of the Django project. + + +ProjectState is a class within the django.db.migrations.state module of the Django project. + + +## Example 1 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / tests / test_models.py**](https://github.com/jazzband/django-axes/blob/master/axes/tests/test_models.py) + +```python +# test_models.py +from django.apps.registry import apps +from django.db import connection +from django.db.migrations.autodetector import MigrationAutodetector +from django.db.migrations.executor import MigrationExecutor +~~from django.db.migrations.state import ProjectState + +from axes.models import AccessAttempt, AccessLog +from axes.tests.base import AxesTestCase + + +class ModelsTestCase(AxesTestCase): + def setUp(self): + self.failures_since_start = 42 + + self.access_attempt = AccessAttempt( + failures_since_start=self.failures_since_start + ) + self.access_log = AccessLog() + + def test_access_attempt_str(self): + self.assertIn("Access", str(self.access_attempt)) + + def test_access_log_str(self): + self.assertIn("Access", str(self.access_log)) + + +class MigrationsTestCase(AxesTestCase): + def test_missing_migrations(self): + executor = MigrationExecutor(connection) + autodetector = MigrationAutodetector( +~~ executor.loader.project_state(), ProjectState.from_apps(apps) + ) + + changes = autodetector.changes(graph=executor.loader.graph) + + self.assertEqual({}, changes) + + + +## ... source file continues with no further ProjectState examples... + +``` + diff --git a/content/pages/examples/django/django-db-migrations.markdown b/content/pages/examples/django/django-db-migrations.markdown new file mode 100644 index 000000000..9749b1cae --- /dev/null +++ b/content/pages/examples/django/django-db-migrations.markdown @@ -0,0 +1,987 @@ +title: django.db migrations Example Code +category: page +slug: django-db-migrations-examples +sortorder: 500011166 +toc: False +sidebartitle: django.db migrations +meta: Python example code for the migrations callable from the django.db module of the Django project. + + +migrations is a callable within the django.db module of the Django project. + + +## Example 1 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / migrations / 0004_auto_20181024_1538.py**](https://github.com/jazzband/django-axes/blob/master/axes/migrations/0004_auto_20181024_1538.py) + +```python +# 0004_auto_20181024_1538.py +~~from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [("axes", "0003_auto_20160322_0929")] + + operations = [ +~~ migrations.AlterModelOptions( + name="accessattempt", + options={ + "verbose_name": "access attempt", + "verbose_name_plural": "access attempts", + }, + ), +~~ migrations.AlterModelOptions( + name="accesslog", + options={ + "verbose_name": "access log", + "verbose_name_plural": "access logs", + }, + ), +~~ migrations.AlterField( + model_name="accessattempt", + name="attempt_time", + field=models.DateTimeField(auto_now_add=True, verbose_name="Attempt Time"), + ), +~~ migrations.AlterField( + model_name="accessattempt", + name="user_agent", + field=models.CharField( + db_index=True, max_length=255, verbose_name="User Agent" + ), + ), +~~ migrations.AlterField( + model_name="accessattempt", + name="username", + field=models.CharField( + db_index=True, max_length=255, null=True, verbose_name="Username" + ), + ), +~~ migrations.AlterField( + model_name="accesslog", + name="attempt_time", + field=models.DateTimeField(auto_now_add=True, verbose_name="Attempt Time"), + ), +~~ migrations.AlterField( + model_name="accesslog", + name="logout_time", + field=models.DateTimeField( + blank=True, null=True, verbose_name="Logout Time" + ), + ), +~~ migrations.AlterField( + model_name="accesslog", + name="user_agent", + field=models.CharField( + db_index=True, max_length=255, verbose_name="User Agent" + ), + ), +~~ migrations.AlterField( + model_name="accesslog", + name="username", + field=models.CharField( + db_index=True, max_length=255, null=True, verbose_name="Username" + ), + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / migrations / 0008_auto_20150208_2149.py**](https://github.com/divio/django-cms/blob/develop/cms/migrations/0008_auto_20150208_2149.py) + +```python +# 0008_auto_20150208_2149.py +from __future__ import unicode_literals + +~~from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('cms', '0007_auto_20141028_1559'), + ] + + operations = [ +~~ migrations.AlterField( + model_name='title', + name='redirect', + field=models.CharField(max_length=2048, null=True, verbose_name='redirect', blank=True), + preserve_default=True, + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 3 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / migrations / 0006_auto_20160623_1627.py**](https://github.com/divio/django-filer/blob/develop/filer/migrations/0006_auto_20160623_1627.py) + +```python +# 0006_auto_20160623_1627.py +from __future__ import unicode_literals + +import django.db.models.deletion +~~from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('filer', '0005_auto_20160623_1425'), + ] + + operations = [ +~~ migrations.AlterField( + model_name='image', + name='file_ptr', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='%(app_label)s_%(class)s_file', serialize=False, to='filer.File'), + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 4 from django-flexible-subscriptions +[django-flexible-subscriptions](https://github.com/studybuffalo/django-flexible-subscriptions) +([project documentation](https://django-flexible-subscriptions.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-flexible-subscriptions/)) +provides boilerplate code for adding subscription and recurrent billing +to [Django](/django.html) web applications. Various payment providers +can be added on the back end to run the transactions. + +The django-flexible-subscriptions project is open sourced under the +[GNU General Public License v3.0](https://github.com/studybuffalo/django-flexible-subscriptions/blob/master/LICENSE). + +[**django-flexible-subscriptions / subscriptions / migrations / 0006_add_slugs.py**](https://github.com/studybuffalo/django-flexible-subscriptions/blob/master/subscriptions/migrations/0006_add_slugs.py) + +```python +# 0006_add_slugs.py + +~~from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('subscriptions', '0005_update_recurrence_unit_default'), + ] + + operations = [ +~~ migrations.AddField( + model_name='plancost', + name='slug', + field=models.SlugField( + blank=True, + help_text='slug to reference these cost details', + max_length=128, + null=True, + unique=True, + ), + ), +~~ migrations.AddField( + model_name='subscriptionplan', + name='slug', + field=models.SlugField( + blank=True, + help_text='slug to reference the subscription plan', + max_length=128, + null=True, + unique=True, + ), + ), +~~ migrations.AddField( + model_name='planlist', + name='slug', + field=models.SlugField( + blank=True, + help_text='slug to reference the subscription plan list', + max_length=128, + null=True, + unique=True, + ), + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 5 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / migrations / 0001_initial.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/migrations/0001_initial.py) + +```python +# 0001_initial.py +~~from django.db import models, migrations +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0001_initial'), + ('auth', '0001_initial'), +~~ migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ +~~ migrations.CreateModel( + name='GroupObjectPermission', + fields=[ + ('id', models.AutoField(primary_key=True, + serialize=False, auto_created=True, verbose_name='ID')), + ('object_pk', models.CharField( + max_length=255, verbose_name='object ID')), + ('content_type', models.ForeignKey(to='contenttypes.ContentType', on_delete=models.CASCADE)), + ('group', models.ForeignKey(to='auth.Group', on_delete=models.CASCADE)), + ('permission', models.ForeignKey(to='auth.Permission', on_delete=models.CASCADE)), + ], + options={ + }, + bases=(models.Model,), + ), +~~ migrations.CreateModel( + name='UserObjectPermission', + fields=[ + ('id', models.AutoField(primary_key=True, + serialize=False, auto_created=True, verbose_name='ID')), + ('object_pk', models.CharField( + max_length=255, verbose_name='object ID')), + ('content_type', models.ForeignKey(to='contenttypes.ContentType', on_delete=models.CASCADE)), + ('permission', models.ForeignKey(to='auth.Permission', on_delete=models.CASCADE)), + ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), + ], + options={ + }, + bases=(models.Model,), + ), +~~ migrations.AlterUniqueTogether( + name='userobjectpermission', + unique_together={('user', 'permission', 'object_pk')}, + ), +~~ migrations.AlterUniqueTogether( + name='groupobjectpermission', + unique_together={('group', 'permission', 'object_pk')}, + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 6 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / migrations / 0002_delete_userdashboardmodule.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/migrations/0002_delete_userdashboardmodule.py) + +```python +# 0002_delete_userdashboardmodule.py +from __future__ import unicode_literals + +~~from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('jet', '0001_initial'), + ] + + operations = [ +~~ migrations.DeleteModel( + name='UserDashboardModule', + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 7 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / migrations / 0001_initial.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/migrations/0001_initial.py) + +```python +# 0001_initial.py +from django.conf import settings +import django.db.models.deletion +~~from django.db import migrations, models + +import oauth2_provider.generators +import oauth2_provider.validators +from oauth2_provider.settings import oauth2_settings + + +class Migration(migrations.Migration): + dependencies = [ +~~ migrations.swappable_dependency(settings.AUTH_USER_MODEL) + ] + + operations = [ +~~ migrations.CreateModel( + name='Application', + fields=[ + ('id', models.BigAutoField(serialize=False, primary_key=True)), + ('client_id', models.CharField(default=oauth2_provider.generators.generate_client_id, unique=True, max_length=100, db_index=True)), + ('redirect_uris', models.TextField(help_text='Allowed URIs list, space separated', blank=True)), + ('client_type', models.CharField(max_length=32, choices=[('confidential', 'Confidential'), ('public', 'Public')])), + ('authorization_grant_type', models.CharField(max_length=32, choices=[('authorization-code', 'Authorization code'), ('implicit', 'Implicit'), ('password', 'Resource owner password-based'), ('client-credentials', 'Client credentials')])), + ('client_secret', models.CharField(default=oauth2_provider.generators.generate_client_secret, max_length=255, db_index=True, blank=True)), + ('name', models.CharField(max_length=255, blank=True)), + ('user', models.ForeignKey(related_name="oauth2_provider_application", blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)), + ('skip_authorization', models.BooleanField(default=False)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ], + options={ + 'abstract': False, + 'swappable': 'OAUTH2_PROVIDER_APPLICATION_MODEL', + }, + ), +~~ migrations.CreateModel( + name='AccessToken', + fields=[ + ('id', models.BigAutoField(serialize=False, primary_key=True)), + ('token', models.CharField(unique=True, max_length=255)), + ('expires', models.DateTimeField()), + ('scope', models.TextField(blank=True)), + ('application', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=oauth2_settings.APPLICATION_MODEL)), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='oauth2_provider_accesstoken', to=settings.AUTH_USER_MODEL)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ], + options={ + 'abstract': False, + 'swappable': 'OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL', + }, + ), +~~ migrations.CreateModel( + name='Grant', + fields=[ + ('id', models.BigAutoField(serialize=False, primary_key=True)), + ('code', models.CharField(unique=True, max_length=255)), + ('expires', models.DateTimeField()), + ('redirect_uri', models.CharField(max_length=255)), + ('scope', models.TextField(blank=True)), + ('application', models.ForeignKey(to=oauth2_settings.APPLICATION_MODEL, on_delete=models.CASCADE)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='oauth2_provider_grant', to=settings.AUTH_USER_MODEL)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ], + options={ + 'abstract': False, + 'swappable': 'OAUTH2_PROVIDER_GRANT_MODEL', + }, + ), +~~ migrations.CreateModel( + name='RefreshToken', + fields=[ + ('id', models.BigAutoField(serialize=False, primary_key=True)), + ('token', models.CharField(max_length=255)), + ('access_token', models.OneToOneField(blank=True, null=True, related_name="refresh_token", to=oauth2_settings.ACCESS_TOKEN_MODEL, on_delete=models.SET_NULL)), + ('application', models.ForeignKey(to=oauth2_settings.APPLICATION_MODEL, on_delete=models.CASCADE)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='oauth2_provider_refreshtoken', to=settings.AUTH_USER_MODEL)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('revoked', models.DateTimeField(null=True)), + ], + options={ + 'abstract': False, + 'swappable': 'OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL', + 'unique_together': set([("token", "revoked")]), + }, + ), +~~ migrations.AddField( + model_name='AccessToken', + name='source_refresh_token', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=oauth2_settings.REFRESH_TOKEN_MODEL, related_name="refreshed_access_token"), + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 8 from django-push-notifications +[django-push-notifications](https://github.com/jazzband/django-push-notifications) +is a [Django](/django.html) app for storing and interacting with +push notification services such as +[Google's Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/) +and +[Apple Notifications](https://developer.apple.com/notifications/). +The django-push-notification project's source code is available +open source under the +[MIT license](https://github.com/jazzband/django-push-notifications/blob/master/LICENSE). + +[**django-push-notifications / push_notifications / migrations / 0002_auto_20160106_0850.py**](https://github.com/jazzband/django-push-notifications/blob/master/push_notifications/migrations/0002_auto_20160106_0850.py) + +```python +# 0002_auto_20160106_0850.py +~~from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('push_notifications', '0001_initial'), + ] + + operations = [ +~~ migrations.AlterField( + model_name='apnsdevice', + name='registration_id', + field=models.CharField(max_length=200, unique=True, verbose_name='Registration ID'), + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 9 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / migrations / 0001_initial.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/migrations/0001_initial.py) + +```python +# 0001_initial.py +from __future__ import unicode_literals + +~~from django.db import models, migrations +import sitetree.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0001_initial'), + ] + + operations = [ +~~ migrations.CreateModel( + name='Tree', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('title', models.CharField(help_text='Site tree title for presentational purposes.', max_length=100, verbose_name='Title', blank=True)), + ('alias', models.CharField(help_text='Short name to address site tree from templates.
Note: change with care.', unique=True, max_length=80, verbose_name='Alias', db_index=True)), + ], + options={ + 'abstract': False, + 'verbose_name': 'Site Tree', + 'verbose_name_plural': 'Site Trees', + }, + bases=(models.Model,), + ), +~~ migrations.CreateModel( + name='TreeItem', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('title', models.CharField(help_text='Site tree item title. Can contain template variables E.g.: {{ mytitle }}.', max_length=100, verbose_name='Title')), + ('hint', models.CharField(default='', help_text='Some additional information about this item that is used as a hint.', max_length=200, verbose_name='Hint', blank=True)), + ('url', models.CharField(help_text='Exact URL or URL pattern (see "Additional settings") for this item.', max_length=200, verbose_name='URL', db_index=True)), + ('urlaspattern', models.BooleanField(default=False, help_text='Whether the given URL should be treated as a pattern.
Note: Refer to Django "URL dispatcher" documentation (e.g. "Naming URL patterns" part).', db_index=True, verbose_name='URL as Pattern')), + ('hidden', models.BooleanField(default=False, help_text='Whether to show this item in navigation.', db_index=True, verbose_name='Hidden')), + ('alias', sitetree.models.CharFieldNullable(max_length=80, blank=True, help_text='Short name to address site tree item from a template.
Reserved aliases: "trunk", "this-children", "this-siblings", "this-ancestor-children", "this-parent-siblings".', null=True, verbose_name='Alias', db_index=True)), + ('description', models.TextField(default='', help_text='Additional comments on this item.', verbose_name='Description', blank=True)), + ('inmenu', models.BooleanField(default=True, help_text='Whether to show this item in a menu.', db_index=True, verbose_name='Show in menu')), + ('inbreadcrumbs', models.BooleanField(default=True, help_text='Whether to show this item in a breadcrumb path.', db_index=True, verbose_name='Show in breadcrumb path')), + ('insitetree', models.BooleanField(default=True, help_text='Whether to show this item in a site tree.', db_index=True, verbose_name='Show in site tree')), + ('access_loggedin', models.BooleanField(default=False, help_text='Check it to grant access to this item to authenticated users only.', db_index=True, verbose_name='Logged in only')), + ('access_guest', models.BooleanField(default=False, help_text='Check it to grant access to this item to guests only.', db_index=True, verbose_name='Guests only')), + ('access_restricted', models.BooleanField(default=False, help_text='Check it to restrict user access to this item, using Django permissions system.', db_index=True, verbose_name='Restrict access to permissions')), + ('access_perm_type', models.IntegerField(default=1, help_text='Any — user should have any of chosen permissions. All — user should have all chosen permissions.', verbose_name='Permissions interpretation', choices=[(1, 'Any'), (2, 'All')])), + ('sort_order', models.IntegerField(default=0, help_text='Item position among other site tree items under the same parent.', verbose_name='Sort order', db_index=True)), + ('access_permissions', models.ManyToManyField(to='auth.Permission', verbose_name='Permissions granting access', blank=True)), + ('parent', models.ForeignKey(related_name='treeitem_parent', on_delete=models.CASCADE, blank=True, to='sitetree.TreeItem', help_text='Parent site tree item.', null=True, verbose_name='Parent')), + ('tree', models.ForeignKey(related_name='treeitem_tree', on_delete=models.CASCADE, verbose_name='Site Tree', to='sitetree.Tree', help_text='Site tree this item belongs to.')), + ], + options={ + 'abstract': False, + 'verbose_name': 'Site Tree Item', + 'verbose_name_plural': 'Site Tree Items', + }, + bases=(models.Model,), + ), +~~ migrations.AlterUniqueTogether( + name='treeitem', + unique_together=set([('tree', 'alias')]), + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 10 from django-smithy +[django-smithy](https://github.com/jamiecounsell/django-smithy) is +a [Django](/django.html) code library that allows users to send +HTTP requests from the Django admin user interface. The code for +the project is open source under the +[MIT license](https://github.com/jamiecounsell/django-smithy/blob/master/LICENSE). + +[**django-smithy / smithy / migrations / 0004_auto_20190721_2012.py**](https://github.com/jamiecounsell/django-smithy/blob/master/smithy/migrations/0004_auto_20190721_2012.py) + +```python +# 0004_auto_20190721_2012.py + +~~from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('smithy', '0003_auto_20190721_2004'), + ] + + operations = [ +~~ migrations.AlterField( + model_name='bodyparameter', + name='value', + field=models.TextField(blank=True), + ), +~~ migrations.AlterField( + model_name='cookie', + name='value', + field=models.TextField(blank=True), + ), +~~ migrations.AlterField( + model_name='header', + name='value', + field=models.TextField(blank=True), + ), +~~ migrations.AlterField( + model_name='queryparameter', + name='value', + field=models.TextField(blank=True), + ), +~~ migrations.AlterField( + model_name='variable', + name='value', + field=models.TextField(blank=True), + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 11 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / migrations / 0002_auto_20150501_1515.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/migrations/0002_auto_20150501_1515.py) + +```python +# 0002_auto_20150501_1515.py +from __future__ import unicode_literals + +~~from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('explorer', '0001_initial'), + ] + + operations = [ +~~ migrations.RemoveField( + model_name='querylog', + name='is_playground', + ), +~~ migrations.AlterField( + model_name='querylog', + name='sql', + field=models.TextField(null=True, blank=True), + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 12 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / migrations / 0002_auto_20150616_2121.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/migrations/0002_auto_20150616_2121.py) + +```python +# 0002_auto_20150616_2121.py +~~from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [("taggit", "0001_initial")] + + operations = [ +~~ migrations.AlterIndexTogether( + name="taggeditem", index_together={("content_type", "object_id")} + ) + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 13 from django-user-visit +[django-user-visit](https://github.com/yunojuno/django-user-visit) +([PyPI package information](https://pypi.org/project/django-user-visit/)) +is a [Django](/django.html) app and +[middleware](https://docs.djangoproject.com/en/stable/topics/http/middleware/) +for tracking daily user visits to your web application. The goal +is to record per user per day instead of for every request a user +sends to the application. The project is provided as open source +under the +[MIT license](https://github.com/yunojuno/django-user-visit/blob/master/LICENSE). + +[**django-user-visit / user_visit / migrations / 0002_add_created_at.py**](https://github.com/yunojuno/django-user-visit/blob/master/user_visit/migrations/0002_add_created_at.py) + +```python +# 0002_add_created_at.py +import django.utils.timezone +~~from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("user_visit", "0001_initial"), + ] + + operations = [ +~~ migrations.AlterModelOptions( + name="uservisit", options={"get_latest_by": "timestamp"}, + ), +~~ migrations.AddField( + model_name="uservisit", + name="created_at", + field=models.DateTimeField( + auto_now_add=True, + default=django.utils.timezone.now, + help_text=( + "The time at which the database record was created (!=timestamp)" + ), + ), + preserve_default=False, + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 14 from django-webshell +[django-webshell](https://github.com/onrik/django-webshell) is an extension +for executing arbitrary code in the +[Django admin](https://docs.djangoproject.com/en/stable/ref/contrib/admin/), +similar to how you can run code by using the `django manage.py shell` +command from the terminal. + +The django-webshell project is provided as open source under the +[MIT license](https://github.com/onrik/django-webshell/blob/master/LICENSE). + +[**django-webshell / webshell / migrations / 0001_initial.py**](https://github.com/onrik/django-webshell/blob/master/webshell/migrations/0001_initial.py) + +```python +# 0001_initial.py +from __future__ import unicode_literals + +~~from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ +~~ migrations.CreateModel( + name='Script', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('name', models.CharField(max_length=100, verbose_name='Name')), + ('source', models.TextField(verbose_name='Source')), + ], + options={ + 'verbose_name': 'Script', + 'verbose_name_plural': 'Scripts', + }, + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 15 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / migrations / 0002_urlpath_moved_to.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/migrations/0002_urlpath_moved_to.py) + +```python +# 0002_urlpath_moved_to.py +import django.db.models.deletion +import mptt.fields +~~from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("wiki", "0001_initial"), + ] + + operations = [ +~~ migrations.AddField( + model_name="urlpath", + name="moved_to", + field=mptt.fields.TreeForeignKey( + blank=True, + help_text="Article path was moved to this location", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="moved_from", + to="wiki.URLPath", + verbose_name="Moved to", + ), + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 16 from dmd-interpreter +[dmd-interpreter](https://github.com/mitchalexbailey/dmd-interpreter) +([running web app](http://www.dmd.nl/DOVE)) +is a Python tool to aggregate clinically relevant information related +to variants in the DMD gene and display that [data](/data.html) to a user +with a [Django](/django.html) web application. + +[**dmd-interpreter / interpreter / migrations / 0001_initial.py**](https://github.com/mitchalexbailey/dmd-interpreter/blob/master/interpreter/migrations/0001_initial.py) + +```python +# 0001_initial.py +from __future__ import unicode_literals + +~~from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ +~~ migrations.CreateModel( + name='Choice', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('choice_text', models.CharField(max_length=200)), + ('votes', models.IntegerField(default=0)), + ], + ), +~~ migrations.CreateModel( + name='Question', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('question_text', models.CharField(max_length=200)), + ('pub_date', models.DateTimeField(verbose_name=b'Date Published')), + ], + ), +~~ migrations.AddField( + model_name='choice', + name='question', + field=models.ForeignKey(to='interpreter.Question'), + ), + ] + + + +## ... source file continues with no further migrations examples... + +``` + + +## Example 17 from elasticsearch-django +[elasticsearch-django](https://github.com/yunojuno/elasticsearch-django) +([PyPI package information](https://pypi.org/project/elasticsearch-django/)) +is a [Django](/django.html) app for managing +[ElasticSearch](https://github.com/elastic/elasticsearch) indexes +populated by [Django ORM](/django-orm.html) models. The project is +available as open source under the +[MIT license](https://github.com/yunojuno/elasticsearch-django/blob/master/LICENSE). + +[**elasticsearch-django / elasticsearch_django / migrations / 0009_searchquery_query_type.py**](https://github.com/yunojuno/elasticsearch-django/blob/master/elasticsearch_django/migrations/0009_searchquery_query_type.py) + +```python +# 0009_searchquery_query_type.py + +~~from django.db import migrations, models + +from ..models import SearchQuery + + +class Migration(migrations.Migration): + + dependencies = [("elasticsearch_django", "0008_searchquery_search_terms")] + + operations = [ +~~ migrations.AddField( + model_name="searchquery", + name="query_type", + field=models.CharField( + choices=(lambda: SearchQuery.QUERY_TYPE_CHOICES)(), + default="SEARCH", + help_text="Does this query return results, or just the hit count?", + max_length=10, + ), + ) + ] + + + +## ... source file continues with no further migrations examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-query-baseiterable.markdown b/content/pages/examples/django/django-db-models-query-baseiterable.markdown new file mode 100644 index 000000000..5271e2e6e --- /dev/null +++ b/content/pages/examples/django/django-db-models-query-baseiterable.markdown @@ -0,0 +1,101 @@ +title: django.db.models.query BaseIterable Example Code +category: page +slug: django-db-models-query-baseiterable-examples +sortorder: 500011238 +toc: False +sidebartitle: django.db.models.query BaseIterable +meta: Python example code for the BaseIterable class from the django.db.models.query module of the Django project. + + +BaseIterable is a class within the django.db.models.query module of the Django project. + + +## Example 1 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / query.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/query.py) + +```python +# query.py +import posixpath +import warnings +from collections import defaultdict + +from django.apps import apps +from django.contrib.contenttypes.models import ContentType +from django.db.models import CharField, Q +from django.db.models.functions import Length, Substr +~~from django.db.models.query import BaseIterable +from treebeard.mp_tree import MP_NodeQuerySet + +from wagtail.search.queryset import SearchableQuerySetMixin + + +class TreeQuerySet(MP_NodeQuerySet): + def delete(self): + super().delete() + + delete.queryset_only = True + + def descendant_of_q(self, other, inclusive=False): + q = Q(path__startswith=other.path) & Q(depth__gte=other.depth) + + if not inclusive: + q &= -Q(pk=other.pk) + + return q + + def descendant_of(self, other, inclusive=False): + return self.filter(self.descendant_of_q(other, inclusive)) + + def not_descendant_of(self, other, inclusive=False): + return self.exclude(self.descendant_of_q(other, inclusive)) + + +## ... source file abbreviated to get to BaseIterable examples ... + + + + if missing_pks: + generic_pages = Page.objects.filter(pk__in=missing_pks).select_related('content_type').in_bulk() + warnings.warn( + "Specific versions of the following pages could not be found. " + "This is most likely because a database migration has removed " + "the relevant table or record since the page was created:\n{}".format([ + {'id': p.id, 'title': p.title, 'type': p.content_type} + for p in generic_pages.values() + ]), category=RuntimeWarning + ) + else: + generic_pages = {} + + for pk, content_type in pks_and_types: + try: + page = pages_by_type[content_type][pk] + except KeyError: + page = generic_pages[pk] + if annotation_aliases: + for annotation, value in annotations_by_pk.get(page.pk, {}).items(): + setattr(page, annotation, value) + yield page + + +~~class SpecificIterable(BaseIterable): + def __iter__(self): + return specific_iterator(self.queryset) + + +~~class DeferredSpecificIterable(BaseIterable): + def __iter__(self): + return specific_iterator(self.queryset, defer=True) + + + +## ... source file continues with no further BaseIterable examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-query-emptyqueryset.markdown b/content/pages/examples/django/django-db-models-query-emptyqueryset.markdown new file mode 100644 index 000000000..aa5c5ea3a --- /dev/null +++ b/content/pages/examples/django/django-db-models-query-emptyqueryset.markdown @@ -0,0 +1,195 @@ +title: django.db.models.query EmptyQuerySet Example Code +category: page +slug: django-db-models-query-emptyqueryset-examples +sortorder: 500011239 +toc: False +sidebartitle: django.db.models.query EmptyQuerySet +meta: Python example code for the EmptyQuerySet class from the django.db.models.query module of the Django project. + + +EmptyQuerySet is a class within the django.db.models.query module of the Django project. + + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / managers.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./managers.py) + +```python +# managers.py +from django.db import models +from django.db.models import Count +from django.db.models import Q +~~from django.db.models.query import EmptyQuerySet +from django.db.models.query import QuerySet +from mptt.managers import TreeManager + + +class ArticleQuerySet(QuerySet): + def can_read(self, user): + if user.has_perm("wiki.moderator"): + return self + if user.is_anonymous: + q = self.filter(other_read=True) + else: + q = self.filter( + Q(other_read=True) + | Q(owner=user) + | (Q(group__user=user) & Q(group_read=True)) + ).annotate(Count("id")) + return q + + def can_write(self, user): + if user.has_perm("wiki.moderator"): + return self + if user.is_anonymous: + q = self.filter(other_write=True) + else: + q = self.filter( + Q(other_write=True) + | Q(owner=user) + | (Q(group__user=user) & Q(group_write=True)) + ) + return q + + def active(self): + return self.filter(current_revision__deleted=False) + + +~~class ArticleEmptyQuerySet(EmptyQuerySet): + def can_read(self, user): + return self + + def can_write(self, user): + return self + + def active(self): + return self + + +class ArticleFkQuerySetMixin: + def can_read(self, user): + if user.has_perm("wiki.moderate"): + return self + if user.is_anonymous: + q = self.filter(article__other_read=True) + else: + q = self.filter( + Q(article__other_read=True) + | Q(article__owner=user) + | (Q(article__group__user=user) & Q(article__group_read=True)) + ).annotate(Count("id")) + return q + + + +## ... source file abbreviated to get to EmptyQuerySet examples ... + + + + def can_read(self, user): + return self.get_queryset().can_read(user) + + def can_write(self, user): + return self.get_queryset().can_write(user) + + +class ArticleFkManager(models.Manager): + def get_empty_query_set(self): + return self.get_queryset().none() + + def get_queryset(self): + return ArticleFkQuerySet(self.model, using=self._db) + + def active(self): + return self.get_queryset().active() + + def can_read(self, user): + return self.get_queryset().can_read(user) + + def can_write(self, user): + return self.get_queryset().can_write(user) + + +~~class URLPathEmptyQuerySet(EmptyQuerySet, ArticleFkEmptyQuerySetMixin): + def select_related_common(self): + return self + + def default_order(self): + return self + + +class URLPathQuerySet(QuerySet, ArticleFkQuerySetMixin): + def select_related_common(self): + return self.select_related( + "parent", "article__current_revision", "article__owner" + ) + + def default_order(self): + return self.order_by("article__current_revision__title") + + +class URLPathManager(TreeManager): + def get_empty_query_set(self): + return self.get_queryset().none() + + def get_queryset(self): + return URLPathQuerySet(self.model, using=self._db).order_by( + self.tree_id_attr, self.left_attr + Q(article__other_write=True) + | Q(article__owner=user) + | (Q(article__group__user=user) & Q(article__group_write=True)) + ).annotate(Count("id")) + return q + + def active(self): + return self.filter(article__current_revision__deleted=False) + + +class ArticleFkEmptyQuerySetMixin: + def can_read(self, user): + return self + + def can_write(self, user): + return self + + def active(self): + return self + + +class ArticleFkQuerySet(ArticleFkQuerySetMixin, QuerySet): + pass + + +~~class ArticleFkEmptyQuerySet(ArticleFkEmptyQuerySetMixin, EmptyQuerySet): + pass + + +class ArticleManager(models.Manager): + def get_empty_query_set(self): + return self.get_queryset().none() + + def get_queryset(self): + return ArticleQuerySet(self.model, using=self._db) + + def active(self): + return self.get_queryset().active() + + +## ... source file continues with no further EmptyQuerySet examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-query-modeliterable.markdown b/content/pages/examples/django/django-db-models-query-modeliterable.markdown new file mode 100644 index 000000000..7f203b449 --- /dev/null +++ b/content/pages/examples/django/django-db-models-query-modeliterable.markdown @@ -0,0 +1,72 @@ +title: django.db.models.query ModelIterable Example Code +category: page +slug: django-db-models-query-modeliterable-examples +sortorder: 500011240 +toc: False +sidebartitle: django.db.models.query ModelIterable +meta: Python example code for the ModelIterable class from the django.db.models.query module of the Django project. + + +ModelIterable is a class within the django.db.models.query module of the Django project. + + +## Example 1 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / managers.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./managers.py) + +```python +# managers.py +import django +from django.core.exceptions import ObjectDoesNotExist +from django.db import connection +from django.db import models +from django.db.models.constants import LOOKUP_SEP +from django.db.models.fields.related import OneToOneField, OneToOneRel +~~from django.db.models.query import ModelIterable +from django.db.models.query import QuerySet +from django.db.models.sql.datastructures import Join + + +~~class InheritanceIterable(ModelIterable): + def __iter__(self): + queryset = self.queryset +~~ iter = ModelIterable(queryset) + if getattr(queryset, 'subclasses', False): + extras = tuple(queryset.query.extra.keys()) + subclasses = sorted(queryset.subclasses, key=len, reverse=True) + for obj in iter: + sub_obj = None + for s in subclasses: + sub_obj = queryset._get_sub_obj_recurse(obj, s) + if sub_obj: + break + if not sub_obj: + sub_obj = obj + + if getattr(queryset, '_annotated', False): + for k in queryset._annotated: + setattr(sub_obj, k, getattr(obj, k)) + + for k in extras: + setattr(sub_obj, k, getattr(obj, k)) + + yield sub_obj + else: + yield from iter + + + + +## ... source file continues with no further ModelIterable examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-query-prefetch-related-objects.markdown b/content/pages/examples/django/django-db-models-query-prefetch-related-objects.markdown new file mode 100644 index 000000000..0aaefd46f --- /dev/null +++ b/content/pages/examples/django/django-db-models-query-prefetch-related-objects.markdown @@ -0,0 +1,110 @@ +title: django.db.models.query prefetch_related_objects Example Code +category: page +slug: django-db-models-query-prefetch-related-objects-examples +sortorder: 500011244 +toc: False +sidebartitle: django.db.models.query prefetch_related_objects +meta: Python example code for the prefetch_related_objects callable from the django.db.models.query module of the Django project. + + +prefetch_related_objects is a callable within the django.db.models.query module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / cms_menus.py**](https://github.com/divio/django-cms/blob/develop/cms/./cms_menus.py) + +```python +# cms_menus.py +~~from django.db.models.query import Prefetch, prefetch_related_objects +from django.urls import reverse +from django.utils.functional import SimpleLazyObject +from django.utils.translation import override as force_language + +from cms import constants +from cms.api import get_page_draft +from cms.apphook_pool import apphook_pool +from cms.models import EmptyTitle +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import ( + get_fallback_languages, + get_public_languages, + hide_untranslated, + is_valid_site_language, +) +from cms.utils.permissions import get_view_restrictions +from cms.utils.page import get_page_queryset +from cms.utils.page_permissions import user_can_view_all_pages + +from menus.base import Menu, NavigationNode, Modifier +from menus.menu_pool import menu_pool + + +def get_visible_nodes(request, pages, site): + + +## ... source file abbreviated to get to prefetch_related_objects examples ... + + + .distinct() + ) + + if not self.renderer.draft_mode_active: + pages = pages.select_related('publisher_public__node') + pages = get_visible_nodes(request, pages, site) + + if not pages: + return [] + + try: + homepage = [page for page in pages if page.is_home][0] + except IndexError: + homepage = None + + titles = Title.objects.filter( + language__in=languages, + publisher_is_draft=self.renderer.draft_mode_active, + ) + + lookup = Prefetch( + 'title_set', + to_attr='filtered_translations', + queryset=titles, + ) +~~ prefetch_related_objects(pages, lookup) + blank_title_cache = {language: EmptyTitle(language=language) for language in languages} + + if lang not in blank_title_cache: + blank_title_cache[lang] = EmptyTitle(language=lang) + + node_id_to_page = {} + + def _page_to_node(page): + page.title_cache = blank_title_cache.copy() + + for trans in page.filtered_translations: + page.title_cache[trans.language] = trans + menu_node = get_menu_node_for_page( + self.renderer, + page, + language=lang, + fallbacks=fallbacks, + ) + return menu_node + + menu_nodes = [] + + for page in pages: + node = page.node + + +## ... source file continues with no further prefetch_related_objects examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-query-prefetch.markdown b/content/pages/examples/django/django-db-models-query-prefetch.markdown new file mode 100644 index 000000000..cc8bd2e08 --- /dev/null +++ b/content/pages/examples/django/django-db-models-query-prefetch.markdown @@ -0,0 +1,110 @@ +title: django.db.models.query Prefetch Example Code +category: page +slug: django-db-models-query-prefetch-examples +sortorder: 500011241 +toc: False +sidebartitle: django.db.models.query Prefetch +meta: Python example code for the Prefetch class from the django.db.models.query module of the Django project. + + +Prefetch is a class within the django.db.models.query module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / cms_menus.py**](https://github.com/divio/django-cms/blob/develop/cms/./cms_menus.py) + +```python +# cms_menus.py +~~from django.db.models.query import Prefetch, prefetch_related_objects +from django.urls import reverse +from django.utils.functional import SimpleLazyObject +from django.utils.translation import override as force_language + +from cms import constants +from cms.api import get_page_draft +from cms.apphook_pool import apphook_pool +from cms.models import EmptyTitle +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import ( + get_fallback_languages, + get_public_languages, + hide_untranslated, + is_valid_site_language, +) +from cms.utils.permissions import get_view_restrictions +from cms.utils.page import get_page_queryset +from cms.utils.page_permissions import user_can_view_all_pages + +from menus.base import Menu, NavigationNode, Modifier +from menus.menu_pool import menu_pool + + +def get_visible_nodes(request, pages, site): + + +## ... source file abbreviated to get to Prefetch examples ... + + + pages = ( + pages + .filter(title_set__language__in=languages) + .select_related('node') + .order_by('node__path') + .distinct() + ) + + if not self.renderer.draft_mode_active: + pages = pages.select_related('publisher_public__node') + pages = get_visible_nodes(request, pages, site) + + if not pages: + return [] + + try: + homepage = [page for page in pages if page.is_home][0] + except IndexError: + homepage = None + + titles = Title.objects.filter( + language__in=languages, + publisher_is_draft=self.renderer.draft_mode_active, + ) + +~~ lookup = Prefetch( + 'title_set', + to_attr='filtered_translations', + queryset=titles, + ) + prefetch_related_objects(pages, lookup) + blank_title_cache = {language: EmptyTitle(language=language) for language in languages} + + if lang not in blank_title_cache: + blank_title_cache[lang] = EmptyTitle(language=lang) + + node_id_to_page = {} + + def _page_to_node(page): + page.title_cache = blank_title_cache.copy() + + for trans in page.filtered_translations: + page.title_cache[trans.language] = trans + menu_node = get_menu_node_for_page( + self.renderer, + page, + language=lang, + fallbacks=fallbacks, + ) + return menu_node + + +## ... source file continues with no further Prefetch examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-query-q.markdown b/content/pages/examples/django/django-db-models-query-q.markdown new file mode 100644 index 000000000..2ba3f36e3 --- /dev/null +++ b/content/pages/examples/django/django-db-models-query-q.markdown @@ -0,0 +1,136 @@ +title: django.db.models.query Q Example Code +category: page +slug: django-db-models-query-q-examples +sortorder: 500011242 +toc: False +sidebartitle: django.db.models.query Q +meta: Python example code for the Q constant from the django.db.models.query module of the Django project. + + +Q is a constant within the django.db.models.query module of the Django project. + + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / managers.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./managers.py) + +```python +# managers.py +from django.db import models +from django.db.models import Count +from django.db.models import Q +from django.db.models.query import EmptyQuerySet +~~from django.db.models.query import QuerySet +from mptt.managers import TreeManager + + +class ArticleQuerySet(QuerySet): + def can_read(self, user): + if user.has_perm("wiki.moderator"): + return self + if user.is_anonymous: + q = self.filter(other_read=True) + else: + q = self.filter( +~~ Q(other_read=True) +~~ | Q(owner=user) +~~ | (Q(group__user=user) & Q(group_read=True)) + ).annotate(Count("id")) + return q + + def can_write(self, user): + if user.has_perm("wiki.moderator"): + return self + if user.is_anonymous: + q = self.filter(other_write=True) + else: + q = self.filter( +~~ Q(other_write=True) +~~ | Q(owner=user) +~~ | (Q(group__user=user) & Q(group_write=True)) + ) + return q + + def active(self): + return self.filter(current_revision__deleted=False) + + +class ArticleEmptyQuerySet(EmptyQuerySet): + def can_read(self, user): + return self + + def can_write(self, user): + return self + + def active(self): + return self + + +class ArticleFkQuerySetMixin: + def can_read(self, user): + if user.has_perm("wiki.moderate"): + return self + if user.is_anonymous: + q = self.filter(article__other_read=True) + else: + q = self.filter( +~~ Q(article__other_read=True) +~~ | Q(article__owner=user) +~~ | (Q(article__group__user=user) & Q(article__group_read=True)) + ).annotate(Count("id")) + return q + + def can_write(self, user): + if user.has_perm("wiki.moderate"): + return self + if user.is_anonymous: + q = self.filter(article__other_write=True) + else: + q = self.filter( +~~ Q(article__other_write=True) +~~ | Q(article__owner=user) +~~ | (Q(article__group__user=user) & Q(article__group_write=True)) + ).annotate(Count("id")) + return q + + def active(self): + return self.filter(article__current_revision__deleted=False) + + +class ArticleFkEmptyQuerySetMixin: + def can_read(self, user): + return self + + def can_write(self, user): + return self + + def active(self): + return self + + +class ArticleFkQuerySet(ArticleFkQuerySetMixin, QuerySet): + pass + + +class ArticleFkEmptyQuerySet(ArticleFkEmptyQuerySetMixin, EmptyQuerySet): + pass + + +## ... source file continues with no further Q examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-query-queryset.markdown b/content/pages/examples/django/django-db-models-query-queryset.markdown new file mode 100644 index 000000000..fcc29c3fc --- /dev/null +++ b/content/pages/examples/django/django-db-models-query-queryset.markdown @@ -0,0 +1,900 @@ +title: django.db.models.query QuerySet Example Code +category: page +slug: django-db-models-query-queryset-examples +sortorder: 500011243 +toc: False +sidebartitle: django.db.models.query QuerySet +meta: Python example code for the QuerySet class from the django.db.models.query module of the Django project. + + +QuerySet is a class within the django.db.models.query module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / publisher / query.py**](https://github.com/divio/django-cms/blob/develop/cms/publisher/query.py) + +```python +# query.py +~~from django.db.models.query import QuerySet + + +~~class PublisherQuerySet(QuerySet): + def drafts(self): + return self.filter(publisher_is_draft=True) + + def public(self): + return self.filter(publisher_is_draft=False) + + + +## ... source file continues with no further QuerySet examples... + +``` + + +## Example 2 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / admin / __init__.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/admin/__init__.py) + +```python +# __init__.py +import six +import operator +from functools import update_wrapper +from six.moves import reduce +from typing import Tuple, Dict, Callable # NOQA + +from django.apps import apps +from django.http import HttpResponse, HttpResponseNotFound +from django.conf import settings +from django.db import models +~~from django.db.models.query import QuerySet +from django.utils.encoding import smart_str +from django.utils.translation import gettext as _ +from django.utils.text import get_text_list +from django.contrib import admin + +from django_extensions.admin.widgets import ForeignKeySearchInput + + +class ForeignKeyAutocompleteAdminMixin: + + related_search_fields = {} # type: Dict[str, Tuple[str]] + related_string_functions = {} # type: Dict[str, Callable] + autocomplete_limit = getattr(settings, 'FOREIGNKEY_AUTOCOMPLETE_LIMIT', None) + + def get_urls(self): + from django.urls import path + + def wrap(view): + def wrapper(*args, **kwargs): + return self.admin_site.admin_view(view)(*args, **kwargs) + return update_wrapper(wrapper, view) + + return [ + path('foreignkey_autocomplete/', wrap(self.foreignkey_autocomplete), + + +## ... source file abbreviated to get to QuerySet examples ... + + + object_pk = request.GET.get('object_pk', None) + + try: + to_string_function = self.related_string_functions[model_name] + except KeyError: + to_string_function = lambda x: x.__str__() + + if search_fields and app_label and model_name and (query or object_pk): + def construct_search(field_name): + if field_name.startswith('^'): + return "%s__istartswith" % field_name[1:] + elif field_name.startswith('='): + return "%s__iexact" % field_name[1:] + elif field_name.startswith('@'): + return "%s__search" % field_name[1:] + else: + return "%s__icontains" % field_name + + model = apps.get_model(app_label, model_name) + + queryset = model._default_manager.all() + data = '' + if query: + for bit in query.split(): + or_queries = [models.Q(**{construct_search(smart_str(field_name)): smart_str(bit)}) for field_name in search_fields.split(',')] +~~ other_qs = QuerySet(model) + other_qs.query.select_related = queryset.query.select_related + other_qs = other_qs.filter(reduce(operator.or_, or_queries)) + queryset = queryset & other_qs + + additional_filter = self.get_related_filter(model, request) + if additional_filter: + queryset = queryset.filter(additional_filter) + + if self.autocomplete_limit: + queryset = queryset[:self.autocomplete_limit] + + data = ''.join([six.u('%s|%s\n') % (to_string_function(f), f.pk) for f in queryset]) + elif object_pk: + try: + obj = queryset.get(pk=object_pk) + except Exception: # FIXME: use stricter exception checking + pass + else: + data = to_string_function(obj) + return HttpResponse(data, content_type='text/plain') + return HttpResponseNotFound() + + def get_related_filter(self, model, request): + return None + + +## ... source file continues with no further QuerySet examples... + +``` + + +## Example 3 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / core.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./core.py) + +```python +# core.py +from itertools import chain + +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Permission +~~from django.db.models.query import QuerySet +from django.utils.encoding import force_str + +from guardian.conf import settings as guardian_settings +from guardian.ctypes import get_content_type +from guardian.utils import get_group_obj_perms_model, get_identity, get_user_obj_perms_model + + +def _get_pks_model_and_ctype(objects): + +~~ if isinstance(objects, QuerySet): + model = objects.model + pks = [force_str(pk) for pk in objects.values_list('pk', flat=True)] + ctype = get_content_type(model) + else: + pks = [] + for idx, obj in enumerate(objects): + if not idx: + model = type(obj) + ctype = get_content_type(model) + pks.append(force_str(obj.pk)) + + return pks, model, ctype + + +class ObjectPermissionChecker: + + def __init__(self, user_or_group=None): + self.user, self.group = get_identity(user_or_group) + self._obj_perms_cache = {} + + def has_perm(self, perm, obj): + if self.user and not self.user.is_active: + return False + elif self.user and self.user.is_superuser: + + +## ... source file continues with no further QuerySet examples... + +``` + + +## Example 4 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / resources.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./resources.py) + +```python +# resources.py +import functools +import logging +import tablib +import traceback +from collections import OrderedDict +from copy import deepcopy + +from diff_match_patch import diff_match_patch + +import django +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.core.management.color import no_style +from django.core.paginator import Paginator +from django.db import DEFAULT_DB_ALIAS, connections +from django.db.models.fields.related import ForeignObjectRel +~~from django.db.models.query import QuerySet +from django.db.transaction import ( + TransactionManagementError, + atomic, + savepoint, + savepoint_commit, + savepoint_rollback +) +from django.utils.encoding import force_str +from django.utils.safestring import mark_safe + +from . import widgets +from .fields import Field +from .instance_loaders import ModelInstanceLoader +from .results import Error, Result, RowResult +from .utils import atomic_if_using_transaction + +if django.VERSION[0] >= 3: + from django.core.exceptions import FieldDoesNotExist +else: + from django.db.models.fields import FieldDoesNotExist + + +logger = logging.getLogger(__name__) +logger.addHandler(logging.NullHandler()) + + +## ... source file abbreviated to get to QuerySet examples ... + + + method = getattr(self, 'dehydrate_%s' % field_name, None) + if method is not None: + return method(obj) + return field.export(obj) + + def get_export_fields(self): + return self.get_fields() + + def export_resource(self, obj): + return [self.export_field(field, obj) for field in self.get_export_fields()] + + def get_export_headers(self): + headers = [ + force_str(field.column_name) for field in self.get_export_fields()] + return headers + + def get_user_visible_headers(self): + headers = [ + force_str(field.column_name) for field in self.get_user_visible_fields()] + return headers + + def get_user_visible_fields(self): + return self.get_fields() + + def iter_queryset(self, queryset): +~~ if not isinstance(queryset, QuerySet): + yield from queryset + elif queryset._prefetch_related_lookups: + if not queryset.query.order_by: + queryset = queryset.order_by('pk') + paginator = Paginator(queryset, self.get_chunk_size()) + for index in range(paginator.num_pages): + yield from paginator.get_page(index + 1) + else: + yield from queryset.iterator(chunk_size=self.get_chunk_size()) + + def export(self, queryset=None, *args, **kwargs): + + self.before_export(queryset, *args, **kwargs) + + if queryset is None: + queryset = self.get_queryset() + headers = self.get_export_headers() + data = tablib.Dataset(headers=headers) + + for obj in self.iter_queryset(queryset): + data.append(self.export_resource(obj)) + + self.after_export(queryset, data, *args, **kwargs) + + + +## ... source file continues with no further QuerySet examples... + +``` + + +## Example 5 from django-jsonfield +[django-jsonfield](https://github.com/dmkoch/django-jsonfield) +([jsonfield on PyPi](https://pypi.org/project/jsonfield/)) is a +[Django](/django.html) code library that makes it easier to store validated +JSON in a [Django object-relational mapper (ORM)](/django-orm.html) database +model. + +The django-jsonfield project is open source under the +[MIT license](https://github.com/dmkoch/django-jsonfield/blob/master/LICENSE). + +[**django-jsonfield / src/jsonfield / encoder.py**](https://github.com/dmkoch/django-jsonfield/blob/master/src/jsonfield/./encoder.py) + +```python +# encoder.py +import datetime +import decimal +import json +import uuid + +~~from django.db.models.query import QuerySet +from django.utils import timezone +from django.utils.encoding import force_str +from django.utils.functional import Promise + + +class JSONEncoder(json.JSONEncoder): + def default(self, obj): # noqa: C901 + if isinstance(obj, Promise): + return force_str(obj) + elif isinstance(obj, datetime.datetime): + representation = obj.isoformat() + if representation.endswith('+00:00'): + representation = representation[:-6] + 'Z' + return representation + elif isinstance(obj, datetime.date): + return obj.isoformat() + elif isinstance(obj, datetime.time): + if timezone and timezone.is_aware(obj): + raise ValueError("JSON can't represent timezone-aware times.") + representation = obj.isoformat() + return representation + elif isinstance(obj, datetime.timedelta): + return str(obj.total_seconds()) + elif isinstance(obj, decimal.Decimal): + return float(obj) + elif isinstance(obj, uuid.UUID): + return str(obj) +~~ elif isinstance(obj, QuerySet): + return tuple(obj) + elif isinstance(obj, bytes): + return obj.decode() + elif hasattr(obj, 'tolist'): + return obj.tolist() + elif hasattr(obj, '__getitem__'): + cls = (list if isinstance(obj, (list, tuple)) else dict) + try: + return cls(obj) + except Exception: + pass + elif hasattr(obj, '__iter__'): + return tuple(item for item in obj) + return super().default(obj) + + + +## ... source file continues with no further QuerySet examples... + +``` + + +## Example 6 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / managers.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./managers.py) + +```python +# managers.py +import django +from django.core.exceptions import ObjectDoesNotExist +from django.db import connection +from django.db import models +from django.db.models.constants import LOOKUP_SEP +from django.db.models.fields.related import OneToOneField, OneToOneRel +from django.db.models.query import ModelIterable +~~from django.db.models.query import QuerySet +from django.db.models.sql.datastructures import Join + + +class InheritanceIterable(ModelIterable): + def __iter__(self): + queryset = self.queryset + iter = ModelIterable(queryset) + if getattr(queryset, 'subclasses', False): + extras = tuple(queryset.query.extra.keys()) + subclasses = sorted(queryset.subclasses, key=len, reverse=True) + for obj in iter: + sub_obj = None + for s in subclasses: + sub_obj = queryset._get_sub_obj_recurse(obj, s) + if sub_obj: + break + if not sub_obj: + sub_obj = obj + + if getattr(queryset, '_annotated', False): + for k in queryset._annotated: + setattr(sub_obj, k, getattr(obj, k)) + + for k in extras: + + +## ... source file abbreviated to get to QuerySet examples ... + + + if levels or levels is None: + parent_model = related.model + parent_link = parent_model._meta.get_ancestor_link( + self.model) + else: + parent_link = None + return LOOKUP_SEP.join(ancestry) + + def _get_sub_obj_recurse(self, obj, s): + rel, _, s = s.partition(LOOKUP_SEP) + + try: + node = getattr(obj, rel) + except ObjectDoesNotExist: + return None + if s: + child = self._get_sub_obj_recurse(node, s) + return child + else: + return node + + def get_subclass(self, *args, **kwargs): + return self.select_subclasses().get(*args, **kwargs) + + +~~class InheritanceQuerySet(InheritanceQuerySetMixin, QuerySet): + def instance_of(self, *models): + + + + where_queries = [] + for model in models: + where_queries.append('(' + ' AND '.join([ + '"{}"."{}" IS NOT NULL'.format( + model._meta.db_table, + field.attname, # Should this be something else? + ) for field in model._meta.parents.values() + ]) + ')') + + return self.select_subclasses(*models).extra(where=[' OR '.join(where_queries)]) + + +class InheritanceManagerMixin: + _queryset_class = InheritanceQuerySet + + def get_queryset(self): + return self._queryset_class(self.model) + + def select_subclasses(self, *subclasses): + return self.get_queryset().select_subclasses(*subclasses) + + +## ... source file abbreviated to get to QuerySet examples ... + + + self._q = models.Q(**kwargs) + self._order_by = None + super().__init__() + + def order_by(self, *args): + self._order_by = args + return self + + def get_queryset(self): + qs = super().get_queryset().filter(self._q) + if self._order_by is not None: + return qs.order_by(*self._order_by) + return qs + + +class QueryManager(QueryManagerMixin, models.Manager): + pass + + +class SoftDeletableQuerySetMixin: + + def delete(self): + self.update(is_removed=True) + + +~~class SoftDeletableQuerySet(SoftDeletableQuerySetMixin, QuerySet): + pass + + +class SoftDeletableManagerMixin: + _queryset_class = SoftDeletableQuerySet + + def get_queryset(self): + kwargs = {'model': self.model, 'using': self._db} + if hasattr(self, '_hints'): + kwargs['hints'] = self._hints + + return self._queryset_class(**kwargs).filter(is_removed=False) + + +class SoftDeletableManager(SoftDeletableManagerMixin, models.Manager): + pass + + +class JoinQueryset(models.QuerySet): + + def get_quoted_query(self, query): + query, params = query.sql_with_params() + + params = [ + + +## ... source file continues with no further QuerySet examples... + +``` + + +## Example 7 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / relations.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./relations.py) + +```python +# relations.py +import sys +from collections import OrderedDict +from urllib import parse + +from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist +from django.db.models import Manager +~~from django.db.models.query import QuerySet +from django.urls import NoReverseMatch, Resolver404, get_script_prefix, resolve +from django.utils.encoding import smart_str, uri_to_iri +from django.utils.translation import gettext_lazy as _ + +from rest_framework.fields import ( + Field, empty, get_attribute, is_simple_callable, iter_options +) +from rest_framework.reverse import reverse +from rest_framework.settings import api_settings +from rest_framework.utils import html + + +def method_overridden(method_name, klass, instance): + method = getattr(klass, method_name) + default_method = getattr(method, '__func__', method) # Python 3 compat + return default_method is not getattr(instance, method_name).__func__ + + +class ObjectValueError(ValueError): + + +class ObjectTypeError(TypeError): + + + + +## ... source file abbreviated to get to QuerySet examples ... + + + ) + kwargs.pop('many', None) + kwargs.pop('allow_empty', None) + super().__init__(**kwargs) + + def __new__(cls, *args, **kwargs): + if kwargs.pop('many', False): + return cls.many_init(*args, **kwargs) + return super().__new__(cls, *args, **kwargs) + + @classmethod + def many_init(cls, *args, **kwargs): + list_kwargs = {'child_relation': cls(*args, **kwargs)} + for key in kwargs: + if key in MANY_RELATION_KWARGS: + list_kwargs[key] = kwargs[key] + return ManyRelatedField(**list_kwargs) + + def run_validation(self, data=empty): + if data == '': + data = None + return super().run_validation(data) + + def get_queryset(self): + queryset = self.queryset +~~ if isinstance(queryset, (QuerySet, Manager)): + queryset = queryset.all() + return queryset + + def use_pk_only_optimization(self): + return False + + def get_attribute(self, instance): + if self.use_pk_only_optimization() and self.source_attrs: + try: + attribute_instance = get_attribute(instance, self.source_attrs[:-1]) + value = attribute_instance.serializable_value(self.source_attrs[-1]) + if is_simple_callable(value): + value = value().pk + return PKOnlyObject(pk=value) + except AttributeError: + pass + + return super().get_attribute(instance) + + def get_choices(self, cutoff=None): + queryset = self.get_queryset() + if queryset is None: + return {} + + + +## ... source file continues with no further QuerySet examples... + +``` + + +## Example 8 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / managers.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./managers.py) + +```python +# managers.py +from django.db import models +from django.db.models import Count +from django.db.models import Q +from django.db.models.query import EmptyQuerySet +~~from django.db.models.query import QuerySet +from mptt.managers import TreeManager + + +~~class ArticleQuerySet(QuerySet): + def can_read(self, user): + if user.has_perm("wiki.moderator"): + return self + if user.is_anonymous: + q = self.filter(other_read=True) + else: + q = self.filter( + Q(other_read=True) + | Q(owner=user) + | (Q(group__user=user) & Q(group_read=True)) + ).annotate(Count("id")) + return q + + def can_write(self, user): + if user.has_perm("wiki.moderator"): + return self + if user.is_anonymous: + q = self.filter(other_write=True) + else: + q = self.filter( + Q(other_write=True) + | Q(owner=user) + | (Q(group__user=user) & Q(group_write=True)) + ) + + +## ... source file abbreviated to get to QuerySet examples ... + + +class ArticleFkManager(models.Manager): + def get_empty_query_set(self): + return self.get_queryset().none() + + def get_queryset(self): + return ArticleFkQuerySet(self.model, using=self._db) + + def active(self): + return self.get_queryset().active() + + def can_read(self, user): + return self.get_queryset().can_read(user) + + def can_write(self, user): + return self.get_queryset().can_write(user) + + +class URLPathEmptyQuerySet(EmptyQuerySet, ArticleFkEmptyQuerySetMixin): + def select_related_common(self): + return self + + def default_order(self): + return self + + +~~class URLPathQuerySet(QuerySet, ArticleFkQuerySetMixin): + def select_related_common(self): + return self.select_related( + "parent", "article__current_revision", "article__owner" + ) + + def default_order(self): + return self.order_by("article__current_revision__title") + + +class URLPathManager(TreeManager): + def get_empty_query_set(self): + return self.get_queryset().none() + + def get_queryset(self): + return URLPathQuerySet(self.model, using=self._db).order_by( + self.tree_id_attr, self.left_attr + ) + + def select_related_common(self): + return self.get_queryset().common_select_related() + + def active(self): + return self.get_queryset().active() + + if user.is_anonymous: + q = self.filter(article__other_write=True) + else: + q = self.filter( + Q(article__other_write=True) + | Q(article__owner=user) + | (Q(article__group__user=user) & Q(article__group_write=True)) + ).annotate(Count("id")) + return q + + def active(self): + return self.filter(article__current_revision__deleted=False) + + +class ArticleFkEmptyQuerySetMixin: + def can_read(self, user): + return self + + def can_write(self, user): + return self + + def active(self): + return self + + +~~class ArticleFkQuerySet(ArticleFkQuerySetMixin, QuerySet): + pass + + +class ArticleFkEmptyQuerySet(ArticleFkEmptyQuerySetMixin, EmptyQuerySet): + pass + + +class ArticleManager(models.Manager): + def get_empty_query_set(self): + return self.get_queryset().none() + + def get_queryset(self): + return ArticleQuerySet(self.model, using=self._db) + + def active(self): + return self.get_queryset().active() + + def can_read(self, user): + return self.get_queryset().can_read(user) + + def can_write(self, user): + return self.get_queryset().can_write(user) + + + + +## ... source file continues with no further QuerySet examples... + +``` + + +## Example 9 from elasticsearch-django +[elasticsearch-django](https://github.com/yunojuno/elasticsearch-django) +([PyPI package information](https://pypi.org/project/elasticsearch-django/)) +is a [Django](/django.html) app for managing +[ElasticSearch](https://github.com/elastic/elasticsearch) indexes +populated by [Django ORM](/django-orm.html) models. The project is +available as open source under the +[MIT license](https://github.com/yunojuno/elasticsearch-django/blob/master/LICENSE). + +[**elasticsearch-django / elasticsearch_django / models.py**](https://github.com/yunojuno/elasticsearch-django/blob/master/elasticsearch_django/./models.py) + +```python +# models.py +from __future__ import annotations + +import logging +import time +import warnings +from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Union + +from django.conf import settings +from django.contrib.postgres.fields import JSONField +from django.core.cache import cache +from django.core.serializers.json import DjangoJSONEncoder +from django.db import models +from django.db.models.expressions import RawSQL +from django.db.models.fields import CharField +~~from django.db.models.query import QuerySet +from django.utils.timezone import now as tz_now +from elasticsearch_dsl import Search + +from .settings import ( + get_client, + get_model_index_properties, + get_model_indexes, + get_setting, +) + +if TYPE_CHECKING: + from django.contrib.auth.models import AbstractBaseUser + +logger = logging.getLogger(__name__) + +UPDATE_STRATEGY_FULL = "full" +UPDATE_STRATEGY_PARTIAL = "partial" +UPDATE_STRATEGY = get_setting("update_strategy", UPDATE_STRATEGY_FULL) + + +class SearchDocumentManagerMixin(models.Manager): + + def get_search_queryset(self, index: str = "_all") -> QuerySet: + raise NotImplementedError( + + +## ... source file continues with no further QuerySet examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-query-utils-deferredattribute.markdown b/content/pages/examples/django/django-db-models-query-utils-deferredattribute.markdown new file mode 100644 index 000000000..1211e4cd4 --- /dev/null +++ b/content/pages/examples/django/django-db-models-query-utils-deferredattribute.markdown @@ -0,0 +1,120 @@ +title: django.db.models.query_utils DeferredAttribute Example Code +category: page +slug: django-db-models-query-utils-deferredattribute-examples +sortorder: 500011245 +toc: False +sidebartitle: django.db.models.query_utils DeferredAttribute +meta: Python example code for the DeferredAttribute class from the django.db.models.query_utils module of the Django project. + + +DeferredAttribute is a class within the django.db.models.query_utils module of the Django project. + + +## Example 1 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / tracker.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./tracker.py) + +```python +# tracker.py +from copy import deepcopy +from functools import wraps + +import django +from django.core.exceptions import FieldError +from django.db import models +from django.db.models.fields.files import FileDescriptor +~~from django.db.models.query_utils import DeferredAttribute + + +class DescriptorMixin: + tracker_instance = None + + def __get__(self, instance, owner): + if instance is None: + return self + was_deferred = False + field_name = self._get_field_name() + if field_name in instance._deferred_fields: + instance._deferred_fields.remove(field_name) + was_deferred = True + value = super().__get__(instance, owner) + if was_deferred: + self.tracker_instance.saved_data[field_name] = deepcopy(value) + return value + + def _get_field_name(self): + return self.field_name + + +class DescriptorWrapper: + + + +## ... source file abbreviated to get to DeferredAttribute examples ... + + + if self.instance.pk and field in self.deferred_fields and field not in self.saved_data: + + if field not in self.instance.__dict__: + self.get_field_value(field) + + else: + current_value = self.get_field_value(field) + self.instance.refresh_from_db(fields=[field]) + self.saved_data[field] = deepcopy(self.get_field_value(field)) + setattr(self.instance, self.field_map[field], current_value) + + return self.saved_data.get(field) + + def changed(self): + return { + field: self.previous(field) + for field in self.fields + if self.has_changed(field) + } + + def init_deferred_fields(self): + self.instance._deferred_fields = set() + if hasattr(self.instance, '_deferred') and not self.instance._deferred: + return + +~~ class DeferredAttributeTracker(DescriptorMixin, DeferredAttribute): + tracker_instance = self + + class FileDescriptorTracker(DescriptorMixin, FileDescriptor): + tracker_instance = self + + def _get_field_name(self): + return self.field.name + + self.instance._deferred_fields = self.instance.get_deferred_fields() + for field in self.instance._deferred_fields: + field_obj = self.instance.__class__.__dict__.get(field) + if isinstance(field_obj, FileDescriptor): + field_tracker = FileDescriptorTracker(field_obj.field) + setattr(self.instance.__class__, field, field_tracker) + else: + field_tracker = DeferredAttributeTracker(field) + setattr(self.instance.__class__, field, field_tracker) + + +class FieldTracker: + + tracker_class = FieldInstanceTracker + + def __init__(self, fields=None): + + +## ... source file continues with no further DeferredAttribute examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-query-utils-pathinfo.markdown b/content/pages/examples/django/django-db-models-query-utils-pathinfo.markdown new file mode 100644 index 000000000..941641c13 --- /dev/null +++ b/content/pages/examples/django/django-db-models-query-utils-pathinfo.markdown @@ -0,0 +1,162 @@ +title: django.db.models.query_utils PathInfo Example Code +category: page +slug: django-db-models-query-utils-pathinfo-examples +sortorder: 500011246 +toc: False +sidebartitle: django.db.models.query_utils PathInfo +meta: Python example code for the PathInfo class from the django.db.models.query_utils module of the Django project. + + +PathInfo is a class within the django.db.models.query_utils module of the Django project. + + +## Example 1 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / managers.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./managers.py) + +```python +# managers.py +import uuid +from operator import attrgetter + +from django import VERSION +from django.conf import settings +from django.contrib.contenttypes.fields import GenericRelation +from django.contrib.contenttypes.models import ContentType +from django.db import connections, models, router +from django.db.models import signals +from django.db.models.fields.related import ( + ManyToManyRel, + OneToOneRel, + RelatedField, + lazy_related_operation, +) +~~from django.db.models.query_utils import PathInfo +from django.utils.text import capfirst +from django.utils.translation import gettext_lazy as _ + +from taggit.forms import TagField +from taggit.models import ( + CommonGenericTaggedItemBase, + GenericUUIDTaggedItemBase, + TaggedItem, +) +from taggit.utils import require_instance_manager + + +class ExtraJoinRestriction: + + contains_aggregate = False + + def __init__(self, alias, col, content_types): + self.alias = alias + self.col = col + self.content_types = content_types + + def as_sql(self, compiler, connection): + qn = compiler.quote_name_unless_alias + if len(self.content_types) == 1: + + +## ... source file abbreviated to get to PathInfo examples ... + + + filtered_relation=filtered_relation + ) + else: + if VERSION < (2, 0): + join1infos = linkfield2.get_reverse_path_info() + join2infos = linkfield1.get_path_info() + else: + join1infos = linkfield2.get_reverse_path_info( + filtered_relation=filtered_relation + ) + join2infos = linkfield1.get_path_info( + filtered_relation=filtered_relation + ) + pathinfos.extend(join1infos) + pathinfos.extend(join2infos) + return pathinfos + + def _get_gfk_case_path_info(self, direct=False, filtered_relation=None): + pathinfos = [] + from_field = self.model._meta.pk + opts = self.through._meta + linkfield = self.through._meta.get_field(self.m2m_reverse_field_name()) + if direct: + if VERSION < (2, 0): + join1infos = [ +~~ PathInfo( + self.model._meta, + opts, + [from_field], + self.remote_field, + True, + False, + ) + ] + join2infos = linkfield.get_path_info() + else: + join1infos = [ +~~ PathInfo( + self.model._meta, + opts, + [from_field], + self.remote_field, + True, + False, + filtered_relation, + ) + ] + join2infos = linkfield.get_path_info( + filtered_relation=filtered_relation + ) + else: + if VERSION < (2, 0): + join1infos = linkfield.get_reverse_path_info() + join2infos = [ +~~ PathInfo(opts, self.model._meta, [from_field], self, True, False) + ] + else: + join1infos = linkfield.get_reverse_path_info( + filtered_relation=filtered_relation + ) + join2infos = [ +~~ PathInfo( + opts, + self.model._meta, + [from_field], + self, + True, + False, + filtered_relation, + ) + ] + pathinfos.extend(join1infos) + pathinfos.extend(join2infos) + return pathinfos + + def get_path_info(self, filtered_relation=None): + if self.use_gfk: + return self._get_gfk_case_path_info( + direct=True, filtered_relation=filtered_relation + ) + else: + return self._get_mm_case_path_info( + direct=True, filtered_relation=filtered_relation + ) + + def get_reverse_path_info(self, filtered_relation=None): + + +## ... source file continues with no further PathInfo examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-query-utils-q.markdown b/content/pages/examples/django/django-db-models-query-utils-q.markdown new file mode 100644 index 000000000..b13b3dfea --- /dev/null +++ b/content/pages/examples/django/django-db-models-query-utils-q.markdown @@ -0,0 +1,117 @@ +title: django.db.models.query_utils Q Example Code +category: page +slug: django-db-models-query-utils-q-examples +sortorder: 500011247 +toc: False +sidebartitle: django.db.models.query_utils Q +meta: Python example code for the Q constant from the django.db.models.query_utils module of the Django project. + + +Q is a constant within the django.db.models.query_utils module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / utils / placeholder.py**](https://github.com/divio/django-cms/blob/develop/cms/utils/placeholder.py) + +```python +# placeholder.py +import operator +import warnings +from collections import OrderedDict + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +~~from django.db.models.query_utils import Q +from django.template import TemplateSyntaxError, NodeList, Variable, Context, Template, engines +from django.template.base import VariableNode +from django.template.loader import get_template +from django.template.loader_tags import BlockNode, ExtendsNode, IncludeNode + +from six import string_types + +from sekizai.helpers import get_varname + +from cms.exceptions import DuplicatePlaceholderWarning +from cms.utils.conf import get_cms_setting + + +def _get_nodelist(tpl): + if hasattr(tpl, 'template'): + return tpl.template.nodelist + else: + return tpl.nodelist + + +def get_context(): + if engines is not None: + context = Context() + context.template = Template('') + + +## ... source file abbreviated to get to Q examples ... + + + + def copy(self, **kwargs): + return False + + def get_copy_languages(self, **kwargs): + return [] + + +class MLNGPlaceholderActions(PlaceholderNoAction): + can_copy = True + + def copy(self, target_placeholder, source_language, fieldname, model, target_language, **kwargs): + from cms.utils.copy_plugins import copy_plugins_to + trgt = model.objects.get(**{fieldname: target_placeholder}) + src = model.objects.get(master=trgt.master, language_code=source_language) + + source_placeholder = getattr(src, fieldname, None) + if not source_placeholder: + return False + return copy_plugins_to(source_placeholder.get_plugins_list(), + target_placeholder, target_language) + + def get_copy_languages(self, placeholder, model, fieldname, **kwargs): + manager = model.objects + src = manager.get(**{fieldname: placeholder}) +~~ query = Q(master=src.master) +~~ query &= Q(**{'%s__cmsplugin__isnull' % fieldname: False}) + query &= -Q(pk=src.pk) + + language_codes = manager.filter(query).values_list('language_code', flat=True).distinct() + return [(lc, dict(settings.LANGUAGES)[lc]) for lc in language_codes] + + +def restore_sekizai_context(context, changes): + varname = get_varname() + sekizai_container = context.get(varname) + for key, values in changes.items(): + sekizai_namespace = sekizai_container[key] + for value in values: + sekizai_namespace.append(value) + + +def _scan_placeholders(nodelist, node_class=None, current_block=None, ignore_blocks=None): + from cms.templatetags.cms_tags import Placeholder + + if not node_class: + node_class = Placeholder + + nodes = [] + + if ignore_blocks is None: + + +## ... source file continues with no further Q examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-signals-post-delete.markdown b/content/pages/examples/django/django-db-models-signals-post-delete.markdown new file mode 100644 index 000000000..7a5dd1965 --- /dev/null +++ b/content/pages/examples/django/django-db-models-signals-post-delete.markdown @@ -0,0 +1,63 @@ +title: django.db.models.signals post_delete Example Code +category: page +slug: django-db-models-signals-post-delete-examples +sortorder: 500011248 +toc: False +sidebartitle: django.db.models.signals post_delete +meta: Python example code for the post_delete callable from the django.db.models.signals module of the Django project. + + +post_delete is a callable within the django.db.models.signals module of the Django project. + + +## Example 1 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / signal_handlers.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/signal_handlers.py) + +```python +# signal_handlers.py +import logging + +from django.core.cache import cache +~~from django.db.models.signals import post_delete, post_save, pre_delete + +from wagtail.core.models import Page, Site + +logger = logging.getLogger('wagtail.core') + + +def post_save_site_signal_handler(instance, update_fields=None, **kwargs): + cache.delete('wagtail_site_root_paths') + + +def post_delete_site_signal_handler(instance, **kwargs): + cache.delete('wagtail_site_root_paths') + + +def pre_delete_page_unpublish(sender, instance, **kwargs): + if instance.live: + instance.unpublish(commit=False) + + +def post_delete_page_log_deletion(sender, instance, **kwargs): + logger.info("Page deleted: \"%s\" id=%d", instance.title, instance.id) + + +def register_signal_handlers(): + post_save.connect(post_save_site_signal_handler, sender=Site) +~~ post_delete.connect(post_delete_site_signal_handler, sender=Site) + + pre_delete.connect(pre_delete_page_unpublish, sender=Page) +~~ post_delete.connect(post_delete_page_log_deletion, sender=Page) + + + +## ... source file continues with no further post_delete examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-signals-post-save.markdown b/content/pages/examples/django/django-db-models-signals-post-save.markdown new file mode 100644 index 000000000..5646633c8 --- /dev/null +++ b/content/pages/examples/django/django-db-models-signals-post-save.markdown @@ -0,0 +1,149 @@ +title: django.db.models.signals post_save Example Code +category: page +slug: django-db-models-signals-post-save-examples +sortorder: 500011249 +toc: False +sidebartitle: django.db.models.signals post_save +meta: Python example code for the post_save callable from the django.db.models.signals module of the Django project. + + +post_save is a callable within the django.db.models.signals module of the Django project. + + +## Example 1 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / models.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./models.py) + +```python +# models.py +from django.core.exceptions import ImproperlyConfigured +from django.db import models, transaction, router +~~from django.db.models.signals import post_save, pre_save +from django.utils.translation import gettext_lazy as _ + +from model_utils.fields import ( + AutoCreatedField, + AutoLastModifiedField, + StatusField, + MonitorField, + UUIDField, +) +from model_utils.managers import ( + QueryManager, + SoftDeletableManager, +) + +from django.db.models.functions import Now +now = Now() + + +class TimeStampedModel(models.Model): + created = AutoCreatedField(_('created')) + modified = AutoLastModifiedField(_('modified')) + + def save(self, *args, **kwargs): + if 'update_fields' in kwargs and 'modified' not in kwargs['update_fields']: + + +## ... source file abbreviated to get to post_save examples ... + + + + def save_base(self, raw=False, force_insert=False, + force_update=False, using=None, update_fields=None): + using = using or router.db_for_write(self.__class__, instance=self) + assert not (force_insert and (force_update or update_fields)) + assert update_fields is None or len(update_fields) > 0 + cls = origin = self.__class__ + + if cls._meta.proxy: + cls = cls._meta.concrete_model + meta = cls._meta + if not meta.auto_created and 'pre_save' not in self.signals_to_disable: + pre_save.send( + sender=origin, instance=self, raw=raw, using=using, + update_fields=update_fields, + ) + with transaction.atomic(using=using, savepoint=False): + if not raw: + self._save_parents(cls, using, update_fields) + updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) + + self._state.db = using + self._state.adding = False + + if not meta.auto_created and 'post_save' not in self.signals_to_disable: +~~ post_save.send( + sender=origin, instance=self, created=(not updated), + update_fields=update_fields, raw=raw, using=using, + ) + + self.signals_to_disable = [] + + + +## ... source file continues with no further post_save examples... + +``` + + +## Example 2 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / signal_handlers.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/signal_handlers.py) + +```python +# signal_handlers.py +import logging + +from django.core.cache import cache +~~from django.db.models.signals import post_delete, post_save, pre_delete + +from wagtail.core.models import Page, Site + +logger = logging.getLogger('wagtail.core') + + +def post_save_site_signal_handler(instance, update_fields=None, **kwargs): + cache.delete('wagtail_site_root_paths') + + +def post_delete_site_signal_handler(instance, **kwargs): + cache.delete('wagtail_site_root_paths') + + +def pre_delete_page_unpublish(sender, instance, **kwargs): + if instance.live: + instance.unpublish(commit=False) + + +def post_delete_page_log_deletion(sender, instance, **kwargs): + logger.info("Page deleted: \"%s\" id=%d", instance.title, instance.id) + + +def register_signal_handlers(): +~~ post_save.connect(post_save_site_signal_handler, sender=Site) + post_delete.connect(post_delete_site_signal_handler, sender=Site) + + pre_delete.connect(pre_delete_page_unpublish, sender=Page) + post_delete.connect(post_delete_page_log_deletion, sender=Page) + + + +## ... source file continues with no further post_save examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-signals-pre-delete.markdown b/content/pages/examples/django/django-db-models-signals-pre-delete.markdown new file mode 100644 index 000000000..1585599c7 --- /dev/null +++ b/content/pages/examples/django/django-db-models-signals-pre-delete.markdown @@ -0,0 +1,63 @@ +title: django.db.models.signals pre_delete Example Code +category: page +slug: django-db-models-signals-pre-delete-examples +sortorder: 500011250 +toc: False +sidebartitle: django.db.models.signals pre_delete +meta: Python example code for the pre_delete callable from the django.db.models.signals module of the Django project. + + +pre_delete is a callable within the django.db.models.signals module of the Django project. + + +## Example 1 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / signal_handlers.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/signal_handlers.py) + +```python +# signal_handlers.py +import logging + +from django.core.cache import cache +~~from django.db.models.signals import post_delete, post_save, pre_delete + +from wagtail.core.models import Page, Site + +logger = logging.getLogger('wagtail.core') + + +def post_save_site_signal_handler(instance, update_fields=None, **kwargs): + cache.delete('wagtail_site_root_paths') + + +def post_delete_site_signal_handler(instance, **kwargs): + cache.delete('wagtail_site_root_paths') + + +def pre_delete_page_unpublish(sender, instance, **kwargs): + if instance.live: + instance.unpublish(commit=False) + + +def post_delete_page_log_deletion(sender, instance, **kwargs): + logger.info("Page deleted: \"%s\" id=%d", instance.title, instance.id) + + +def register_signal_handlers(): + post_save.connect(post_save_site_signal_handler, sender=Site) + post_delete.connect(post_delete_site_signal_handler, sender=Site) + +~~ pre_delete.connect(pre_delete_page_unpublish, sender=Page) + post_delete.connect(post_delete_page_log_deletion, sender=Page) + + + +## ... source file continues with no further pre_delete examples... + +``` + diff --git a/content/pages/examples/django/django-db-models-signals-pre-save.markdown b/content/pages/examples/django/django-db-models-signals-pre-save.markdown new file mode 100644 index 000000000..a83fdc5c0 --- /dev/null +++ b/content/pages/examples/django/django-db-models-signals-pre-save.markdown @@ -0,0 +1,240 @@ +title: django.db.models.signals pre_save Example Code +category: page +slug: django-db-models-signals-pre-save-examples +sortorder: 500011251 +toc: False +sidebartitle: django.db.models.signals pre_save +meta: Python example code for the pre_save callable from the django.db.models.signals module of the Django project. + + +pre_save is a callable within the django.db.models.signals module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog / middleware.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog/middleware.py) + +```python +# middleware.py +from __future__ import unicode_literals + +import threading +import time + +from django.conf import settings +~~from django.db.models.signals import pre_save +from django.utils.functional import curry +from django.apps import apps +from auditlog.models import LogEntry +from auditlog.compat import is_authenticated + +try: + from django.utils.deprecation import MiddlewareMixin +except ImportError: + MiddlewareMixin = object + + +threadlocal = threading.local() + + +class AuditlogMiddleware(MiddlewareMixin): + + def process_request(self, request): + threadlocal.auditlog = { + 'signal_duid': (self.__class__, time.time()), + 'remote_addr': request.META.get('REMOTE_ADDR'), + } + + if request.META.get('HTTP_X_FORWARDED_FOR'): + threadlocal.auditlog['remote_addr'] = request.META.get('HTTP_X_FORWARDED_FOR').split(',')[0] + + if hasattr(request, 'user') and is_authenticated(request.user): + set_actor = curry(self.set_actor, user=request.user, signal_duid=threadlocal.auditlog['signal_duid']) +~~ pre_save.connect(set_actor, sender=LogEntry, dispatch_uid=threadlocal.auditlog['signal_duid'], weak=False) + + def process_response(self, request, response): + if hasattr(threadlocal, 'auditlog'): +~~ pre_save.disconnect(sender=LogEntry, dispatch_uid=threadlocal.auditlog['signal_duid']) + + return response + + def process_exception(self, request, exception): + if hasattr(threadlocal, 'auditlog'): +~~ pre_save.disconnect(sender=LogEntry, dispatch_uid=threadlocal.auditlog['signal_duid']) + + return None + + @staticmethod + def set_actor(user, sender, instance, signal_duid, **kwargs): + if hasattr(threadlocal, 'auditlog'): + if signal_duid != threadlocal.auditlog['signal_duid']: + return + try: + app_label, model_name = settings.AUTH_USER_MODEL.split('.') + auth_user_model = apps.get_model(app_label, model_name) + except ValueError: + auth_user_model = apps.get_model('auth', 'user') + if sender == LogEntry and isinstance(user, auth_user_model) and instance.actor is None: + instance.actor = user + + instance.remote_addr = threadlocal.auditlog['remote_addr'] + + + +## ... source file continues with no further pre_save examples... + +``` + + +## Example 2 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / models.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./models.py) + +```python +# models.py +from django.core.exceptions import ImproperlyConfigured +from django.db import models, transaction, router +~~from django.db.models.signals import post_save, pre_save +from django.utils.translation import gettext_lazy as _ + +from model_utils.fields import ( + AutoCreatedField, + AutoLastModifiedField, + StatusField, + MonitorField, + UUIDField, +) +from model_utils.managers import ( + QueryManager, + SoftDeletableManager, +) + +from django.db.models.functions import Now +now = Now() + + +class TimeStampedModel(models.Model): + created = AutoCreatedField(_('created')) + modified = AutoLastModifiedField(_('modified')) + + def save(self, *args, **kwargs): + if 'update_fields' in kwargs and 'modified' not in kwargs['update_fields']: + + +## ... source file abbreviated to get to pre_save examples ... + + + class Meta: + abstract = True + + +class SaveSignalHandlingModel(models.Model): + class Meta: + abstract = True + + def save(self, signals_to_disable=None, *args, **kwargs): + + self.signals_to_disable = signals_to_disable or [] + + super().save(*args, **kwargs) + + def save_base(self, raw=False, force_insert=False, + force_update=False, using=None, update_fields=None): + using = using or router.db_for_write(self.__class__, instance=self) + assert not (force_insert and (force_update or update_fields)) + assert update_fields is None or len(update_fields) > 0 + cls = origin = self.__class__ + + if cls._meta.proxy: + cls = cls._meta.concrete_model + meta = cls._meta + if not meta.auto_created and 'pre_save' not in self.signals_to_disable: +~~ pre_save.send( + sender=origin, instance=self, raw=raw, using=using, + update_fields=update_fields, + ) + with transaction.atomic(using=using, savepoint=False): + if not raw: + self._save_parents(cls, using, update_fields) + updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) + + self._state.db = using + self._state.adding = False + + if not meta.auto_created and 'post_save' not in self.signals_to_disable: + post_save.send( + sender=origin, instance=self, created=(not updated), + update_fields=update_fields, raw=raw, using=using, + ) + + self.signals_to_disable = [] + + + +## ... source file continues with no further pre_save examples... + +``` + + +## Example 3 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / images / signal_handlers.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/images/signal_handlers.py) + +```python +# signal_handlers.py +from django.conf import settings +from django.db import transaction +~~from django.db.models.signals import post_delete, pre_save + +from wagtail.images import get_image_model + + +def post_delete_file_cleanup(instance, **kwargs): + transaction.on_commit(lambda: instance.file.delete(False)) + + +def post_delete_purge_rendition_cache(instance, **kwargs): + instance.purge_from_cache() + + +def pre_save_image_feature_detection(instance, **kwargs): + if getattr(settings, 'WAGTAILIMAGES_FEATURE_DETECTION_ENABLED', False): + if not instance.has_focal_point(): + instance.set_focal_point(instance.get_suggested_focal_point()) + + +def register_signal_handlers(): + Image = get_image_model() + Rendition = Image.get_rendition_model() + +~~ pre_save.connect(pre_save_image_feature_detection, sender=Image) + post_delete.connect(post_delete_file_cleanup, sender=Image) + post_delete.connect(post_delete_file_cleanup, sender=Rendition) + post_delete.connect(post_delete_purge_rendition_cache, sender=Rendition) + + + +## ... source file continues with no further pre_save examples... + +``` + diff --git a/content/pages/examples/django/django-db-models.markdown b/content/pages/examples/django/django-db-models.markdown new file mode 100644 index 000000000..8d4b12427 --- /dev/null +++ b/content/pages/examples/django/django-db-models.markdown @@ -0,0 +1,4688 @@ +title: django.db models Example Code +category: page +slug: django-db-models-examples +sortorder: 500011167 +toc: False +sidebartitle: django.db models +meta: Python example code for the models callable from the django.db module of the Django project. + + +models is a callable within the django.db module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog_tests / models.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog_tests/models.py) + +```python +# models.py +import uuid + +from django.contrib.postgres.fields import ArrayField +~~from django.db import models +from auditlog.models import AuditlogHistoryField +from auditlog.registry import auditlog + +from multiselectfield import MultiSelectField + + +@auditlog.register() +class SimpleModel(models.Model): + +~~ text = models.TextField(blank=True) +~~ boolean = models.BooleanField(default=False) +~~ integer = models.IntegerField(blank=True, null=True) +~~ datetime = models.DateTimeField(auto_now=True) + + history = AuditlogHistoryField() + + +class AltPrimaryKeyModel(models.Model): + +~~ key = models.CharField(max_length=100, primary_key=True) + +~~ text = models.TextField(blank=True) +~~ boolean = models.BooleanField(default=False) +~~ integer = models.IntegerField(blank=True, null=True) +~~ datetime = models.DateTimeField(auto_now=True) + + history = AuditlogHistoryField(pk_indexable=False) + + +class UUIDPrimaryKeyModel(models.Model): + +~~ id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + +~~ text = models.TextField(blank=True) +~~ boolean = models.BooleanField(default=False) +~~ integer = models.IntegerField(blank=True, null=True) +~~ datetime = models.DateTimeField(auto_now=True) + + history = AuditlogHistoryField(pk_indexable=False) + + +class ProxyModel(SimpleModel): + + class Meta: + proxy = True + + +class RelatedModel(models.Model): + +~~ related = models.ForeignKey(to='self', on_delete=models.CASCADE) + + history = AuditlogHistoryField() + + +class ManyRelatedModel(models.Model): + +~~ related = models.ManyToManyField('self') + + history = AuditlogHistoryField() + + +@auditlog.register(include_fields=['label']) +class SimpleIncludeModel(models.Model): + +~~ label = models.CharField(max_length=100) +~~ text = models.TextField(blank=True) + + history = AuditlogHistoryField() + + +class SimpleExcludeModel(models.Model): + +~~ label = models.CharField(max_length=100) +~~ text = models.TextField(blank=True) + + history = AuditlogHistoryField() + + +class SimpleMappingModel(models.Model): + +~~ sku = models.CharField(max_length=100) +~~ vtxt = models.CharField(verbose_name='Version', max_length=100) +~~ not_mapped = models.CharField(max_length=100) + + history = AuditlogHistoryField() + + +class AdditionalDataIncludedModel(models.Model): + +~~ label = models.CharField(max_length=100) +~~ text = models.TextField(blank=True) +~~ related = models.ForeignKey(to=SimpleModel, on_delete=models.CASCADE) + + history = AuditlogHistoryField() + + def get_additional_data(self): + object_details = { + 'related_model_id': self.related.id, + 'related_model_text': self.related.text + } + return object_details + + +class DateTimeFieldModel(models.Model): +~~ label = models.CharField(max_length=100) +~~ timestamp = models.DateTimeField() +~~ date = models.DateField() +~~ time = models.TimeField() +~~ naive_dt = models.DateTimeField(null=True, blank=True) + + history = AuditlogHistoryField() + + +class ChoicesFieldModel(models.Model): + RED = 'r' + YELLOW = 'y' + GREEN = 'g' + + STATUS_CHOICES = ( + (RED, 'Red'), + (YELLOW, 'Yellow'), + (GREEN, 'Green'), + ) + +~~ status = models.CharField(max_length=1, choices=STATUS_CHOICES) + multiselect = MultiSelectField(max_length=3, choices=STATUS_CHOICES, max_choices=3) +~~ multiplechoice = models.CharField(max_length=255, choices=STATUS_CHOICES) + + history = AuditlogHistoryField() + + +class CharfieldTextfieldModel(models.Model): + +~~ longchar = models.CharField(max_length=255) +~~ longtextfield = models.TextField() + + history = AuditlogHistoryField() + + +class PostgresArrayFieldModel(models.Model): + RED = 'r' + YELLOW = 'y' + GREEN = 'g' + + STATUS_CHOICES = ( + (RED, 'Red'), + (YELLOW, 'Yellow'), + (GREEN, 'Green'), + ) + + arrayfield = ArrayField(models.CharField(max_length=1, choices=STATUS_CHOICES), size=3) + + history = AuditlogHistoryField() + + +class NoDeleteHistoryModel(models.Model): +~~ integer = models.IntegerField(blank=True, null=True) + + history = AuditlogHistoryField(delete_related=False) + + +auditlog.register(AltPrimaryKeyModel) +auditlog.register(UUIDPrimaryKeyModel) +auditlog.register(ProxyModel) +auditlog.register(RelatedModel) +auditlog.register(ManyRelatedModel) +auditlog.register(ManyRelatedModel.related.through) +auditlog.register(SimpleExcludeModel, exclude_fields=['text']) +auditlog.register(SimpleMappingModel, mapping_fields={'sku': 'Product No.'}) +auditlog.register(AdditionalDataIncludedModel) +auditlog.register(DateTimeFieldModel) +auditlog.register(ChoicesFieldModel) +auditlog.register(CharfieldTextfieldModel) +auditlog.register(PostgresArrayFieldModel) +auditlog.register(NoDeleteHistoryModel) + + + +## ... source file continues with no further models examples... + +``` + + +## Example 2 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / chair / forms.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/chair/forms.py) + +```python +# forms.py +from functools import reduce + +from django import forms +from django.contrib.auth import get_user_model +~~from django.db import models +from django.db.models import Q, F, Count, Max, Subquery, OuterRef, Value +from django.db.models.functions import Concat +from django.forms import MultipleChoiceField, ChoiceField, Form +from django.urls import reverse +from django.utils.translation import ugettext_lazy as _ + +from django_countries import countries + +from conferences.models import Conference, ArtifactDescriptor +from gears.widgets import CustomCheckboxSelectMultiple, CustomFileInput +from review.models import Reviewer, Review, ReviewStats +from review.utilities import get_average_score +from submissions.models import Submission, Attachment +from users.models import Profile + +User = get_user_model() + + +def clean_data_to_int(iterable, empty=None): + return [int(x) if x != '' else None for x in iterable] + + +def q_or(disjuncts, default=True): + if disjuncts: + + +## ... source file abbreviated to get to models examples ... + + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + assert isinstance(self.instance, Conference) + countries_dict = dict(countries) + + self.fields['countries'].choices = [ + (code, countries_dict[code]) for code in + Profile.objects.filter(country__isnull=False).values_list( + 'country', flat=True).order_by('country').distinct()] + + self.fields['affiliations'].choices = [ + (aff, aff) for aff in + Profile.objects.values_list('affiliation', flat=True).order_by( + 'affiliation').distinct() if aff] + + def order_profiles(self, profiles): + order = self.cleaned_data['order'] + direction = '-' if self.cleaned_data['direction'] == 'DESC' else '' + if order == self.ORDER_BY_ID or not order: + return profiles.order_by(f'{direction}pk') + + elif order == self.ORDER_BY_NAME: + profiles = profiles.annotate( + full_name=Concat( + 'last_name', Value(' '), 'first_name', +~~ output_field=models.CharField())) + return profiles.order_by(f'{direction}full_name') + + return profiles + + def apply_term(self, profiles): + term = self.cleaned_data['term'] + for word in term.lower().split(): + profiles = profiles.filter( + Q(pk__icontains=word) | Q(first_name__icontains=word) | + Q(last_name__icontains=word) | + Q(first_name_rus__icontains=word) | + Q(last_name_rus__icontains=word) | + Q(middle_name_rus__icontains=word)) + return profiles + + def apply_countries(self, profiles): + data = self.cleaned_data['countries'] + if data: + profiles = profiles.filter(country__in=data) + return profiles + + def apply_affiliations(self, profiles): + data = self.cleaned_data['affiliations'] + if data: + + +## ... source file continues with no further models examples... + +``` + + +## Example 3 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / tests.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/./tests.py) + +```python +# tests.py +from __future__ import unicode_literals + +import json +import requests +from datetime import date, datetime + +import django +from django.core.files.base import ContentFile +~~from django.db import models +from django.test import RequestFactory, TestCase +from django.utils.http import base36_to_int, int_to_base36 +from django.views import csrf + +from . import utils + + +try: + from unittest.mock import Mock, patch +except ImportError: + from mock import Mock, patch # noqa + + +class MockedResponse(object): + def __init__(self, status_code, content, headers=None): + if headers is None: + headers = {} + + self.status_code = status_code + self.content = content.encode('utf8') + self.headers = headers + + def json(self): + return json.loads(self.text) + + +## ... source file abbreviated to get to models examples ... + + + + def test_email_validation(self): + s = 'this.email.address.is.a.bit.too.long.but.should.still.validate@example.com' # noqa + self.assertEqual(s, utils.valid_email_or_none(s)) + + def test_serializer(self): + + class SomeValue: + pass + + some_value = SomeValue() + + class SomeField(models.Field): + def get_prep_value(self, value): + return 'somevalue' + if django.VERSION < (3, 0): + def from_db_value( + self, value, expression, connection, context + ): + return some_value + else: + def from_db_value(self, value, expression, connection): + return some_value + + class SomeModel(models.Model): +~~ dt = models.DateTimeField() +~~ t = models.TimeField() +~~ d = models.DateField() +~~ img1 = models.ImageField() +~~ img2 = models.ImageField() +~~ img3 = models.ImageField() + something = SomeField() + + def method(self): + pass + + instance = SomeModel(dt=datetime.now(), + d=date.today(), + something=some_value, + t=datetime.now().time()) + content_file = ContentFile(b'%PDF') + content_file.name = 'foo.pdf' + instance.img1 = content_file + instance.img2 = 'foo.png' + instance.method = method + instance.nonfield = 'hello' + data = utils.serialize_instance(instance) + instance2 = utils.deserialize_instance(SomeModel, data) + self.assertEqual(getattr(instance, 'method', None), method) + self.assertEqual(getattr(instance2, 'method', None), None) + self.assertEqual(instance2.something, some_value) + self.assertEqual(instance2.img1.name, 'foo.pdf') + self.assertEqual(instance2.img2.name, 'foo.png') + self.assertEqual(instance2.img3.name, '') + self.assertEqual(instance.nonfield, instance2.nonfield) + self.assertEqual(instance.d, instance2.d) + self.assertEqual(instance.dt.date(), instance2.dt.date()) + for t1, t2 in [(instance.t, instance2.t), + (instance.dt.time(), instance2.dt.time())]: + self.assertEqual(t1.hour, t2.hour) + self.assertEqual(t1.minute, t2.minute) + self.assertEqual(t1.second, t2.second) + self.assertEqual(int(t1.microsecond / 1000), + int(t2.microsecond / 1000)) + + def test_serializer_binary_field(self): + class SomeBinaryModel(models.Model): +~~ bb = models.BinaryField() +~~ bb_empty = models.BinaryField() + + instance = SomeBinaryModel(bb=b'some binary data') + + serialized = utils.serialize_instance(instance) + deserialized = utils.deserialize_instance(SomeBinaryModel, serialized) + + self.assertEqual(serialized['bb'], 'c29tZSBiaW5hcnkgZGF0YQ==') + self.assertEqual(serialized['bb_empty'], '') + self.assertEqual(deserialized.bb, b'some binary data') + self.assertEqual(deserialized.bb_empty, b'') + + def test_build_absolute_uri(self): + self.assertEqual( + utils.build_absolute_uri(None, '/foo'), + 'http://example.com/foo') + self.assertEqual( + utils.build_absolute_uri(None, '/foo', protocol='ftp'), + 'ftp://example.com/foo') + self.assertEqual( + utils.build_absolute_uri(None, 'http://foo.com/bar'), + 'http://foo.com/bar') + + def test_int_to_base36(self): + n = 55798679658823689999 + + +## ... source file continues with no further models examples... + +``` + + +## Example 4 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / models.py**](https://github.com/jazzband/django-axes/blob/master/axes/./models.py) + +```python +# models.py +~~from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class AccessBase(models.Model): +~~ user_agent = models.CharField(_("User Agent"), max_length=255, db_index=True) + +~~ ip_address = models.GenericIPAddressField(_("IP Address"), null=True, db_index=True) + +~~ username = models.CharField(_("Username"), max_length=255, null=True, db_index=True) + +~~ http_accept = models.CharField(_("HTTP Accept"), max_length=1025) + +~~ path_info = models.CharField(_("Path"), max_length=255) + +~~ attempt_time = models.DateTimeField(_("Attempt Time"), auto_now_add=True) + + class Meta: + app_label = "axes" + abstract = True + ordering = ["-attempt_time"] + + +class AccessAttempt(AccessBase): +~~ get_data = models.TextField(_("GET Data")) + +~~ post_data = models.TextField(_("POST Data")) + +~~ failures_since_start = models.PositiveIntegerField(_("Failed Logins")) + + def __str__(self): + return f"Attempted Access: {self.attempt_time}" + + class Meta: + verbose_name = _("access attempt") + verbose_name_plural = _("access attempts") + + +class AccessLog(AccessBase): +~~ logout_time = models.DateTimeField(_("Logout Time"), null=True, blank=True) + + def __str__(self): + return f"Access Log for {self.username} @ {self.attempt_time}" + + class Meta: + verbose_name = _("access log") + verbose_name_plural = _("access logs") + + + +## ... source file continues with no further models examples... + +``` + + +## Example 5 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / migrations / 0008_auto_20150208_2149.py**](https://github.com/divio/django-cms/blob/develop/cms/migrations/0008_auto_20150208_2149.py) + +```python +# 0008_auto_20150208_2149.py +from __future__ import unicode_literals + +~~from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('cms', '0007_auto_20141028_1559'), + ] + + operations = [ + migrations.AlterField( + model_name='title', + name='redirect', +~~ field=models.CharField(max_length=2048, null=True, verbose_name='redirect', blank=True), + preserve_default=True, + ), + ] + + + +## ... source file continues with no further models examples... + +``` + + +## Example 6 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / admin / __init__.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/admin/__init__.py) + +```python +# __init__.py +import six +import operator +from functools import update_wrapper +from six.moves import reduce +from typing import Tuple, Dict, Callable # NOQA + +from django.apps import apps +from django.http import HttpResponse, HttpResponseNotFound +from django.conf import settings +~~from django.db import models +from django.db.models.query import QuerySet +from django.utils.encoding import smart_str +from django.utils.translation import gettext as _ +from django.utils.text import get_text_list +from django.contrib import admin + +from django_extensions.admin.widgets import ForeignKeySearchInput + + +class ForeignKeyAutocompleteAdminMixin: + + related_search_fields = {} # type: Dict[str, Tuple[str]] + related_string_functions = {} # type: Dict[str, Callable] + autocomplete_limit = getattr(settings, 'FOREIGNKEY_AUTOCOMPLETE_LIMIT', None) + + def get_urls(self): + from django.urls import path + + def wrap(view): + def wrapper(*args, **kwargs): + return self.admin_site.admin_view(view)(*args, **kwargs) + return update_wrapper(wrapper, view) + + return [ + + +## ... source file abbreviated to get to models examples ... + + + data = ''.join([six.u('%s|%s\n') % (to_string_function(f), f.pk) for f in queryset]) + elif object_pk: + try: + obj = queryset.get(pk=object_pk) + except Exception: # FIXME: use stricter exception checking + pass + else: + data = to_string_function(obj) + return HttpResponse(data, content_type='text/plain') + return HttpResponseNotFound() + + def get_related_filter(self, model, request): + return None + + def get_help_text(self, field_name, model_name): + searchable_fields = self.related_search_fields.get(field_name, None) + if searchable_fields: + help_kwargs = { + 'model_name': model_name, + 'field_list': get_text_list(searchable_fields, _('and')), + } + return _('Use the left field to do %(model_name)s lookups in the fields %(field_list)s.') % help_kwargs + return '' + + def formfield_for_dbfield(self, db_field, **kwargs): +~~ if isinstance(db_field, models.ForeignKey) and db_field.name in self.related_search_fields: + help_text = self.get_help_text(db_field.name, db_field.remote_field.model._meta.object_name) + if kwargs.get('help_text'): + help_text = six.u('%s %s' % (kwargs['help_text'], help_text)) + kwargs['widget'] = ForeignKeySearchInput(db_field.remote_field, self.related_search_fields[db_field.name]) + kwargs['help_text'] = help_text + return super().formfield_for_dbfield(db_field, **kwargs) + + +class ForeignKeyAutocompleteAdmin(ForeignKeyAutocompleteAdminMixin, admin.ModelAdmin): + pass + + +class ForeignKeyAutocompleteTabularInline(ForeignKeyAutocompleteAdminMixin, admin.TabularInline): + pass + + +class ForeignKeyAutocompleteStackedInline(ForeignKeyAutocompleteAdminMixin, admin.StackedInline): + pass + + + +## ... source file continues with no further models examples... + +``` + + +## Example 7 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / migrations / 0006_auto_20160623_1627.py**](https://github.com/divio/django-filer/blob/develop/filer/migrations/0006_auto_20160623_1627.py) + +```python +# 0006_auto_20160623_1627.py +from __future__ import unicode_literals + +import django.db.models.deletion +~~from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('filer', '0005_auto_20160623_1425'), + ] + + operations = [ + migrations.AlterField( + model_name='image', + name='file_ptr', +~~ field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='%(app_label)s_%(class)s_file', serialize=False, to='filer.File'), + ), + ] + + + +## ... source file continues with no further models examples... + +``` + + +## Example 8 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / filterset.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./filterset.py) + +```python +# filterset.py +import copy +from collections import OrderedDict + +from django import forms +~~from django.db import models +from django.db.models.constants import LOOKUP_SEP +from django.db.models.fields.related import ( + ManyToManyRel, + ManyToOneRel, + OneToOneRel +) + +from .conf import settings +from .constants import ALL_FIELDS +from .filters import ( + BaseInFilter, + BaseRangeFilter, + BooleanFilter, + CharFilter, + ChoiceFilter, + DateFilter, + DateTimeFilter, + DurationFilter, + Filter, + ModelChoiceFilter, + ModelMultipleChoiceFilter, + NumberFilter, + TimeFilter, + UUIDFilter + + +## ... source file abbreviated to get to models examples ... + + + if isinstance(obj, Filter) + ] + + for filter_name, f in filters: + if getattr(f, 'field_name', None) is None: + f.field_name = filter_name + + filters.sort(key=lambda x: x[1].creation_counter) + + known = set(attrs) + + def visit(name): + known.add(name) + return name + + base_filters = [ + (visit(name), f) + for base in bases if hasattr(base, 'declared_filters') + for name, f in base.declared_filters.items() if name not in known + ] + + return OrderedDict(base_filters + filters) + + +FILTER_FOR_DBFIELD_DEFAULTS = { +~~ models.AutoField: {'filter_class': NumberFilter}, +~~ models.CharField: {'filter_class': CharFilter}, +~~ models.TextField: {'filter_class': CharFilter}, +~~ models.BooleanField: {'filter_class': BooleanFilter}, +~~ models.DateField: {'filter_class': DateFilter}, +~~ models.DateTimeField: {'filter_class': DateTimeFilter}, +~~ models.TimeField: {'filter_class': TimeFilter}, +~~ models.DurationField: {'filter_class': DurationFilter}, +~~ models.DecimalField: {'filter_class': NumberFilter}, +~~ models.SmallIntegerField: {'filter_class': NumberFilter}, +~~ models.IntegerField: {'filter_class': NumberFilter}, +~~ models.PositiveIntegerField: {'filter_class': NumberFilter}, +~~ models.PositiveSmallIntegerField: {'filter_class': NumberFilter}, +~~ models.FloatField: {'filter_class': NumberFilter}, +~~ models.NullBooleanField: {'filter_class': BooleanFilter}, +~~ models.SlugField: {'filter_class': CharFilter}, +~~ models.EmailField: {'filter_class': CharFilter}, +~~ models.FilePathField: {'filter_class': CharFilter}, +~~ models.URLField: {'filter_class': CharFilter}, +~~ models.GenericIPAddressField: {'filter_class': CharFilter}, +~~ models.CommaSeparatedIntegerField: {'filter_class': CharFilter}, +~~ models.UUIDField: {'filter_class': UUIDFilter}, + +~~ models.OneToOneField: { + 'filter_class': ModelChoiceFilter, + 'extra': lambda f: { + 'queryset': remote_queryset(f), + 'to_field_name': f.remote_field.field_name, + 'null_label': settings.NULL_CHOICE_LABEL if f.null else None, + } + }, +~~ models.ForeignKey: { + 'filter_class': ModelChoiceFilter, + 'extra': lambda f: { + 'queryset': remote_queryset(f), + 'to_field_name': f.remote_field.field_name, + 'null_label': settings.NULL_CHOICE_LABEL if f.null else None, + } + }, +~~ models.ManyToManyField: { + 'filter_class': ModelMultipleChoiceFilter, + 'extra': lambda f: { + 'queryset': remote_queryset(f), + } + }, + + OneToOneRel: { + 'filter_class': ModelChoiceFilter, + 'extra': lambda f: { + 'queryset': remote_queryset(f), + 'null_label': settings.NULL_CHOICE_LABEL if f.null else None, + } + }, + ManyToOneRel: { + 'filter_class': ModelMultipleChoiceFilter, + 'extra': lambda f: { + 'queryset': remote_queryset(f), + } + }, + ManyToManyRel: { + 'filter_class': ModelMultipleChoiceFilter, + 'extra': lambda f: { + 'queryset': remote_queryset(f), + } + + +## ... source file abbreviated to get to models examples ... + + + queryset = self._meta.model._default_manager.all() + model = queryset.model + + self.is_bound = data is not None + self.data = data or {} + self.queryset = queryset + self.request = request + self.form_prefix = prefix + + self.filters = copy.deepcopy(self.base_filters) + + for filter_ in self.filters.values(): + filter_.model = model + filter_.parent = self + + def is_valid(self): + return self.is_bound and self.form.is_valid() + + @property + def errors(self): + return self.form.errors + + def filter_queryset(self, queryset): + for name, value in self.form.cleaned_data.items(): + queryset = self.filters[name].filter(queryset, value) +~~ assert isinstance(queryset, models.QuerySet), \ + "Expected '%s.%s' to return a QuerySet, but got a %s instead." \ + % (type(self).__name__, name, type(queryset).__name__) + return queryset + + @property + def qs(self): + if not hasattr(self, '_qs'): + qs = self.queryset.all() + if self.is_bound: + self.errors + qs = self.filter_queryset(qs) + self._qs = qs + return self._qs + + def get_form_class(self): + fields = OrderedDict([ + (name, filter_.field) + for name, filter_ in self.filters.items()]) + + return type(str('%sForm' % self.__class__.__name__), + (self._meta.form,), fields) + + @property + def form(self): + + +## ... source file abbreviated to get to models examples ... + + + "%s resolved field '%s' with '%s' lookup to an unrecognized field " + "type %s. Try adding an override to 'Meta.filter_overrides'. See: " + "https://django-filter.readthedocs.io/en/master/ref/filterset.html" + "#customise-filter-generation-with-filter-overrides" + ) % (cls.__name__, field_name, lookup_expr, field.__class__.__name__) + + return filter_class(**default) + + @classmethod + def filter_for_lookup(cls, field, lookup_type): + DEFAULTS = dict(cls.FILTER_DEFAULTS) + if hasattr(cls, '_meta'): + DEFAULTS.update(cls._meta.filter_overrides) + + data = try_dbfield(DEFAULTS.get, field.__class__) or {} + filter_class = data.get('filter_class') + params = data.get('extra', lambda field: {})(field) + + if not filter_class: + return None, {} + + if lookup_type == 'exact' and getattr(field, 'choices', None): + return ChoiceFilter, {'choices': field.choices} + + if lookup_type == 'isnull': +~~ data = try_dbfield(DEFAULTS.get, models.BooleanField) + + filter_class = data.get('filter_class') + params = data.get('extra', lambda field: {})(field) + return filter_class, params + + if lookup_type == 'in': + class ConcreteInFilter(BaseInFilter, filter_class): + pass + ConcreteInFilter.__name__ = cls._csv_filter_class_name( + filter_class, lookup_type + ) + + return ConcreteInFilter, params + + if lookup_type == 'range': + class ConcreteRangeFilter(BaseRangeFilter, filter_class): + pass + ConcreteRangeFilter.__name__ = cls._csv_filter_class_name( + filter_class, lookup_type + ) + + return ConcreteRangeFilter, params + + return filter_class, params + + +## ... source file continues with no further models examples... + +``` + + +## Example 9 from django-flexible-subscriptions +[django-flexible-subscriptions](https://github.com/studybuffalo/django-flexible-subscriptions) +([project documentation](https://django-flexible-subscriptions.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-flexible-subscriptions/)) +provides boilerplate code for adding subscription and recurrent billing +to [Django](/django.html) web applications. Various payment providers +can be added on the back end to run the transactions. + +The django-flexible-subscriptions project is open sourced under the +[GNU General Public License v3.0](https://github.com/studybuffalo/django-flexible-subscriptions/blob/master/LICENSE). + +[**django-flexible-subscriptions / subscriptions / models.py**](https://github.com/studybuffalo/django-flexible-subscriptions/blob/master/subscriptions/./models.py) + +```python +# models.py +from datetime import timedelta +from uuid import uuid4 + +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group +from django.core.validators import MinValueValidator +~~from django.db import models +from django.utils.translation import gettext_lazy as _ + + +ONCE = '0' +SECOND = '1' +MINUTE = '2' +HOUR = '3' +DAY = '4' +WEEK = '5' +MONTH = '6' +YEAR = '7' +RECURRENCE_UNIT_CHOICES = ( + (ONCE, 'once'), + (SECOND, 'second'), + (MINUTE, 'minute'), + (HOUR, 'hour'), + (DAY, 'day'), + (WEEK, 'week'), + (MONTH, 'month'), + (YEAR, 'year'), +) + + +class PlanTag(models.Model): +~~ tag = models.CharField( + help_text=_('the tag name'), + max_length=64, + unique=True, + ) + + class Meta: + ordering = ('tag',) + + def __str__(self): + return self.tag + + +class SubscriptionPlan(models.Model): +~~ id = models.UUIDField( + default=uuid4, + editable=False, + primary_key=True, + verbose_name='ID', + ) +~~ plan_name = models.CharField( + help_text=_('the name of the subscription plan'), + max_length=128, + ) +~~ slug = models.SlugField( + blank=True, + help_text=_('slug to reference the subscription plan'), + max_length=128, + null=True, + unique=True, + ) +~~ plan_description = models.CharField( + blank=True, + help_text=_('a description of the subscription plan'), + max_length=512, + null=True, + ) +~~ group = models.ForeignKey( + Group, + blank=True, + help_text=_('the Django auth group for this plan'), + null=True, +~~ on_delete=models.SET_NULL, + related_name='plans', + ) +~~ tags = models.ManyToManyField( + PlanTag, + blank=True, + help_text=_('any tags associated with this plan'), + related_name='plans', + ) +~~ grace_period = models.PositiveIntegerField( + default=0, + help_text=_( + 'how many days after the subscription ends before the ' + 'subscription expires' + ), + ) + + class Meta: + ordering = ('plan_name',) + permissions = ( + ('subscriptions', 'Can interact with subscription details'), + ) + + def __str__(self): + return self.plan_name + + def display_tags(self): + if self.tags.count() > 3: + return '{}, ...'.format( + ', '.join(tag.tag for tag in self.tags.all()[:3]) + ) + + return ', '.join(tag.tag for tag in self.tags.all()[:3]) + + +class PlanCost(models.Model): +~~ id = models.UUIDField( + default=uuid4, + editable=False, + primary_key=True, + verbose_name='ID', + ) +~~ plan = models.ForeignKey( + SubscriptionPlan, + help_text=_('the subscription plan for these cost details'), +~~ on_delete=models.CASCADE, + related_name='costs', + ) +~~ slug = models.SlugField( + blank=True, + help_text=_('slug to reference these cost details'), + max_length=128, + null=True, + unique=True, + ) +~~ recurrence_period = models.PositiveSmallIntegerField( + default=1, + help_text=_('how often the plan is billed (per recurrence unit)'), + validators=[MinValueValidator(1)], + ) +~~ recurrence_unit = models.CharField( + choices=RECURRENCE_UNIT_CHOICES, + default=MONTH, + max_length=1, + ) +~~ cost = models.DecimalField( + blank=True, + decimal_places=4, + help_text=_('the cost per recurrence of the plan'), + max_digits=19, + null=True, + ) + + class Meta: + ordering = ('recurrence_unit', 'recurrence_period', 'cost',) + + @property + def display_recurrent_unit_text(self): + conversion = { + ONCE: 'one-time', + SECOND: 'per second', + MINUTE: 'per minute', + HOUR: 'per hour', + DAY: 'per day', + WEEK: 'per week', + MONTH: 'per month', + YEAR: 'per year', + } + + return conversion[self.recurrence_unit] + + +## ... source file abbreviated to get to models examples ... + + + if self.recurrence_unit == SECOND: + delta = timedelta(seconds=self.recurrence_period) + elif self.recurrence_unit == MINUTE: + delta = timedelta(minutes=self.recurrence_period) + elif self.recurrence_unit == HOUR: + delta = timedelta(hours=self.recurrence_period) + elif self.recurrence_unit == DAY: + delta = timedelta(days=self.recurrence_period) + elif self.recurrence_unit == WEEK: + delta = timedelta(weeks=self.recurrence_period) + elif self.recurrence_unit == MONTH: + delta = timedelta( + days=30.4368 * self.recurrence_period + ) + elif self.recurrence_unit == YEAR: + delta = timedelta( + days=365.2425 * self.recurrence_period + ) + else: + return None + + return current + delta + + +class UserSubscription(models.Model): +~~ id = models.UUIDField( + default=uuid4, + editable=False, + primary_key=True, + verbose_name='ID', + ) +~~ user = models.ForeignKey( + get_user_model(), + help_text=_('the user this subscription applies to'), + null=True, +~~ on_delete=models.CASCADE, + related_name='subscriptions', + ) +~~ subscription = models.ForeignKey( + PlanCost, + help_text=_('the plan costs and billing frequency for this user'), + null=True, +~~ on_delete=models.CASCADE, + related_name='subscriptions' + ) +~~ date_billing_start = models.DateTimeField( + blank=True, + help_text=_('the date to start billing this subscription'), + null=True, + verbose_name='billing start date', + ) +~~ date_billing_end = models.DateTimeField( + blank=True, + help_text=_('the date to finish billing this subscription'), + null=True, + verbose_name='billing start end', + ) +~~ date_billing_last = models.DateTimeField( + blank=True, + help_text=_('the last date this plan was billed'), + null=True, + verbose_name='last billing date', + ) +~~ date_billing_next = models.DateTimeField( + blank=True, + help_text=_('the next date billing is due'), + null=True, + verbose_name='next start date', + ) +~~ active = models.BooleanField( + default=True, + help_text=_('whether this subscription is active or not'), + ) +~~ cancelled = models.BooleanField( + default=False, + help_text=_('whether this subscription is cancelled or not'), + ) + + class Meta: + ordering = ('user', 'date_billing_start',) + + +class SubscriptionTransaction(models.Model): +~~ id = models.UUIDField( + default=uuid4, + editable=False, + primary_key=True, + verbose_name='ID', + ) +~~ user = models.ForeignKey( + get_user_model(), + help_text=_('the user that this subscription was billed for'), + null=True, +~~ on_delete=models.SET_NULL, + related_name='subscription_transactions' + ) +~~ subscription = models.ForeignKey( + PlanCost, + help_text=_('the plan costs that were billed'), + null=True, +~~ on_delete=models.SET_NULL, + related_name='transactions' + ) +~~ date_transaction = models.DateTimeField( + help_text=_('the datetime the transaction was billed'), + verbose_name='transaction date', + ) +~~ amount = models.DecimalField( + blank=True, + decimal_places=4, + help_text=_('how much was billed for the user'), + max_digits=19, + null=True, + ) + + class Meta: + ordering = ('date_transaction', 'user',) + + +class PlanList(models.Model): +~~ title = models.TextField( + blank=True, + help_text=_('title to display on the subscription plan list page'), + null=True, + ) +~~ slug = models.SlugField( + blank=True, + help_text=_('slug to reference the subscription plan list'), + max_length=128, + null=True, + unique=True, + ) +~~ subtitle = models.TextField( + blank=True, + help_text=_('subtitle to display on the subscription plan list page'), + null=True, + ) +~~ header = models.TextField( + blank=True, + help_text=_('header text to display on the subscription plan list page'), + null=True, + ) +~~ footer = models.TextField( + blank=True, + help_text=_('header text to display on the subscription plan list page'), + null=True, + ) +~~ active = models.BooleanField( + default=True, + help_text=_('whether this plan list is active or not.'), + ) + + def __str__(self): + return self.title + + +class PlanListDetail(models.Model): +~~ plan = models.ForeignKey( + SubscriptionPlan, +~~ on_delete=models.CASCADE, + related_name='plan_list_details', + ) +~~ plan_list = models.ForeignKey( + PlanList, +~~ on_delete=models.CASCADE, + related_name='plan_list_details', + ) +~~ html_content = models.TextField( + blank=True, + help_text=_('HTML content to display for plan'), + null=True, + ) +~~ subscribe_button_text = models.CharField( + blank=True, + default='Subscribe', + max_length=128, + null=True, + ) +~~ order = models.PositiveIntegerField( + default=1, + help_text=_('Order to display plan in (lower numbers displayed first)'), + ) + + def __str__(self): + return 'Plan List {} - {}'.format( + self.plan_list, self.plan.plan_name + ) + + + +## ... source file continues with no further models examples... + +``` + + +## Example 10 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / backends.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./backends.py) + +```python +# backends.py +from django.contrib.auth import get_user_model +~~from django.db import models +from guardian.conf import settings +from guardian.core import ObjectPermissionChecker +from guardian.ctypes import get_content_type +from guardian.exceptions import WrongAppError + + +def check_object_support(obj): +~~ return isinstance(obj, models.Model) + + +def check_user_support(user_obj): + if not user_obj.is_authenticated: + if settings.ANONYMOUS_USER_NAME is None: + return False, user_obj + User = get_user_model() + lookup = {User.USERNAME_FIELD: settings.ANONYMOUS_USER_NAME} + user_obj = User.objects.get(**lookup) + + return True, user_obj + + +def check_support(user_obj, obj): + obj_support = check_object_support(obj) + user_support, user_obj = check_user_support(user_obj) + return obj_support and user_support, user_obj + + +class ObjectPermissionBackend: + supports_object_permissions = True + supports_anonymous_user = True + supports_inactive_user = True + + + +## ... source file continues with no further models examples... + +``` + + +## Example 11 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / signals.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./signals.py) + +```python +# signals.py +~~from django.db import models + +from haystack.exceptions import NotHandled + + +class BaseSignalProcessor(object): + + def __init__(self, connections, connection_router): + self.connections = connections + self.connection_router = connection_router + self.setup() + + def setup(self): + pass + + def teardown(self): + pass + + def handle_save(self, sender, instance, **kwargs): + using_backends = self.connection_router.for_write(instance=instance) + + for using in using_backends: + try: + index = self.connections[using].get_unified_index().get_index(sender) + index.update_object(instance, using=using) + except NotHandled: + pass + + def handle_delete(self, sender, instance, **kwargs): + using_backends = self.connection_router.for_write(instance=instance) + + for using in using_backends: + try: + index = self.connections[using].get_unified_index().get_index(sender) + index.remove_object(instance, using=using) + except NotHandled: + pass + + +class RealtimeSignalProcessor(BaseSignalProcessor): + + def setup(self): +~~ models.signals.post_save.connect(self.handle_save) +~~ models.signals.post_delete.connect(self.handle_delete) + + def teardown(self): +~~ models.signals.post_save.disconnect(self.handle_save) +~~ models.signals.post_delete.disconnect(self.handle_delete) + + + +## ... source file continues with no further models examples... + +``` + + +## Example 12 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / models.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./models.py) + +```python +# models.py +~~from django.db import models +from django.utils import timezone +from django.utils.encoding import python_2_unicode_compatible +from django.utils.translation import ugettext_lazy as _ + + +@python_2_unicode_compatible +class Bookmark(models.Model): +~~ url = models.URLField(verbose_name=_('URL')) +~~ title = models.CharField(verbose_name=_('title'), max_length=255) +~~ user = models.PositiveIntegerField(verbose_name=_('user')) +~~ date_add = models.DateTimeField(verbose_name=_('date created'), default=timezone.now) + + class Meta: + verbose_name = _('bookmark') + verbose_name_plural = _('bookmarks') + ordering = ('date_add',) + + def __str__(self): + return self.title + + +@python_2_unicode_compatible +class PinnedApplication(models.Model): +~~ app_label = models.CharField(verbose_name=_('application name'), max_length=255) +~~ user = models.PositiveIntegerField(verbose_name=_('user')) +~~ date_add = models.DateTimeField(verbose_name=_('date created'), default=timezone.now) + + class Meta: + verbose_name = _('pinned application') + verbose_name_plural = _('pinned applications') + ordering = ('date_add',) + + def __str__(self): + return self.app_label + + + + +## ... source file continues with no further models examples... + +``` + + +## Example 13 from django-jsonfield +[django-jsonfield](https://github.com/dmkoch/django-jsonfield) +([jsonfield on PyPi](https://pypi.org/project/jsonfield/)) is a +[Django](/django.html) code library that makes it easier to store validated +JSON in a [Django object-relational mapper (ORM)](/django-orm.html) database +model. + +The django-jsonfield project is open source under the +[MIT license](https://github.com/dmkoch/django-jsonfield/blob/master/LICENSE). + +[**django-jsonfield / src/jsonfield / fields.py**](https://github.com/dmkoch/django-jsonfield/blob/master/src/jsonfield/./fields.py) + +```python +# fields.py +import copy +import json +import warnings + +~~from django.db import models +from django.forms import ValidationError +from django.utils.translation import gettext_lazy as _ + +from . import forms +from .encoder import JSONEncoder +from .json import JSONString, checked_loads + +DEFAULT_DUMP_KWARGS = { + 'cls': JSONEncoder, +} + +DEFAULT_LOAD_KWARGS = {} + +INVALID_JSON_WARNING = ( + '{0!s} failed to load invalid json ({1}) from the database. The value has ' + 'been returned as a string instead.' +) + + +class JSONFieldMixin(models.Field): + form_class = forms.JSONField + + def __init__(self, *args, dump_kwargs=None, load_kwargs=None, **kwargs): + self.dump_kwargs = DEFAULT_DUMP_KWARGS if dump_kwargs is None else dump_kwargs + + +## ... source file abbreviated to get to models examples ... + + + def get_prep_value(self, value): + if self.null and value is None: + return None + return json.dumps(value, **self.dump_kwargs) + + def value_to_string(self, obj): + value = self.value_from_object(obj) + return json.dumps(value, **self.dump_kwargs) + + def formfield(self, **kwargs): + kwargs.setdefault('form_class', self.form_class) + if issubclass(kwargs['form_class'], forms.JSONField): + kwargs.setdefault('dump_kwargs', self.dump_kwargs) + kwargs.setdefault('load_kwargs', self.load_kwargs) + + return super().formfield(**kwargs) + + def get_default(self): + if self.has_default(): + if callable(self.default): + return self.default() + return copy.deepcopy(self.default) + return super().get_default() + + +~~class JSONField(JSONFieldMixin, models.TextField): + + def formfield(self, **kwargs): + field = super().formfield(**kwargs) + if isinstance(field, forms.JSONField): + field.dump_kwargs.setdefault('indent', 4) + field.dump_kwargs.setdefault('ensure_ascii', False) + return field + + +~~class JSONCharField(JSONFieldMixin, models.CharField): + + + +## ... source file continues with no further models examples... + +``` + + +## Example 14 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / models.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./models.py) + +```python +# models.py +from django.core.exceptions import ImproperlyConfigured +~~from django.db import models, transaction, router +from django.db.models.signals import post_save, pre_save +from django.utils.translation import gettext_lazy as _ + +from model_utils.fields import ( + AutoCreatedField, + AutoLastModifiedField, + StatusField, + MonitorField, + UUIDField, +) +from model_utils.managers import ( + QueryManager, + SoftDeletableManager, +) + +from django.db.models.functions import Now +now = Now() + + +class TimeStampedModel(models.Model): + created = AutoCreatedField(_('created')) + modified = AutoLastModifiedField(_('modified')) + + def save(self, *args, **kwargs): + if 'update_fields' in kwargs and 'modified' not in kwargs['update_fields']: + kwargs['update_fields'] += ['modified'] + super().save(*args, **kwargs) + + class Meta: + abstract = True + + +class TimeFramedModel(models.Model): +~~ start = models.DateTimeField(_('start'), null=True, blank=True) +~~ end = models.DateTimeField(_('end'), null=True, blank=True) + + class Meta: + abstract = True + + +class StatusModel(models.Model): + status = StatusField(_('status')) + status_changed = MonitorField(_('status changed'), monitor='status') + + class Meta: + abstract = True + + +def add_status_query_managers(sender, **kwargs): + if not issubclass(sender, StatusModel): + return + + default_manager = sender._meta.default_manager + + for value, display in getattr(sender, 'STATUS', ()): + if _field_exists(sender, value): + raise ImproperlyConfigured( + "StatusModel: Model '%s' has a field named '%s' which " + "conflicts with a status of the same name." + % (sender.__name__, value) + ) + sender.add_to_class(value, QueryManager(status=value)) + + sender._meta.default_manager_name = default_manager.name + + +def add_timeframed_query_manager(sender, **kwargs): + if not issubclass(sender, TimeFramedModel): + return + if _field_exists(sender, 'timeframed'): + raise ImproperlyConfigured( + "Model '%s' has a field named 'timeframed' " + "which conflicts with the TimeFramedModel manager." + % sender.__name__ + ) + sender.add_to_class('timeframed', QueryManager( +~~ (models.Q(start__lte=now) | models.Q(start__isnull=True)) +~~ & (models.Q(end__gte=now) | models.Q(end__isnull=True)) + )) + + +models.signals.class_prepared.connect(add_status_query_managers) +models.signals.class_prepared.connect(add_timeframed_query_manager) + + +def _field_exists(model_class, field_name): + return field_name in [f.attname for f in model_class._meta.local_fields] + + +class SoftDeletableModel(models.Model): +~~ is_removed = models.BooleanField(default=False) + + class Meta: + abstract = True + + objects = SoftDeletableManager() +~~ all_objects = models.Manager() + + def delete(self, using=None, soft=True, *args, **kwargs): + if soft: + self.is_removed = True + self.save(using=using) + else: + return super().delete(using=using, *args, **kwargs) + + +class UUIDModel(models.Model): + id = UUIDField( + primary_key=True, + version=4, + editable=False, + ) + + class Meta: + abstract = True + + +class SaveSignalHandlingModel(models.Model): + class Meta: + abstract = True + + + +## ... source file continues with no further models examples... + +``` + + +## Example 15 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / models.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./models.py) + +```python +# models.py +import logging +from datetime import timedelta +from urllib.parse import parse_qsl, urlparse + +from django.apps import apps +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +~~from django.db import models, transaction +from django.urls import reverse +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ + +from .generators import generate_client_id, generate_client_secret +from .scopes import get_scopes_backend +from .settings import oauth2_settings +from .validators import RedirectURIValidator, WildcardSet + + +logger = logging.getLogger(__name__) + + +class AbstractApplication(models.Model): + CLIENT_CONFIDENTIAL = "confidential" + CLIENT_PUBLIC = "public" + CLIENT_TYPES = ( + (CLIENT_CONFIDENTIAL, _("Confidential")), + (CLIENT_PUBLIC, _("Public")), + ) + + GRANT_AUTHORIZATION_CODE = "authorization-code" + GRANT_IMPLICIT = "implicit" + GRANT_PASSWORD = "password" + GRANT_CLIENT_CREDENTIALS = "client-credentials" + GRANT_TYPES = ( + (GRANT_AUTHORIZATION_CODE, _("Authorization code")), + (GRANT_IMPLICIT, _("Implicit")), + (GRANT_PASSWORD, _("Resource owner password-based")), + (GRANT_CLIENT_CREDENTIALS, _("Client credentials")), + ) + +~~ id = models.BigAutoField(primary_key=True) +~~ client_id = models.CharField( + max_length=100, unique=True, default=generate_client_id, db_index=True + ) +~~ user = models.ForeignKey( + settings.AUTH_USER_MODEL, + related_name="%(app_label)s_%(class)s", +~~ null=True, blank=True, on_delete=models.CASCADE + ) + +~~ redirect_uris = models.TextField( + blank=True, help_text=_("Allowed URIs list, space separated"), + ) +~~ client_type = models.CharField(max_length=32, choices=CLIENT_TYPES) +~~ authorization_grant_type = models.CharField( + max_length=32, choices=GRANT_TYPES + ) +~~ client_secret = models.CharField( + max_length=255, blank=True, default=generate_client_secret, db_index=True + ) +~~ name = models.CharField(max_length=255, blank=True) +~~ skip_authorization = models.BooleanField(default=False) + +~~ created = models.DateTimeField(auto_now_add=True) +~~ updated = models.DateTimeField(auto_now=True) + + class Meta: + abstract = True + + def __str__(self): + return self.name or self.client_id + + @property + def default_redirect_uri(self): + if self.redirect_uris: + return self.redirect_uris.split().pop(0) + + assert False, ( + "If you are using implicit, authorization_code" + "or all-in-one grant_type, you must define " + "redirect_uris field in your Application model" + ) + + def redirect_uri_allowed(self, uri): + parsed_uri = urlparse(uri) + uqs_set = set(parse_qsl(parsed_uri.query)) + for allowed_uri in self.redirect_uris.split(): + parsed_allowed_uri = urlparse(allowed_uri) + + + +## ... source file abbreviated to get to models examples ... + + + + +class ApplicationManager(models.Manager): + def get_by_natural_key(self, client_id): + return self.get(client_id=client_id) + + +class Application(AbstractApplication): + objects = ApplicationManager() + + class Meta(AbstractApplication.Meta): + swappable = "OAUTH2_PROVIDER_APPLICATION_MODEL" + + def natural_key(self): + return (self.client_id,) + + +class AbstractGrant(models.Model): + CODE_CHALLENGE_PLAIN = "plain" + CODE_CHALLENGE_S256 = "S256" + CODE_CHALLENGE_METHODS = ( + (CODE_CHALLENGE_PLAIN, "plain"), + (CODE_CHALLENGE_S256, "S256") + ) + +~~ id = models.BigAutoField(primary_key=True) +~~ user = models.ForeignKey( +~~ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, + related_name="%(app_label)s_%(class)s" + ) +~~ code = models.CharField(max_length=255, unique=True) # code comes from oauthlib +~~ application = models.ForeignKey( +~~ oauth2_settings.APPLICATION_MODEL, on_delete=models.CASCADE + ) +~~ expires = models.DateTimeField() +~~ redirect_uri = models.CharField(max_length=255) +~~ scope = models.TextField(blank=True) + +~~ created = models.DateTimeField(auto_now_add=True) +~~ updated = models.DateTimeField(auto_now=True) + +~~ code_challenge = models.CharField(max_length=128, blank=True, default="") +~~ code_challenge_method = models.CharField( + max_length=10, blank=True, default="", choices=CODE_CHALLENGE_METHODS) + + def is_expired(self): + if not self.expires: + return True + + return timezone.now() >= self.expires + + def redirect_uri_allowed(self, uri): + return uri == self.redirect_uri + + def __str__(self): + return self.code + + class Meta: + abstract = True + + +class Grant(AbstractGrant): + class Meta(AbstractGrant.Meta): + swappable = "OAUTH2_PROVIDER_GRANT_MODEL" + + +class AbstractAccessToken(models.Model): +~~ id = models.BigAutoField(primary_key=True) +~~ user = models.ForeignKey( +~~ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True, + related_name="%(app_label)s_%(class)s" + ) +~~ source_refresh_token = models.OneToOneField( +~~ oauth2_settings.REFRESH_TOKEN_MODEL, on_delete=models.SET_NULL, blank=True, null=True, + related_name="refreshed_access_token" + ) +~~ token = models.CharField(max_length=255, unique=True, ) +~~ application = models.ForeignKey( +~~ oauth2_settings.APPLICATION_MODEL, on_delete=models.CASCADE, blank=True, null=True, + ) +~~ expires = models.DateTimeField() +~~ scope = models.TextField(blank=True) + +~~ created = models.DateTimeField(auto_now_add=True) +~~ updated = models.DateTimeField(auto_now=True) + + def is_valid(self, scopes=None): + return not self.is_expired() and self.allow_scopes(scopes) + + def is_expired(self): + if not self.expires: + return True + + return timezone.now() >= self.expires + + def allow_scopes(self, scopes): + if not scopes: + return True + + provided_scopes = set(self.scope.split()) + resource_scopes = set(scopes) + + return resource_scopes.issubset(provided_scopes) + + def revoke(self): + self.delete() + + @property + def scopes(self): + all_scopes = get_scopes_backend().get_all_scopes() + token_scopes = self.scope.split() + return {name: desc for name, desc in all_scopes.items() if name in token_scopes} + + def __str__(self): + return self.token + + class Meta: + abstract = True + + +class AccessToken(AbstractAccessToken): + class Meta(AbstractAccessToken.Meta): + swappable = "OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL" + + +class AbstractRefreshToken(models.Model): +~~ id = models.BigAutoField(primary_key=True) +~~ user = models.ForeignKey( +~~ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, + related_name="%(app_label)s_%(class)s" + ) +~~ token = models.CharField(max_length=255) +~~ application = models.ForeignKey( +~~ oauth2_settings.APPLICATION_MODEL, on_delete=models.CASCADE) +~~ access_token = models.OneToOneField( +~~ oauth2_settings.ACCESS_TOKEN_MODEL, on_delete=models.SET_NULL, blank=True, null=True, + related_name="refresh_token" + ) + +~~ created = models.DateTimeField(auto_now_add=True) +~~ updated = models.DateTimeField(auto_now=True) +~~ revoked = models.DateTimeField(null=True) + + def revoke(self): + access_token_model = get_access_token_model() + refresh_token_model = get_refresh_token_model() + with transaction.atomic(): + self = refresh_token_model.objects.filter( + pk=self.pk, revoked__isnull=True + ).select_for_update().first() + if not self: + return + + try: + access_token_model.objects.get(id=self.access_token_id).revoke() + except access_token_model.DoesNotExist: + pass + self.access_token = None + self.revoked = timezone.now() + self.save() + + def __str__(self): + return self.token + + class Meta: + abstract = True + + +## ... source file continues with no further models examples... + +``` + + +## Example 16 from django-push-notifications +[django-push-notifications](https://github.com/jazzband/django-push-notifications) +is a [Django](/django.html) app for storing and interacting with +push notification services such as +[Google's Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/) +and +[Apple Notifications](https://developer.apple.com/notifications/). +The django-push-notification project's source code is available +open source under the +[MIT license](https://github.com/jazzband/django-push-notifications/blob/master/LICENSE). + +[**django-push-notifications / push_notifications / models.py**](https://github.com/jazzband/django-push-notifications/blob/master/push_notifications/./models.py) + +```python +# models.py +~~from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from .fields import HexIntegerField +from .settings import PUSH_NOTIFICATIONS_SETTINGS as SETTINGS + + +CLOUD_MESSAGE_TYPES = ( + ("FCM", "Firebase Cloud Message"), + ("GCM", "Google Cloud Message"), +) + +BROWSER_TYPES = ( + ("CHROME", "Chrome"), + ("FIREFOX", "Firefox"), + ("OPERA", "Opera"), +) + + +class Device(models.Model): +~~ name = models.CharField(max_length=255, verbose_name=_("Name"), blank=True, null=True) +~~ active = models.BooleanField( + verbose_name=_("Is active"), default=True, + help_text=_("Inactive devices will not be sent notifications") + ) +~~ user = models.ForeignKey( +~~ SETTINGS["USER_MODEL"], blank=True, null=True, on_delete=models.CASCADE + ) +~~ date_created = models.DateTimeField( + verbose_name=_("Creation date"), auto_now_add=True, null=True + ) +~~ application_id = models.CharField( + max_length=64, verbose_name=_("Application ID"), + help_text=_( + "Opaque application identity, should be filled in for multiple" + " key/certificate access" + ), + blank=True, null=True + ) + + class Meta: + abstract = True + + def __str__(self): + return ( + self.name or + str(self.device_id or "") or + "{} for {}".format(self.__class__.__name__, self.user or "unknown user") + ) + + +class GCMDeviceManager(models.Manager): + def get_queryset(self): + return GCMDeviceQuerySet(self.model) + + + + +## ... source file abbreviated to get to models examples ... + + + + app_ids = self.filter(active=True).order_by( + "application_id" + ).values_list("application_id", flat=True).distinct() + response = [] + for cloud_type in ("FCM", "GCM"): + for app_id in app_ids: + reg_ids = list( + self.filter( + active=True, cloud_message_type=cloud_type, application_id=app_id).values_list( + "registration_id", flat=True + ) + ) + if reg_ids: + r = gcm_send_message(reg_ids, data, cloud_type, application_id=app_id, **kwargs) + response.append(r) + + return response + + +class GCMDevice(Device): + device_id = HexIntegerField( + verbose_name=_("Device ID"), blank=True, null=True, db_index=True, + help_text=_("ANDROID_ID / TelephonyManager.getDeviceId() (always as hex)") + ) +~~ registration_id = models.TextField(verbose_name=_("Registration ID"), unique=SETTINGS["UNIQUE_REG_ID"]) +~~ cloud_message_type = models.CharField( + verbose_name=_("Cloud Message Type"), max_length=3, + choices=CLOUD_MESSAGE_TYPES, default="GCM", + help_text=_("You should choose FCM or GCM") + ) + objects = GCMDeviceManager() + + class Meta: + verbose_name = _("GCM device") + + def send_message(self, message, **kwargs): + from .gcm import send_message as gcm_send_message + + data = kwargs.pop("extra", {}) + if message is not None: + data["message"] = message + + return gcm_send_message( + self.registration_id, data, self.cloud_message_type, + application_id=self.application_id, **kwargs + ) + + +class APNSDeviceManager(models.Manager): + def get_queryset(self): + + +## ... source file abbreviated to get to models examples ... + + + +class APNSDeviceQuerySet(models.query.QuerySet): + def send_message(self, message, creds=None, **kwargs): + if self: + from .apns import apns_send_bulk_message + + app_ids = self.filter(active=True).order_by("application_id")\ + .values_list("application_id", flat=True).distinct() + res = [] + for app_id in app_ids: + reg_ids = list(self.filter(active=True, application_id=app_id).values_list( + "registration_id", flat=True) + ) + r = apns_send_bulk_message( + registration_ids=reg_ids, alert=message, application_id=app_id, + creds=creds, **kwargs + ) + if hasattr(r, "keys"): + res += [r] + elif hasattr(r, "__getitem__"): + res += r + return res + + +class APNSDevice(Device): +~~ device_id = models.UUIDField( + verbose_name=_("Device ID"), blank=True, null=True, db_index=True, + help_text="UDID / UIDevice.identifierForVendor()" + ) +~~ registration_id = models.CharField( + verbose_name=_("Registration ID"), max_length=200, unique=SETTINGS["UNIQUE_REG_ID"] + ) + + objects = APNSDeviceManager() + + class Meta: + verbose_name = _("APNS device") + + def send_message(self, message, creds=None, **kwargs): + from .apns import apns_send_message + + return apns_send_message( + registration_id=self.registration_id, + alert=message, + application_id=self.application_id, creds=creds, + **kwargs + ) + + +class WNSDeviceManager(models.Manager): + def get_queryset(self): + return WNSDeviceQuerySet(self.model) + + +class WNSDeviceQuerySet(models.query.QuerySet): + def send_message(self, message, **kwargs): + from .wns import wns_send_bulk_message + + app_ids = self.filter(active=True).order_by("application_id").values_list( + "application_id", flat=True + ).distinct() + res = [] + for app_id in app_ids: + reg_ids = self.filter(active=True, application_id=app_id).values_list( + "registration_id", flat=True + ) + r = wns_send_bulk_message(uri_list=list(reg_ids), message=message, **kwargs) + if hasattr(r, "keys"): + res += [r] + elif hasattr(r, "__getitem__"): + res += r + + return res + + +class WNSDevice(Device): +~~ device_id = models.UUIDField( + verbose_name=_("Device ID"), blank=True, null=True, db_index=True, + help_text=_("GUID()") + ) +~~ registration_id = models.TextField(verbose_name=_("Notification URI"), unique=SETTINGS["UNIQUE_REG_ID"]) + + objects = WNSDeviceManager() + + class Meta: + verbose_name = _("WNS device") + + def send_message(self, message, **kwargs): + from .wns import wns_send_message + + return wns_send_message( + uri=self.registration_id, message=message, application_id=self.application_id, + **kwargs + ) + + +class WebPushDeviceManager(models.Manager): + def get_queryset(self): + return WebPushDeviceQuerySet(self.model) + + +class WebPushDeviceQuerySet(models.query.QuerySet): + def send_message(self, message, **kwargs): + devices = self.filter(active=True).order_by("application_id").distinct() + res = [] + for device in devices: + res.append(device.send_message(message)) + + return res + + +class WebPushDevice(Device): +~~ registration_id = models.TextField(verbose_name=_("Registration ID"), unique=SETTINGS["UNIQUE_REG_ID"]) +~~ p256dh = models.CharField( + verbose_name=_("User public encryption key"), + max_length=88) +~~ auth = models.CharField( + verbose_name=_("User auth secret"), + max_length=24) +~~ browser = models.CharField( + verbose_name=_("Browser"), max_length=10, + choices=BROWSER_TYPES, default=BROWSER_TYPES[0][0], + help_text=_("Currently only support to Chrome, Firefox and Opera browsers") + ) + objects = WebPushDeviceManager() + + class Meta: + verbose_name = _("WebPush device") + + @property + def device_id(self): + return None + + def send_message(self, message, **kwargs): + from .webpush import webpush_send_message + + return webpush_send_message( + uri=self.registration_id, message=message, browser=self.browser, + auth=self.auth, p256dh=self.p256dh, application_id=self.application_id, **kwargs) + + + +## ... source file continues with no further models examples... + +``` + + +## Example 17 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / serializers.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./serializers.py) + +```python +# serializers.py +import copy +import inspect +import traceback +from collections import OrderedDict, defaultdict +from collections.abc import Mapping + +from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured +from django.core.exceptions import ValidationError as DjangoValidationError +~~from django.db import models +from django.db.models.fields import Field as DjangoModelField +from django.utils import timezone +from django.utils.functional import cached_property +from django.utils.translation import gettext_lazy as _ + +from rest_framework.compat import postgres_fields +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.fields import get_error_detail, set_value +from rest_framework.settings import api_settings +from rest_framework.utils import html, model_meta, representation +from rest_framework.utils.field_mapping import ( + ClassLookupDict, get_field_kwargs, get_nested_relation_kwargs, + get_relation_kwargs, get_url_kwargs +) +from rest_framework.utils.serializer_helpers import ( + BindingDict, BoundField, JSONBoundField, NestedBoundField, ReturnDict, + ReturnList +) +from rest_framework.validators import ( + UniqueForDateValidator, UniqueForMonthValidator, UniqueForYearValidator, + UniqueTogetherValidator +) + +from rest_framework.fields import ( # NOQA # isort:skip + + +## ... source file abbreviated to get to models examples ... + + + + if not self.allow_empty and len(data) == 0: + message = self.error_messages['empty'] + raise ValidationError({ + api_settings.NON_FIELD_ERRORS_KEY: [message] + }, code='empty') + + ret = [] + errors = [] + + for item in data: + try: + validated = self.child.run_validation(item) + except ValidationError as exc: + errors.append(exc.detail) + else: + ret.append(validated) + errors.append({}) + + if any(errors): + raise ValidationError(errors) + + return ret + + def to_representation(self, data): +~~ iterable = data.all() if isinstance(data, models.Manager) else data + + return [ + self.child.to_representation(item) for item in iterable + ] + + def validate(self, attrs): + return attrs + + def update(self, instance, validated_data): + raise NotImplementedError( + "Serializers with many=True do not support multiple update by " + "default, only multiple create. For updates it is unclear how to " + "deal with insertions and deletions. If you need to support " + "multiple update, use a `ListSerializer` class and override " + "`.update()` so you can specify the behavior exactly." + ) + + def create(self, validated_data): + return [ + self.child.create(attrs) for attrs in validated_data + ] + + def save(self, **kwargs): + assert 'commit' not in kwargs, ( + + +## ... source file abbreviated to get to models examples ... + + + module=serializer.__class__.__module__, + class_name=serializer.__class__.__name__ + ) + ) + + assert not any( + len(field.source_attrs) > 1 and + (field.source_attrs[0] in validated_data) and + (field.source_attrs[0] in model_field_info.relations) and + isinstance(validated_data[field.source_attrs[0]], (list, dict)) + for field in serializer._writable_fields + ), ( + 'The `.{method_name}()` method does not support writable dotted-source ' + 'fields by default.\nWrite an explicit `.{method_name}()` method for ' + 'serializer `{module}.{class_name}`, or set `read_only=True` on ' + 'dotted-source serializer fields.'.format( + method_name=method_name, + module=serializer.__class__.__module__, + class_name=serializer.__class__.__name__ + ) + ) + + +class ModelSerializer(Serializer): + serializer_field_mapping = { +~~ models.AutoField: IntegerField, +~~ models.BigIntegerField: IntegerField, +~~ models.BooleanField: BooleanField, +~~ models.CharField: CharField, +~~ models.CommaSeparatedIntegerField: CharField, +~~ models.DateField: DateField, +~~ models.DateTimeField: DateTimeField, +~~ models.DecimalField: DecimalField, +~~ models.DurationField: DurationField, +~~ models.EmailField: EmailField, +~~ models.Field: ModelField, +~~ models.FileField: FileField, +~~ models.FloatField: FloatField, +~~ models.ImageField: ImageField, +~~ models.IntegerField: IntegerField, +~~ models.NullBooleanField: BooleanField, +~~ models.PositiveIntegerField: IntegerField, +~~ models.PositiveSmallIntegerField: IntegerField, +~~ models.SlugField: SlugField, +~~ models.SmallIntegerField: IntegerField, +~~ models.TextField: CharField, +~~ models.TimeField: TimeField, +~~ models.URLField: URLField, +~~ models.UUIDField: UUIDField, +~~ models.GenericIPAddressField: IPAddressField, +~~ models.FilePathField: FilePathField, + } + if postgres_fields: + serializer_field_mapping[postgres_fields.HStoreField] = HStoreField + serializer_field_mapping[postgres_fields.ArrayField] = ListField + serializer_field_mapping[postgres_fields.JSONField] = JSONField + serializer_related_field = PrimaryKeyRelatedField + serializer_related_to_field = SlugRelatedField + serializer_url_field = HyperlinkedIdentityField + serializer_choice_field = ChoiceField + + url_field_name = None + + def create(self, validated_data): + raise_errors_on_nested_writes('create', self, validated_data) + + ModelClass = self.Meta.model + + info = model_meta.get_field_info(ModelClass) + many_to_many = {} + for field_name, relation_info in info.relations.items(): + if relation_info.to_many and (field_name in validated_data): + many_to_many[field_name] = validated_data.pop(field_name) + + try: + + +## ... source file continues with no further models examples... + +``` + + +## Example 18 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / models.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./models.py) + +```python +# models.py +from django.contrib.auth.models import Permission +~~from django.db import models +from django.utils.translation import gettext_lazy as _ + +from .settings import MODEL_TREE, TREE_ITEMS_ALIASES + + +class CharFieldNullable(models.CharField): + def get_prep_value(self, value): + if value is not None: + if value.strip() == '': + return None + return self.to_python(value) + + +class TreeBase(models.Model): + +~~ title = models.CharField( + _('Title'), max_length=100, help_text=_('Site tree title for presentational purposes.'), blank=True) + +~~ alias = models.CharField( + _('Alias'), max_length=80, + help_text=_('Short name to address site tree from templates.
Note: change with care.'), + unique=True, db_index=True) + + class Meta: + abstract = True + verbose_name = _('Site Tree') + verbose_name_plural = _('Site Trees') + + def get_title(self) -> str: + return self.title or self.alias + + def __str__(self) -> str: + return self.alias + + +class TreeItemBase(models.Model): + + PERM_TYPE_ANY = 1 + PERM_TYPE_ALL = 2 + + PERM_TYPE_CHOICES = { + PERM_TYPE_ANY: _('Any'), + PERM_TYPE_ALL: _('All'), + } + +~~ title = models.CharField( + _('Title'), max_length=100, + help_text=_('Site tree item title. Can contain template variables E.g.: {{ mytitle }}.')) + +~~ hint = models.CharField( + _('Hint'), max_length=200, + help_text=_('Some additional information about this item that is used as a hint.'), blank=True, default='') + +~~ url = models.CharField( + _('URL'), max_length=200, + help_text=_('Exact URL or URL pattern (see "Additional settings") for this item.'), db_index=True) + +~~ urlaspattern = models.BooleanField( + _('URL as Pattern'), + help_text=_('Whether the given URL should be treated as a pattern.
' + 'Note: Refer to Django "URL dispatcher" documentation (e.g. "Naming URL patterns" part).'), + db_index=True, default=False) + +~~ tree = models.ForeignKey( +~~ MODEL_TREE, related_name='%(class)s_tree', on_delete=models.CASCADE, verbose_name=_('Site Tree'), + help_text=_('Site tree this item belongs to.'), db_index=True) + +~~ hidden = models.BooleanField( + _('Hidden'), help_text=_('Whether to show this item in navigation.'), db_index=True, default=False) + + alias = CharFieldNullable( + _('Alias'), max_length=80, + help_text=_( + 'Short name to address site tree item from a template.
' + 'Reserved aliases: "%s".' % '", "'.join(TREE_ITEMS_ALIASES) + ), + db_index=True, blank=True, null=True) + +~~ description = models.TextField( + _('Description'), + help_text=_('Additional comments on this item.'), blank=True, default='') + +~~ inmenu = models.BooleanField( + _('Show in menu'), + help_text=_('Whether to show this item in a menu.'), db_index=True, default=True) + +~~ inbreadcrumbs = models.BooleanField( + _('Show in breadcrumb path'), + help_text=_('Whether to show this item in a breadcrumb path.'), db_index=True, default=True) + +~~ insitetree = models.BooleanField( + _('Show in site tree'), + help_text=_('Whether to show this item in a site tree.'), db_index=True, default=True) + +~~ access_loggedin = models.BooleanField( + _('Logged in only'), + help_text=_('Check it to grant access to this item to authenticated users only.'), + db_index=True, default=False) + +~~ access_guest = models.BooleanField( + _('Guests only'), + help_text=_('Check it to grant access to this item to guests only.'), db_index=True, default=False) + +~~ access_restricted = models.BooleanField( + _('Restrict access to permissions'), + help_text=_('Check it to restrict user access to this item, using Django permissions system.'), + db_index=True, default=False) + +~~ access_permissions = models.ManyToManyField( + Permission, verbose_name=_('Permissions granting access'), blank=True) + +~~ access_perm_type = models.IntegerField( + _('Permissions interpretation'), + help_text=_('Any — user should have any of chosen permissions. ' + 'All — user should have all chosen permissions.'), + choices=PERM_TYPE_CHOICES.items(), default=PERM_TYPE_ANY) + +~~ parent = models.ForeignKey( +~~ 'self', related_name='%(class)s_parent', on_delete=models.CASCADE, verbose_name=_('Parent'), + help_text=_('Parent site tree item.'), db_index=True, null=True, blank=True) + +~~ sort_order = models.IntegerField( + _('Sort order'), + help_text=_('Item position among other site tree items under the same parent.'), db_index=True, default=0) + + def save(self, force_insert=False, force_update=False, **kwargs): + if self.parent == self: + self.parent = None + + id_ = self.id + if id_ and self.sort_order == 0: + self.sort_order = id_ + + super().save(force_insert, force_update, **kwargs) + + if self.sort_order == 0: + self.sort_order = self.id + self.save() + + class Meta: + abstract = True + verbose_name = _('Site Tree Item') + verbose_name_plural = _('Site Tree Items') + unique_together = ('tree', 'alias') + + def __str__(self) -> str: + + +## ... source file continues with no further models examples... + +``` + + +## Example 19 from django-smithy +[django-smithy](https://github.com/jamiecounsell/django-smithy) is +a [Django](/django.html) code library that allows users to send +HTTP requests from the Django admin user interface. The code for +the project is open source under the +[MIT license](https://github.com/jamiecounsell/django-smithy/blob/master/LICENSE). + +[**django-smithy / smithy / models.py**](https://github.com/jamiecounsell/django-smithy/blob/master/smithy/./models.py) + +```python +# models.py + +~~from django.db import models +from django.db.models.signals import post_save +from django.dispatch import receiver +from requests import Request as HTTPRequest, Session +from requests.cookies import create_cookie, RequestsCookieJar +from urllib.parse import parse_qs, urlparse, urlencode +from requests_toolbelt.utils import dump + +from model_utils.models import TimeStampedModel + +from smithy.helpers import render_with_context, parse_dump_result + + +class NameValueModel(TimeStampedModel): +~~ name = models.CharField(max_length = 200) +~~ value = models.TextField(blank = True) + + def __str__(self): + return self.name + + class Meta: + abstract = True + + +class Request(TimeStampedModel): + METHODS = ( + ('GET', 'GET'), + ('POST', 'POST'), + ('PUT', 'PUT'), + ('DELETE', 'DELETE'), + ('OPTIONS', 'OPTIONS'), + ('HEAD', 'HEAD'), + ) + BODY_TYPES = ( + ('', 'Other'), + ('application/x-www-form-urlencoded', 'x-www-form-urlencoded'), + ('application/json', 'JSON'), + ('text/plain', 'Text'), + ('application/javascript', 'JavaScript'), + ('application/xml', 'XML (application/xml)'), + ('text/xml', 'XML (text/xml)'), + ('text/html', 'HTML'), + ) +~~ method = models.CharField( + max_length = 7, choices = METHODS, + blank = False, null = False) +~~ name = models.CharField(max_length = 500, blank = False) +~~ url = models.CharField(max_length = 2083) +~~ body = models.TextField(blank = True) +~~ content_type = models.CharField( + default = BODY_TYPES[0][0], + blank = True, null = True, + max_length = 100, choices = BODY_TYPES) + + def __str__(self): + if self.name: + return self.name + return "{} {}".format( + self.method, + self.url, + ) + + +class RequestBlueprint(Request): +~~ follow_redirects = models.BooleanField( + default = False, blank = False, null = False) + + @property + def name_value_related(self): + return [ + self.headers, + self.query_parameters, + self.cookies + ] + + def send(self, context = None): + + context = context or {} + for variable in self.variables.all(): + context[variable.name] = variable.value + + request = HTTPRequest( + url = render_with_context(self.url, context), + method = self.method) + + session = Session() + record = RequestRecord.objects.create(blueprint = self) + + for qs in self.name_value_related: + + +## ... source file abbreviated to get to models examples ... + + + obj.save() + + if self.content_type == self.BODY_TYPES[0][0]: + data = render_with_context(self.body, context) + else: + data = {} + for param in self.body_parameters.all(): + param.add_to(data, context) + + request.data = data + prepared_request = request.prepare() + + response = session.send(prepared_request, stream = True) + + RequestRecord.objects.filter(pk = record.pk).update( + raw_request = parse_dump_result(dump._dump_request_data, prepared_request), + raw_response = parse_dump_result(dump._dump_response_data, response), + status = response.status_code, + **RequestRecord.get_clone_args(self, context) + ) + + return RequestRecord.objects.get(pk = record.pk) + + +class RequestRecord(Request): +~~ raw_request = models.TextField() +~~ raw_response = models.TextField() +~~ status = models.PositiveIntegerField(null = True) +~~ blueprint = models.ForeignKey( + 'smithy.RequestBlueprint', +~~ on_delete = models.SET_NULL, + null = True) + + @property + def is_success(self): + return self.status and self.status < 400 + + @staticmethod + def of_blueprint(blueprint): + return RequestRecord.objects.filter( + blueprint = blueprint) + + @classmethod + def get_clone_args(cls, obj, context : dict): + return dict([ + ( + render_with_context(fld.name, context), + render_with_context(getattr(obj, fld.name), context) + ) + for fld \ + in cls._meta.fields \ + if fld.name != obj._meta.pk \ + and fld in obj._meta.fields \ + and fld.name not in [ + 'request', 'id', 'created', 'updated' + ]]) + + +class Variable(NameValueModel): +~~ request = models.ForeignKey( + 'smithy.RequestBlueprint', +~~ on_delete = models.CASCADE, + related_name = 'variables') + + +class BodyParameter(NameValueModel): +~~ request = models.ForeignKey( + 'smithy.RequestBlueprint', +~~ on_delete = models.CASCADE, + related_name = 'body_parameters') + + def add_to(self, payload : dict, context: dict): + if self.name and self.value: + payload[ + render_with_context(self.name, context) + ] = render_with_context(self.value, context) + else: + pass # TODO: warn + + +class Header(NameValueModel): +~~ request = models.ForeignKey( + 'smithy.Request', +~~ on_delete = models.CASCADE, + related_name = 'headers') + + def add_to(self, request : HTTPRequest): + if self.name and self.value: + request.headers[self.name] = self.value + else: + pass # TODO: warn + + +class QueryParameter(NameValueModel): +~~ request = models.ForeignKey( + 'smithy.Request', +~~ on_delete = models.CASCADE, + related_name = 'query_parameters') + + def add_to(self, request : HTTPRequest): + existing_param_str = urlparse(request.url).query + param_dict = parse_qs(existing_param_str) + + param_dict[self.name] = self.value + + base_url = request.url.rstrip(existing_param_str) + param_str = urlencode(param_dict, doseq=True) + request.url = base_url.rstrip("?") + "?" + param_str + + +class Cookie(NameValueModel): +~~ request = models.ForeignKey( + 'smithy.Request', +~~ on_delete = models.CASCADE, + related_name = 'cookies') + + def add_to(self, request : HTTPRequest): + request.cookies = request.cookies or RequestsCookieJar() + request.cookies.set_cookie( + create_cookie(self.name, self.value) + ) + + +@receiver(post_save, sender = RequestBlueprint) +def add_content_type(sender, instance : RequestBlueprint, created, **kwargs): + if created and not instance.headers.filter(name__iexact = 'content-type').exists(): + instance.content_type and Header.objects.create( + name = 'Content-Type', + value = instance.content_type, + request = instance.request_ptr + ) + + + +## ... source file continues with no further models examples... + +``` + + +## Example 20 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / models.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./models.py) + +```python +# models.py +from __future__ import unicode_literals + +import logging +from time import time +import six + +~~from django.db import models, DatabaseError +try: + from django.urls import reverse +except ImportError: + from django.core.urlresolvers import reverse + +from django.conf import settings + +from explorer import app_settings +from explorer.utils import ( + passes_blacklist, + swap_params, + extract_params, + shared_dict_update, + get_s3_bucket, + get_params_for_url, + get_valid_connection +) + +MSG_FAILED_BLACKLIST = "Query failed the SQL blacklist: %s" + + +logger = logging.getLogger(__name__) + +@six.python_2_unicode_compatible +class Query(models.Model): +~~ title = models.CharField(max_length=255) +~~ sql = models.TextField() +~~ description = models.TextField(null=True, blank=True) +~~ created_by_user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.CASCADE) +~~ created_at = models.DateTimeField(auto_now_add=True) +~~ last_run_date = models.DateTimeField(auto_now=True) +~~ snapshot = models.BooleanField(default=False, help_text="Include in snapshot task (if enabled)") +~~ connection = models.CharField(blank=True, null=True, max_length=128, + help_text="Name of DB connection (as specified in settings) to use for this query. Will use EXPLORER_DEFAULT_CONNECTION if left blank") + + def __init__(self, *args, **kwargs): + self.params = kwargs.get('params') + kwargs.pop('params', None) + super(Query, self).__init__(*args, **kwargs) + + class Meta: + ordering = ['title'] + verbose_name_plural = 'Queries' + + def __str__(self): + return six.text_type(self.title) + + def get_run_count(self): + return self.querylog_set.count() + + def avg_duration(self): + return self.querylog_set.aggregate(models.Avg('duration'))['duration__avg'] + + def passes_blacklist(self): + return passes_blacklist(self.final_sql()) + + def final_sql(self): + + +## ... source file abbreviated to get to models examples ... + + + return ql + + @property + def shared(self): + return self.id in set(sum(app_settings.EXPLORER_GET_USER_QUERY_VIEWS().values(), [])) + + @property + def snapshots(self): + if app_settings.ENABLE_TASKS: + b = get_s3_bucket() + keys = b.list(prefix='query-%s/snap-' % self.id) + keys_s = sorted(keys, key=lambda k: k.last_modified) + return [SnapShot(k.generate_url(expires_in=0, query_auth=False), + k.last_modified) for k in keys_s] + + +class SnapShot(object): + + def __init__(self, url, last_modified): + self.url = url + self.last_modified = last_modified + + +class QueryLog(models.Model): + +~~ sql = models.TextField(null=True, blank=True) +~~ query = models.ForeignKey(Query, null=True, blank=True, on_delete=models.SET_NULL) +~~ run_by_user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.CASCADE) +~~ run_at = models.DateTimeField(auto_now_add=True) +~~ duration = models.FloatField(blank=True, null=True) # milliseconds +~~ connection = models.CharField(blank=True, null=True, max_length=128) + + @property + def is_playground(self): + return self.query_id is None + + class Meta: + ordering = ['-run_at'] + + +class QueryResult(object): + + def __init__(self, sql, connection): + + self.sql = sql + self.connection = connection + + cursor, duration = self.execute_query() + + self._description = cursor.description or [] + self._data = [list(r) for r in cursor.fetchall()] + self.duration = duration + + cursor.close() + + + +## ... source file continues with no further models examples... + +``` + + +## Example 21 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / utils.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/./utils.py) + +```python +# utils.py +import inspect +import warnings +from collections import OrderedDict +from functools import total_ordering +from itertools import chain + +from django.core.exceptions import FieldDoesNotExist +~~from django.db import models +from django.utils.html import format_html_join + + +class Sequence(list): + + def expand(self, columns): + ellipses = self.count("...") + if ellipses > 1: + raise ValueError("'...' must be used at most once in a sequence.") + elif ellipses == 0: + self.append("...") + + columns = list(columns) # take a copy and exhaust the generator + head = [] + tail = [] + target = head # start by adding things to the head + for name in self: + if name == "...": + target = tail + continue + target.append(name) + if name in columns: + columns.pop(columns.index(name)) + self[:] = chain(head, columns, tail) + + +## ... source file abbreviated to get to models examples ... + + + + return instance + + def resolve(self, context, safe=True, quiet=False): + if isinstance(context, dict) and self in context: + return context[self] + + try: + current = context + for bit in self.bits: + try: # dictionary lookup + current = current[bit] + except (TypeError, AttributeError, KeyError): + try: # attribute lookup + current = getattr(current, bit) + except (TypeError, AttributeError): + try: # list-index lookup + current = current[int(bit)] + except ( + IndexError, # list index out of range + ValueError, # invalid literal for int() + KeyError, # dict without `int(bit)` key + TypeError, # unsubscriptable object + ): + current_context = ( +~~ type(current) if isinstance(current, models.Model) else current + ) + + raise ValueError( + self.LOOKUP_ERROR_FMT.format( + key=bit, context=current_context, accessor=self + ) + ) + if callable(current): + if safe and getattr(current, "alters_data", False): + raise ValueError(self.ALTERS_DATA_ERROR_FMT.format(method=repr(current))) + if not getattr(current, "do_not_call_in_templates", False): + current = current() + if current is None: + break + return current + except Exception: + if not quiet: + raise + + @property + def bits(self): + if self == "": + return () + return self.split(self.SEPARATOR) + + +## ... source file continues with no further models examples... + +``` + + +## Example 22 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / models.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./models.py) + +```python +# models.py +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +~~from django.db import IntegrityError, models, router, transaction +from django.utils.text import slugify +from django.utils.translation import gettext, gettext_lazy as _ + +try: + from unidecode import unidecode +except ImportError: + + def unidecode(tag): + return tag + + +class TagBase(models.Model): +~~ name = models.CharField(verbose_name=_("name"), unique=True, max_length=100) +~~ slug = models.SlugField(verbose_name=_("slug"), unique=True, max_length=100) + + def __str__(self): + return self.name + + def __gt__(self, other): + return self.name.lower() > other.name.lower() + + def __lt__(self, other): + return self.name.lower() < other.name.lower() + + class Meta: + abstract = True + + def save(self, *args, **kwargs): + if self._state.adding and not self.slug: + self.slug = self.slugify(self.name) + using = kwargs.get("using") or router.db_for_write( + type(self), instance=self + ) + kwargs["using"] = using + try: + with transaction.atomic(using=using): + res = super().save(*args, **kwargs) + return res + + +## ... source file abbreviated to get to models examples ... + + + @classmethod + def tag_model(cls): + field = cls._meta.get_field("tag") + return field.remote_field.model + + @classmethod + def tag_relname(cls): + field = cls._meta.get_field("tag") + return field.remote_field.related_name + + @classmethod + def lookup_kwargs(cls, instance): + return {"content_object": instance} + + @classmethod + def tags_for(cls, model, instance=None, **extra_filters): + kwargs = extra_filters or {} + if instance is not None: + kwargs.update({"%s__content_object" % cls.tag_relname(): instance}) + return cls.tag_model().objects.filter(**kwargs) + kwargs.update({"%s__content_object__isnull" % cls.tag_relname(): False}) + return cls.tag_model().objects.filter(**kwargs).distinct() + + +class TaggedItemBase(ItemBase): +~~ tag = models.ForeignKey( +~~ Tag, related_name="%(app_label)s_%(class)s_items", on_delete=models.CASCADE + ) + + class Meta: + abstract = True + + +class CommonGenericTaggedItemBase(ItemBase): +~~ content_type = models.ForeignKey( + ContentType, +~~ on_delete=models.CASCADE, + verbose_name=_("content type"), + related_name="%(app_label)s_%(class)s_tagged_items", + ) + content_object = GenericForeignKey() + + class Meta: + abstract = True + + @classmethod + def lookup_kwargs(cls, instance): + return { + "object_id": instance.pk, + "content_type": ContentType.objects.get_for_model(instance), + } + + @classmethod + def tags_for(cls, model, instance=None, **extra_filters): + tag_relname = cls.tag_relname() + model = model._meta.concrete_model + kwargs = { + "%s__content_type__app_label" % tag_relname: model._meta.app_label, + "%s__content_type__model" % tag_relname: model._meta.model_name, + } + if instance is not None: + kwargs["%s__object_id" % tag_relname] = instance.pk + if extra_filters: + kwargs.update(extra_filters) + return cls.tag_model().objects.filter(**kwargs).distinct() + + +class GenericTaggedItemBase(CommonGenericTaggedItemBase): +~~ object_id = models.IntegerField(verbose_name=_("object ID"), db_index=True) + + class Meta: + abstract = True + + +class GenericUUIDTaggedItemBase(CommonGenericTaggedItemBase): +~~ object_id = models.UUIDField(verbose_name=_("object ID"), db_index=True) + + class Meta: + abstract = True + + +class TaggedItem(GenericTaggedItemBase, TaggedItemBase): + class Meta: + verbose_name = _("tagged item") + verbose_name_plural = _("tagged items") + app_label = "taggit" + index_together = [["content_type", "object_id"]] + unique_together = [["content_type", "object_id", "tag"]] + + + +## ... source file continues with no further models examples... + +``` + + +## Example 23 from django-user-visit +[django-user-visit](https://github.com/yunojuno/django-user-visit) +([PyPI package information](https://pypi.org/project/django-user-visit/)) +is a [Django](/django.html) app and +[middleware](https://docs.djangoproject.com/en/stable/topics/http/middleware/) +for tracking daily user visits to your web application. The goal +is to record per user per day instead of for every request a user +sends to the application. The project is provided as open source +under the +[MIT license](https://github.com/yunojuno/django-user-visit/blob/master/LICENSE). + +[**django-user-visit / user_visit / models.py**](https://github.com/yunojuno/django-user-visit/blob/master/user_visit/./models.py) + +```python +# models.py +from __future__ import annotations + +import datetime +import hashlib +import uuid +from typing import Any + +import user_agents +from django.conf import settings +~~from django.db import models +from django.http import HttpRequest +from django.utils import timezone + + +def parse_remote_addr(request: HttpRequest) -> str: + x_forwarded_for = request.headers.get("X-Forwarded-For", "") + if x_forwarded_for: + return x_forwarded_for.split(",")[0] + return request.META.get("REMOTE_ADDR", "") + + +def parse_ua_string(request: HttpRequest) -> str: + return request.headers.get("User-Agent", "") + + +class UserVisitManager(models.Manager): + + def build(self, request: HttpRequest, timestamp: datetime.datetime) -> UserVisit: + uv = UserVisit( + user=request.user, + timestamp=timestamp, + session_key=request.session.session_key, + remote_addr=parse_remote_addr(request), + ua_string=parse_ua_string(request), + ) + uv.hash = uv.md5().hexdigest() + return uv + + +class UserVisit(models.Model): + +~~ user = models.ForeignKey( +~~ settings.AUTH_USER_MODEL, related_name="user_visits", on_delete=models.CASCADE + ) +~~ timestamp = models.DateTimeField( + help_text="The time at which the first visit of the day was recorded", + default=timezone.now, + ) +~~ session_key = models.CharField(help_text="Django session identifier", max_length=40) +~~ remote_addr = models.CharField( + help_text=( + "Client IP address (from X-Forwarded-For HTTP header, " + "or REMOTE_ADDR request property)" + ), + max_length=100, + blank=True, + ) +~~ ua_string = models.TextField( + "User agent (raw)", help_text="Client User-Agent HTTP header", blank=True, + ) +~~ uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) +~~ hash = models.CharField( + max_length=32, + help_text="MD5 hash generated from request properties", + unique=True, + ) +~~ created_at = models.DateTimeField( + help_text="The time at which the database record was created (!=timestamp)", + auto_now_add=True, + ) + + objects = UserVisitManager() + + class Meta: + get_latest_by = "timestamp" + + def __str__(self) -> str: + return f"{self.user} visited the site on {self.timestamp}" + + def __repr__(self) -> str: + return f"" + + def save(self, *args: Any, **kwargs: Any) -> None: + self.hash = self.md5().hexdigest() + super().save(*args, **kwargs) + + @property + def user_agent(self) -> user_agents.parsers.UserAgent: + return user_agents.parsers.parse(self.ua_string) + + @property + + +## ... source file continues with no further models examples... + +``` + + +## Example 24 from django-webshell +[django-webshell](https://github.com/onrik/django-webshell) is an extension +for executing arbitrary code in the +[Django admin](https://docs.djangoproject.com/en/stable/ref/contrib/admin/), +similar to how you can run code by using the `django manage.py shell` +command from the terminal. + +The django-webshell project is provided as open source under the +[MIT license](https://github.com/onrik/django-webshell/blob/master/LICENSE). + +[**django-webshell / webshell / models.py**](https://github.com/onrik/django-webshell/blob/master/webshell/./models.py) + +```python +# models.py +~~from django.db import models +from django.utils.translation import ugettext_lazy as _ + + +class Script(models.Model): +~~ name = models.CharField(_('Name'), max_length=100) +~~ source = models.TextField(_('Source')) + + class Meta: + verbose_name = _('Script') + verbose_name_plural = _('Scripts') + + def __unicode__(self): + return self.name + + + +## ... source file continues with no further models examples... + +``` + + +## Example 25 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / migrations / 0003_mptt_upgrade.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/migrations/0003_mptt_upgrade.py) + +```python +# 0003_mptt_upgrade.py +from django.db import migrations +~~from django.db import models + + +class Migration(migrations.Migration): + + dependencies = [ + ("wiki", "0002_urlpath_moved_to"), + ] + + operations = [ + migrations.AlterField( + model_name="urlpath", + name="level", +~~ field=models.PositiveIntegerField(editable=False), + ), + migrations.AlterField( + model_name="urlpath", + name="lft", +~~ field=models.PositiveIntegerField(editable=False), + ), + migrations.AlterField( + model_name="urlpath", + name="rght", +~~ field=models.PositiveIntegerField(editable=False), + ), + ] + + + +## ... source file continues with no further models examples... + +``` + + +## Example 26 from dmd-interpreter +[dmd-interpreter](https://github.com/mitchalexbailey/dmd-interpreter) +([running web app](http://www.dmd.nl/DOVE)) +is a Python tool to aggregate clinically relevant information related +to variants in the DMD gene and display that [data](/data.html) to a user +with a [Django](/django.html) web application. + +[**dmd-interpreter / interpreter / models.py**](https://github.com/mitchalexbailey/dmd-interpreter/blob/master/interpreter/./models.py) + +```python +# models.py +~~from django.db import models + +class Question(models.Model): +~~ question_text = models.CharField(max_length=200) +~~ pub_date = models.DateTimeField("Date Published") + def __unicode__(self): + return self.question_text + +class Choice(models.Model): +~~ question = models.ForeignKey(Question) +~~ choice_text = models.CharField(max_length=200) +~~ votes = models.IntegerField(default=0) + def __unicode__(self): + return self.choice_text + + + +## ... source file continues with no further models examples... + +``` + + +## Example 27 from drf-action-serializer +[drf-action-serializer](https://github.com/gregschmit/drf-action-serializer) +([PyPI page](https://pypi.org/project/drf-action-serializer/)) +that makes it easier to configure specific serializers to use based on the +client's request action. For example, a list view should have one serializer +whereas the detail view would have a different serializer. + +The project is open source under the +[MIT license](https://github.com/gregschmit/drf-action-serializer/blob/master/LICENSE). + +[**drf-action-serializer / action_serializer / tests.py**](https://github.com/gregschmit/drf-action-serializer/blob/master/action_serializer/./tests.py) + +```python +# tests.py + +import os + +~~from django.db import models +from django.test import TestCase + +from .serializers import ModelActionSerializer + + +def dedent(blocktext): + return "\n".join([line[12:] for line in blocktext.splitlines()[1:-1]]) + + +class RegularFieldsModel(models.Model): + +~~ auto_field = models.AutoField(primary_key=True) +~~ boolean_field = models.BooleanField(default=False) +~~ char_field = models.CharField(max_length=100) +~~ date_field = models.DateField() +~~ decimal_field = models.DecimalField(max_digits=3, decimal_places=1) +~~ email_field = models.EmailField(max_length=100) +~~ float_field = models.FloatField() +~~ integer_field = models.IntegerField() + + +class ModelActionSerializerTestCase(TestCase): + + def test_action_fields(self): + + class TestSerializer(ModelActionSerializer): + class Meta: + model = RegularFieldsModel + fields = "char_field" + action_fields = {"list": {"fields": ("auto_field", "char_field")}} + + expected = dedent( + ) + context = {"view": type("ActionView", (object,), {"action": "list"})} + self.assertEqual(repr(TestSerializer(context=context)), expected) + + def test_action_fields_different_action(self): + + class TestSerializer(ModelActionSerializer): + class Meta: + model = RegularFieldsModel + fields = ("char_field",) + action_fields = {"list": {"fields": ("auto_field", "char_field")}} + + +## ... source file abbreviated to get to models examples ... + + + ) + context = {"view": type("ActionView", (object,), {"action": "create"})} + self.assertEqual(repr(TestSerializer(context=context)), expected) + + def test_action_extra_kwargs(self): + + class TestSerializer(ModelActionSerializer): + class Meta: + model = RegularFieldsModel + fields = "char_field" + action_fields = { + "list": { + "fields": ("auto_field", "char_field"), + "extra_kwargs": { + "auto_field": {"required": False, "read_only": False} + }, + } + } + + expected = dedent( + ) + context = {"view": type("ActionView", (object,), {"action": "list"})} + self.assertEqual(repr(TestSerializer(context=context)), expected) + + def test_action_exclude(self): +~~ auto_field = models.AutoField(primary_key=True) +~~ boolean_field = models.BooleanField(default=False) +~~ char_field = models.CharField(max_length=100) +~~ date_field = models.DateField() +~~ decimal_field = models.DecimalField(max_digits=3, decimal_places=1) +~~ email_field = models.EmailField(max_length=100) +~~ float_field = models.FloatField() +~~ integer_field = models.IntegerField() + + class TestSerializer(ModelActionSerializer): + class Meta: + model = RegularFieldsModel + fields = "char_field" + action_fields = { + "list": { + "exclude": ( + "boolean_field", + "date_field", + "float_field", + "integer_field", + ) + } + } + + expected = dedent( + ) + context = {"view": type("ActionView", (object,), {"action": "list"})} + self.assertEqual(repr(TestSerializer(context=context)), expected) + + + +## ... source file continues with no further models examples... + +``` + + +## Example 28 from elasticsearch-django +[elasticsearch-django](https://github.com/yunojuno/elasticsearch-django) +([PyPI package information](https://pypi.org/project/elasticsearch-django/)) +is a [Django](/django.html) app for managing +[ElasticSearch](https://github.com/elastic/elasticsearch) indexes +populated by [Django ORM](/django-orm.html) models. The project is +available as open source under the +[MIT license](https://github.com/yunojuno/elasticsearch-django/blob/master/LICENSE). + +[**elasticsearch-django / elasticsearch_django / models.py**](https://github.com/yunojuno/elasticsearch-django/blob/master/elasticsearch_django/./models.py) + +```python +# models.py +from __future__ import annotations + +import logging +import time +import warnings +from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Union + +from django.conf import settings +from django.contrib.postgres.fields import JSONField +from django.core.cache import cache +from django.core.serializers.json import DjangoJSONEncoder +~~from django.db import models +from django.db.models.expressions import RawSQL +from django.db.models.fields import CharField +from django.db.models.query import QuerySet +from django.utils.timezone import now as tz_now +from elasticsearch_dsl import Search + +from .settings import ( + get_client, + get_model_index_properties, + get_model_indexes, + get_setting, +) + +if TYPE_CHECKING: + from django.contrib.auth.models import AbstractBaseUser + +logger = logging.getLogger(__name__) + +UPDATE_STRATEGY_FULL = "full" +UPDATE_STRATEGY_PARTIAL = "partial" +UPDATE_STRATEGY = get_setting("update_strategy", UPDATE_STRATEGY_FULL) + + +class SearchDocumentManagerMixin(models.Manager): + + +## ... source file abbreviated to get to models examples ... + + + return + + get_client().update( + index=index, + doc_type=self.search_doc_type, + body={"doc": doc}, + id=self.pk, # type: ignore + ) + + def delete_search_document(self, *, index: str) -> None: + cache.delete(self.search_document_cache_key) + get_client().delete( + index=index, doc_type=self.search_doc_type, id=self.pk # type: ignore + ) + + +class SearchQuery(models.Model): + + QUERY_TYPE_SEARCH = "SEARCH" + QUERY_TYPE_COUNT = "COUNT" + QUERY_TYPE_CHOICES = ( + (QUERY_TYPE_SEARCH, "Search results"), + (QUERY_TYPE_COUNT, "Count only"), + ) + +~~ user = models.ForeignKey( + settings.AUTH_USER_MODEL, + related_name="search_queries", + blank=True, + null=True, + help_text="The user who made the search query (nullable).", +~~ on_delete=models.SET_NULL, + ) +~~ index = models.CharField( + max_length=100, + default="_all", + help_text="The name of the ElasticSearch index(es) being queried.", + ) +~~ search_terms = models.CharField( + max_length=400, + default="", + blank=True, + help_text=( + "Free text search terms used in the query, stored for easy reference." + ), + ) + query = JSONField( + help_text="The raw ElasticSearch DSL query.", encoder=DjangoJSONEncoder + ) + query_type = CharField( + help_text="Does this query return results, or just the hit count?", + choices=QUERY_TYPE_CHOICES, + default=QUERY_TYPE_SEARCH, + max_length=10, + ) + hits = JSONField( + help_text="The list of meta info for each of the query matches returned.", + encoder=DjangoJSONEncoder, + ) +~~ total_hits = models.IntegerField( + default=0, + help_text="Total number of matches found for the query (!= the hits returned).", + ) +~~ reference = models.CharField( + max_length=100, + default="", + blank=True, + help_text="Custom reference used to identify and group related searches.", + ) +~~ executed_at = models.DateTimeField( + help_text="When the search was executed - set via execute() method." + ) +~~ duration = models.FloatField( + help_text="Time taken to execute the search itself, in seconds." + ) + + class Meta: + app_label = "elasticsearch_django" + verbose_name = "Search query" + verbose_name_plural = "Search queries" + + def __str__(self) -> str: + return f"Query (id={self.pk}) run against index '{self.index}'" + + def __repr__(self) -> str: + return ( + f"" + ) + + def save(self, *args: Any, **kwargs: Any) -> SearchQuery: + if self.search_terms is None: + self.search_terms = "" + super().save(**kwargs) + return self + + def _extract_set(self, _property: str) -> List[Union[str, int]]: + + +## ... source file continues with no further models examples... + +``` + + +## Example 29 from gadget-board +[gadget-board](https://github.com/mik4el/gadget-board) is a +[Django](/django.html), +[Django REST Framework (DRF)](/django-rest-framework-drf.html) and +[Angular](/angular.html) web application that is open source under the +[Apache2 license](https://github.com/mik4el/gadget-board/blob/master/LICENSE). + +[**gadget-board / web / authentication / models.py**](https://github.com/mik4el/gadget-board/blob/master/web/authentication/models.py) + +```python +# models.py +from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin +~~from django.db import models +from django.contrib.auth.models import BaseUserManager + + +class AccountManager(BaseUserManager): + def create_account(self, username, password, **kwargs): + if not username: + raise ValueError('Users must have a valid username') + + if not password: + raise ValueError('Users must have a valid password.') + + if not kwargs.get('email'): + raise ValueError('Users must have a valid email.') + + account = self.model( + username=username, email=self.normalize_email(kwargs.get('email')) + ) + + account.is_active = True + + account.set_password(password) + account.save() + + return account + + def create_superuser(self, username, password, **kwargs): + account = self.create_account(username, password, **kwargs) + + account.is_superuser = True + + account.save() + + return account + + +class Account(AbstractBaseUser, PermissionsMixin): +~~ username = models.CharField(max_length=40, unique=True) +~~ email = models.EmailField() # users can share email + +~~ is_gadget = models.BooleanField(default=False) +~~ is_active = models.BooleanField(default=True) + +~~ created_at = models.DateTimeField(auto_now_add=True) +~~ updated_at = models.DateTimeField(auto_now=True) + + objects = AccountManager() + + USERNAME_FIELD = 'username' + REQUIRED_FIELDS = ['email'] + + def __str__(self): + return self.username + + def get_full_name(self): + return self.username + + def get_short_name(self): + return self.username + + @property + def is_staff(self): + "Is the user a member of staff?" + return self.is_superuser + + + +## ... source file continues with no further models examples... + +``` + + +## Example 30 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / models.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/models.py) + +```python +# models.py +import json +import logging +from collections import defaultdict +from io import StringIO +from urllib.parse import urlparse + +from django.conf import settings +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core import checks +from django.core.cache import cache +from django.core.exceptions import ValidationError +from django.core.handlers.base import BaseHandler +from django.core.handlers.wsgi import WSGIRequest +~~from django.db import models, transaction +from django.db.models import Case, Q, Value, When +from django.db.models.functions import Concat, Lower, Substr +from django.http import Http404 +from django.http.request import split_domain_port +from django.template.response import TemplateResponse +from django.urls import NoReverseMatch, reverse +from django.utils import timezone +from django.utils.cache import patch_cache_control +from django.utils.functional import cached_property +from django.utils.text import capfirst, slugify +from django.utils.translation import gettext_lazy as _ +from modelcluster.models import ( + ClusterableModel, get_all_child_m2m_relations, get_all_child_relations) +from treebeard.mp_tree import MP_Node + +from wagtail.core.query import PageQuerySet, TreeQuerySet +from wagtail.core.signals import page_published, page_unpublished, post_page_move, pre_page_move +from wagtail.core.sites import get_site_for_hostname +from wagtail.core.url_routing import RouteResult +from wagtail.core.utils import WAGTAIL_APPEND_SLASH, camelcase_to_underscore, resolve_model_string +from wagtail.search import index + + +logger = logging.getLogger('wagtail.core') + +PAGE_TEMPLATE_VAR = 'page' + + +class SiteManager(models.Manager): + def get_queryset(self): + return super(SiteManager, self).get_queryset().order_by(Lower("hostname")) + + def get_by_natural_key(self, hostname, port): + return self.get(hostname=hostname, port=port) + + +class Site(models.Model): +~~ hostname = models.CharField(verbose_name=_('hostname'), max_length=255, db_index=True) +~~ port = models.IntegerField( + verbose_name=_('port'), + default=80, + help_text=_( + "Set this to something other than 80 if you need a specific port number to appear in URLs" + " (e.g. development on port 8000). Does not affect request handling (so port forwarding still works)." + ) + ) +~~ site_name = models.CharField( + verbose_name=_('site name'), + max_length=255, + blank=True, + help_text=_("Human-readable name for the site.") + ) +~~ root_page = models.ForeignKey('Page', verbose_name=_('root page'), related_name='sites_rooted_here', on_delete=models.CASCADE) +~~ is_default_site = models.BooleanField( + verbose_name=_('is default site'), + default=False, + help_text=_( + "If true, this site will handle requests for all other hostnames that do not have a site entry of their own" + ) + ) + + objects = SiteManager() + + class Meta: + unique_together = ('hostname', 'port') + verbose_name = _('site') + verbose_name_plural = _('sites') + + def natural_key(self): + return (self.hostname, self.port) + + def __str__(self): + default_suffix = " [{}]".format(_("default")) + if self.site_name: + return( + self.site_name + + (default_suffix if self.is_default_site else "") + ) + + +## ... source file abbreviated to get to models examples ... + + + + if 'template' not in dct: + cls.template = "%s/%s.html" % (cls._meta.app_label, camelcase_to_underscore(name)) + + if 'ajax_template' not in dct: + cls.ajax_template = None + + cls._clean_subpage_models = None # to be filled in on first call to cls.clean_subpage_models + cls._clean_parent_page_models = None # to be filled in on first call to cls.clean_parent_page_models + + if 'is_creatable' not in dct: + cls.is_creatable = not cls._meta.abstract + + if not cls._meta.abstract: + PAGE_MODEL_CLASSES.append(cls) + + +class AbstractPage(MP_Node): + objects = PageManager() + + class Meta: + abstract = True + + +class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase): +~~ title = models.CharField( + verbose_name=_('title'), + max_length=255, + help_text=_("The page title as you'd like it to be seen by the public") + ) +~~ draft_title = models.CharField( + max_length=255, + editable=False + ) +~~ slug = models.SlugField( + verbose_name=_('slug'), + allow_unicode=True, + max_length=255, + help_text=_("The name of the page as it will appear in URLs e.g http://domain.com/blog/[my-slug]/") + ) +~~ content_type = models.ForeignKey( + ContentType, + verbose_name=_('content type'), + related_name='pages', +~~ on_delete=models.SET(get_default_page_content_type) + ) +~~ live = models.BooleanField(verbose_name=_('live'), default=True, editable=False) +~~ has_unpublished_changes = models.BooleanField( + verbose_name=_('has unpublished changes'), + default=False, + editable=False + ) +~~ url_path = models.TextField(verbose_name=_('URL path'), blank=True, editable=False) +~~ owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + verbose_name=_('owner'), + null=True, + blank=True, + editable=True, +~~ on_delete=models.SET_NULL, + related_name='owned_pages' + ) + +~~ seo_title = models.CharField( + verbose_name=_("page title"), + max_length=255, + blank=True, + help_text=_("Optional. 'Search Engine Friendly' title. This will appear at the top of the browser window.") + ) + + show_in_menus_default = False +~~ show_in_menus = models.BooleanField( + verbose_name=_('show in menus'), + default=False, + help_text=_("Whether a link to this page will appear in automatically generated menus") + ) +~~ search_description = models.TextField(verbose_name=_('search description'), blank=True) + +~~ go_live_at = models.DateTimeField( + verbose_name=_("go live date/time"), + blank=True, + null=True + ) +~~ expire_at = models.DateTimeField( + verbose_name=_("expiry date/time"), + blank=True, + null=True + ) +~~ expired = models.BooleanField(verbose_name=_('expired'), default=False, editable=False) + +~~ locked = models.BooleanField(verbose_name=_('locked'), default=False, editable=False) +~~ locked_at = models.DateTimeField(verbose_name=_('locked at'), null=True, editable=False) +~~ locked_by = models.ForeignKey( + settings.AUTH_USER_MODEL, + verbose_name=_('locked by'), + null=True, + blank=True, + editable=False, +~~ on_delete=models.SET_NULL, + related_name='locked_pages' + ) + +~~ first_published_at = models.DateTimeField( + verbose_name=_('first published at'), + blank=True, + null=True, + db_index=True + ) +~~ last_published_at = models.DateTimeField( + verbose_name=_('last published at'), + null=True, + editable=False + ) +~~ latest_revision_created_at = models.DateTimeField( + verbose_name=_('latest revision created at'), + null=True, + editable=False + ) +~~ live_revision = models.ForeignKey( + 'PageRevision', + related_name='+', + verbose_name='live revision', +~~ on_delete=models.SET_NULL, + null=True, + blank=True, + editable=False + ) + + search_fields = [ + index.SearchField('title', partial_match=True, boost=2), + index.AutocompleteField('title'), + index.FilterField('title'), + index.FilterField('id'), + index.FilterField('live'), + index.FilterField('owner'), + index.FilterField('content_type'), + index.FilterField('path'), + index.FilterField('depth'), + index.FilterField('locked'), + index.FilterField('show_in_menus'), + index.FilterField('first_published_at'), + index.FilterField('last_published_at'), + index.FilterField('latest_revision_created_at'), + + +## ... source file abbreviated to get to models examples ... + + + self.title, + self.id, + cls._meta.app_label, + cls.__name__, + self.url_path + ) + + return result + + def delete(self, *args, **kwargs): + if type(self) is Page: + return super().delete(*args, **kwargs) + else: + return Page.objects.get(id=self.id).delete(*args, **kwargs) + + @classmethod + def check(cls, **kwargs): + errors = super(Page, cls).check(**kwargs) + + + field_exceptions = [field.name + for model in [cls] + list(cls._meta.get_parent_list()) + for field in model._meta.parents.values() if field] + + for field in cls._meta.fields: +~~ if isinstance(field, models.ForeignKey) and field.name not in field_exceptions: +~~ if field.remote_field.on_delete == models.CASCADE: + errors.append( + checks.Warning( + "Field hasn't specified on_delete action", +~~ hint="Set on_delete=models.SET_NULL and make sure the field is nullable or set on_delete=models.PROTECT. Wagtail does not allow simple database CASCADE because it will corrupt its tree storage.", + obj=field, + id='wagtailcore.W001', + ) + ) + + if not isinstance(cls.objects, PageManager): + errors.append( + checks.Error( + "Manager does not inherit from PageManager", + hint="Ensure that custom Page managers inherit from wagtail.core.models.PageManager", + obj=cls, + id='wagtailcore.E002', + ) + ) + + try: + cls.clean_subpage_models() + except (ValueError, LookupError) as e: + errors.append( + checks.Error( + + +## ... source file abbreviated to get to models examples ... + + + instance=new_self, + parent_page_before=parent_before, + parent_page_after=parent_after, + url_path_before=old_url_path, + url_path_after=new_url_path, + ) + + logger.info("Page moved: \"%s\" id=%d path=%s", self.title, self.id, new_url_path) + + def copy(self, recursive=False, to=None, update_attrs=None, copy_revisions=True, keep_live=True, user=None, process_child_object=None, exclude_fields=None): + specific_self = self.specific + default_exclude_fields = ['id', 'path', 'depth', 'numchild', 'url_path', 'path', 'index_entries'] + exclude_fields = default_exclude_fields + specific_self.exclude_fields_in_copy + (exclude_fields or []) + specific_dict = {} + + for field in specific_self._meta.get_fields(): + if field.name in exclude_fields: + continue + + if field.auto_created: + continue + + if field.many_to_many: + continue + +~~ if isinstance(field, models.OneToOneField) and field.remote_field.parent_link: + continue + + specific_dict[field.name] = getattr(specific_self, field.name) + + for related_field in get_all_child_m2m_relations(specific_self): + if related_field.name in exclude_fields: + continue + + field = getattr(specific_self, related_field.name) + if field and hasattr(field, 'all'): + values = field.all() + if values: + specific_dict[related_field.name] = values + + page_copy = self.specific_class(**specific_dict) + + if not keep_live: + page_copy.live = False + page_copy.has_unpublished_changes = True + page_copy.live_revision = None + page_copy.first_published_at = None + page_copy.last_published_at = None + + if user: + + +## ... source file abbreviated to get to models examples ... + + + + obj.path = self.path + obj.depth = self.depth + obj.numchild = self.numchild + + obj.set_url_path(self.get_parent()) + + obj.draft_title = self.draft_title + obj.live = self.live + obj.has_unpublished_changes = self.has_unpublished_changes + obj.owner = self.owner + obj.locked = self.locked + obj.locked_by = self.locked_by + obj.locked_at = self.locked_at + obj.latest_revision_created_at = self.latest_revision_created_at + obj.first_published_at = self.first_published_at + + return obj + + class Meta: + verbose_name = _('page') + verbose_name_plural = _('pages') + + +class Orderable(models.Model): +~~ sort_order = models.IntegerField(null=True, blank=True, editable=False) + sort_order_field = 'sort_order' + + class Meta: + abstract = True + ordering = ['sort_order'] + + +class SubmittedRevisionsManager(models.Manager): + def get_queryset(self): + return super().get_queryset().filter(submitted_for_moderation=True) + + +class PageRevision(models.Model): +~~ page = models.ForeignKey('Page', verbose_name=_('page'), related_name='revisions', on_delete=models.CASCADE) +~~ submitted_for_moderation = models.BooleanField( + verbose_name=_('submitted for moderation'), + default=False, + db_index=True + ) +~~ created_at = models.DateTimeField(db_index=True, verbose_name=_('created at')) +~~ user = models.ForeignKey( + settings.AUTH_USER_MODEL, verbose_name=_('user'), null=True, blank=True, +~~ on_delete=models.SET_NULL + ) +~~ content_json = models.TextField(verbose_name=_('content JSON')) +~~ approved_go_live_at = models.DateTimeField( + verbose_name=_('approved go live at'), + null=True, + blank=True, + db_index=True + ) + +~~ objects = models.Manager() + submitted_revisions = SubmittedRevisionsManager() + + def save(self, *args, **kwargs): + if self.created_at is None: + self.created_at = timezone.now() + + super().save(*args, **kwargs) + if self.submitted_for_moderation: + self.page.revisions.exclude(id=self.id).update(submitted_for_moderation=False) + + def as_page_object(self): + return self.page.specific.with_content_json(self.content_json) + + def approve_moderation(self): + if self.submitted_for_moderation: + logger.info("Page moderation approved: \"%s\" id=%d revision_id=%d", self.page.title, self.page.id, self.id) + self.publish() + + def reject_moderation(self): + if self.submitted_for_moderation: + logger.info("Page moderation rejected: \"%s\" id=%d revision_id=%d", self.page.title, self.page.id, self.id) + self.submitted_for_moderation = False + self.save(update_fields=['submitted_for_moderation']) + + + +## ... source file abbreviated to get to models examples ... + + + + def __str__(self): + return '"' + str(self.page) + '" at ' + str(self.created_at) + + class Meta: + verbose_name = _('page revision') + verbose_name_plural = _('page revisions') + + +PAGE_PERMISSION_TYPES = [ + ('add', _("Add"), _("Add/edit pages you own")), + ('edit', _("Edit"), _("Edit any page")), + ('publish', _("Publish"), _("Publish any page")), + ('bulk_delete', _("Bulk delete"), _("Delete pages with children")), + ('lock', _("Lock"), _("Lock/unlock pages you've locked")), + ('unlock', _("Unlock"), _("Unlock any page")), +] + +PAGE_PERMISSION_TYPE_CHOICES = [ + (identifier, long_label) + for identifier, short_label, long_label in PAGE_PERMISSION_TYPES +] + + +class GroupPagePermission(models.Model): +~~ group = models.ForeignKey(Group, verbose_name=_('group'), related_name='page_permissions', on_delete=models.CASCADE) +~~ page = models.ForeignKey('Page', verbose_name=_('page'), related_name='group_permissions', on_delete=models.CASCADE) +~~ permission_type = models.CharField( + verbose_name=_('permission type'), + max_length=20, + choices=PAGE_PERMISSION_TYPE_CHOICES + ) + + class Meta: + unique_together = ('group', 'page', 'permission_type') + verbose_name = _('group page permission') + verbose_name_plural = _('group page permissions') + + def __str__(self): + return "Group %d ('%s') has permission '%s' on page %d ('%s')" % ( + self.group.id, self.group, + self.permission_type, + self.page.id, self.page + ) + + +class UserPagePermissionsProxy: + + def __init__(self, user): + self.user = user + + if user.is_active and not user.is_superuser: + + +## ... source file abbreviated to get to models examples ... + + + if not destination.specific_class.creatable_subpage_models(): + return False + + if 'add' not in destination_perms.permissions: + return False + + return True + + def can_view_revisions(self): + return not self.page_is_root + + +class BaseViewRestriction(models.Model): + NONE = 'none' + PASSWORD = 'password' + GROUPS = 'groups' + LOGIN = 'login' + + RESTRICTION_CHOICES = ( + (NONE, _("Public")), + (LOGIN, _("Private, accessible to logged-in users")), + (PASSWORD, _("Private, accessible with the following password")), + (GROUPS, _("Private, accessible to users in specific groups")), + ) + +~~ restriction_type = models.CharField( + max_length=20, choices=RESTRICTION_CHOICES) +~~ password = models.CharField(verbose_name=_('password'), max_length=255, blank=True) +~~ groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True) + + def accept_request(self, request): + if self.restriction_type == BaseViewRestriction.PASSWORD: + passed_restrictions = request.session.get(self.passed_view_restrictions_session_key, []) + if self.id not in passed_restrictions: + return False + + elif self.restriction_type == BaseViewRestriction.LOGIN: + if not request.user.is_authenticated: + return False + + elif self.restriction_type == BaseViewRestriction.GROUPS: + if not request.user.is_superuser: + current_user_groups = request.user.groups.all() + + if not any(group in current_user_groups for group in self.groups.all()): + return False + + return True + + def mark_as_passed(self, request): + has_existing_session = (settings.SESSION_COOKIE_NAME in request.COOKIES) + passed_restrictions = request.session.setdefault(self.passed_view_restrictions_session_key, []) + if self.id not in passed_restrictions: + passed_restrictions.append(self.id) + request.session[self.passed_view_restrictions_session_key] = passed_restrictions + if not has_existing_session: + request.session.set_expiry(0) + + class Meta: + abstract = True + verbose_name = _('view restriction') + verbose_name_plural = _('view restrictions') + + +class PageViewRestriction(BaseViewRestriction): +~~ page = models.ForeignKey( +~~ 'Page', verbose_name=_('page'), related_name='view_restrictions', on_delete=models.CASCADE + ) + + passed_view_restrictions_session_key = 'passed_page_view_restrictions' + + class Meta: + verbose_name = _('page view restriction') + verbose_name_plural = _('page view restrictions') + + +class BaseCollectionManager(models.Manager): + def get_queryset(self): + return TreeQuerySet(self.model).order_by('path') + + +CollectionManager = BaseCollectionManager.from_queryset(TreeQuerySet) + + +class CollectionViewRestriction(BaseViewRestriction): +~~ collection = models.ForeignKey( + 'Collection', + verbose_name=_('collection'), + related_name='view_restrictions', +~~ on_delete=models.CASCADE + ) + + passed_view_restrictions_session_key = 'passed_collection_view_restrictions' + + class Meta: + verbose_name = _('collection view restriction') + verbose_name_plural = _('collection view restrictions') + + +class Collection(MP_Node): +~~ name = models.CharField(max_length=255, verbose_name=_('name')) + + objects = CollectionManager() + + def __str__(self): + return self.name + + def get_ancestors(self, inclusive=False): + return Collection.objects.ancestor_of(self, inclusive) + + def get_descendants(self, inclusive=False): + return Collection.objects.descendant_of(self, inclusive) + + def get_siblings(self, inclusive=True): + return Collection.objects.sibling_of(self, inclusive) + + def get_next_siblings(self, inclusive=False): + return self.get_siblings(inclusive).filter(path__gte=self.path).order_by('path') + + def get_prev_siblings(self, inclusive=False): + return self.get_siblings(inclusive).filter(path__lte=self.path).order_by('-path') + + def get_view_restrictions(self): + return CollectionViewRestriction.objects.filter(collection__in=self.get_ancestors(inclusive=True)) + + @staticmethod + def order_for_display(queryset): + return queryset.annotate( + display_order=Case( + When(depth=1, then=Value('')), + default='name') + ).order_by('display_order') + + class Meta: + verbose_name = _('collection') + verbose_name_plural = _('collections') + + +def get_root_collection_id(): + return Collection.get_first_root_node().id + + +class CollectionMember(models.Model): +~~ collection = models.ForeignKey( + Collection, + default=get_root_collection_id, + verbose_name=_('collection'), + related_name='+', +~~ on_delete=models.CASCADE + ) + + search_fields = [ + index.FilterField('collection'), + ] + + class Meta: + abstract = True + + +class GroupCollectionPermission(models.Model): +~~ group = models.ForeignKey( + Group, + verbose_name=_('group'), + related_name='collection_permissions', +~~ on_delete=models.CASCADE + ) +~~ collection = models.ForeignKey( + Collection, + verbose_name=_('collection'), + related_name='group_permissions', +~~ on_delete=models.CASCADE + ) +~~ permission = models.ForeignKey( + Permission, + verbose_name=_('permission'), +~~ on_delete=models.CASCADE + ) + + def __str__(self): + return "Group %d ('%s') has permission '%s' on collection %d ('%s')" % ( + self.group.id, self.group, + self.permission, + self.collection.id, self.collection + ) + + class Meta: + unique_together = ('group', 'collection', 'permission') + verbose_name = _('group collection permission') + verbose_name_plural = _('group collection permissions') + + ] + + is_creatable = False + + + +## ... source file abbreviated to get to models examples ... + + + "Invalid subpage_types setting for %s" % cls, + hint=str(e), + id='wagtailcore.E002' + ) + + +## ... source file continues with no further models examples... + +``` + diff --git a/content/pages/examples/django/django-db-programmingerror.markdown b/content/pages/examples/django/django-db-programmingerror.markdown new file mode 100644 index 000000000..6b3037811 --- /dev/null +++ b/content/pages/examples/django/django-db-programmingerror.markdown @@ -0,0 +1,232 @@ +title: django.db ProgrammingError Example Code +category: page +slug: django-db-programmingerror-examples +sortorder: 500011163 +toc: False +sidebartitle: django.db ProgrammingError +meta: Python example code for the ProgrammingError class from the django.db module of the Django project. + + +ProgrammingError is a class within the django.db module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / appresolver.py**](https://github.com/divio/django-cms/blob/develop/cms/./appresolver.py) + +```python +# appresolver.py +from collections import OrderedDict +from importlib import import_module + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +~~from django.db import OperationalError, ProgrammingError +from django.utils.translation import get_language, override +from django.urls import Resolver404, reverse + +from six import string_types + +from cms.apphook_pool import apphook_pool +from cms.models.pagemodel import Page +from cms.utils import get_current_site +from cms.utils.compat import DJANGO_1_11 +from cms.utils.compat.dj import RegexPattern, URLPattern, URLResolver +from cms.utils.i18n import get_language_list +from cms.utils.moderator import use_draft + + +APP_RESOLVERS = [] + + +def clear_app_resolvers(): + global APP_RESOLVERS + APP_RESOLVERS = [] + + +def applications_page_check(request, current_page=None, path=None): + if current_page: + + +## ... source file abbreviated to get to ProgrammingError examples ... + + + if not hasattr(mod, 'urlpatterns'): + raise ImproperlyConfigured( + "URLConf `%s` has no urlpatterns attribute" % urlconf) + yield getattr(mod, 'urlpatterns') + elif isinstance(urlconf, (list, tuple)): + yield urlconf + else: + yield [urlconf] + + +def get_patterns_for_title(path, title): + app = apphook_pool.get_apphook(title.page.application_urls) + url_patterns = [] + for pattern_list in get_app_urls(app.get_urls(title.page, title.language)): + if path and not path.endswith('/'): + path += '/' + page_id = title.page.id + url_patterns += recurse_patterns(path, pattern_list, page_id) + return url_patterns + + +def get_app_patterns(): + try: + site = get_current_site() + return _get_app_patterns(site) +~~ except (OperationalError, ProgrammingError): + return [] + + +def _get_app_patterns(site): + from cms.models import Title + + included = [] + + title_qs = Title.objects.public().filter(page__node__site=site) + + hooked_applications = OrderedDict() + + titles = (title_qs.exclude(page__application_urls=None) + .exclude(page__application_urls='') + .order_by('-page__node__path').select_related()) + for title in titles: + path = title.path + mix_id = "%s:%s:%s" % ( + path + "/", title.page.application_urls, title.language) + if mix_id in included: + continue + if not settings.APPEND_SLASH: + path += '/' + app = apphook_pool.get_apphook(title.page.application_urls) + + +## ... source file continues with no further ProgrammingError examples... + +``` + + +## Example 2 from django-migration-linter +[django-migration-linter](https://github.com/3YOURMIND/django-migration-linter) +([PyPI package information](https://pypi.org/project/django-migration-linter/)) +checks for backwards-incompatible changes in [Django ORM](/django-orm.html) +schema migrations and warns you about them. The purpose of the project is +to save time in older and larger projects by detecting field migrations +that will be a problem so you do not run into issues later, and make it +easier to enable continuous [deployment](/deployment.html) configurations +with database changes. There is a +[blog post on keeping Django database migrations backward compatible](https://medium.com/3yourmind/keeping-django-database-migrations-backward-compatible-727820260dbb) +that goes into further detail on the tool. + +The django-migration-linter project is open sourced under the +[Apache 2.0 license](https://github.com/3YOURMIND/django-migration-linter/blob/master/LICENSE). + +[**django-migration-linter / django_migration_linter / migration_linter.py**](https://github.com/3YOURMIND/django-migration-linter/blob/master/django_migration_linter/./migration_linter.py) + +```python +# migration_linter.py +from __future__ import print_function + +import hashlib +import inspect +import logging +import os +import re +from subprocess import Popen, PIPE + +from django.conf import settings +from django.core.management import call_command +~~from django.db import DEFAULT_DB_ALIAS, connections, ProgrammingError +from django.db.migrations import RunPython +from enum import Enum, unique +from six import PY2 + +from .cache import Cache +from .constants import ( + DEFAULT_CACHE_PATH, + EXPECTED_DATA_MIGRATION_ARGS, + DJANGO_APPS_WITH_MIGRATIONS, +) +from .utils import clean_bytes_to_str, get_migration_abspath, split_migration_path +from .operations import IgnoreMigration +from .sql_analyser import analyse_sql_statements + +logger = logging.getLogger(__name__) + + +@unique +class MessageType(Enum): + OK = "ok" + IGNORE = "ignore" + WARNING = "warning" + ERROR = "error" + + + +## ... source file abbreviated to get to ProgrammingError examples ... + + + def print_summary(self): + print() + print("*** Summary ***") + print("Valid migrations: {}/{}".format(self.nb_valid, self.nb_total)) + print("Erroneous migrations: {}/{}".format(self.nb_erroneous, self.nb_total)) + print("Migrations with warnings: {}/{}".format(self.nb_warnings, self.nb_total)) + print("Ignored migrations: {}/{}".format(self.nb_ignored, self.nb_total)) + + @property + def has_errors(self): + return self.nb_erroneous > 0 + + def get_sql(self, app_label, migration_name): + logger.info( + "Calling sqlmigrate command {} {}".format(app_label, migration_name) + ) + dev_null = open(os.devnull, "w") + try: + sql_statement = call_command( + "sqlmigrate", + app_label, + migration_name, + database=self.database, + stdout=dev_null, + ) +~~ except (ValueError, ProgrammingError): + logger.warning( + ( + "Error while executing sqlmigrate on (%s, %s). " + "Continuing execution with empty SQL." + ), + app_label, + migration_name, + ) + sql_statement = "" + return sql_statement.splitlines() + + @staticmethod + def is_migration_file(filename): + from django.db.migrations.loader import MIGRATIONS_MODULE_NAME + + return ( + re.search(r"/{0}/.*\.py".format(MIGRATIONS_MODULE_NAME), filename) + and "__init__" not in filename + ) + + @classmethod + def read_migrations_list(cls, migrations_file_path): + if not migrations_file_path: + return None + + +## ... source file continues with no further ProgrammingError examples... + +``` + diff --git a/content/pages/examples/django/django-db-router.markdown b/content/pages/examples/django/django-db-router.markdown new file mode 100644 index 000000000..7987041a7 --- /dev/null +++ b/content/pages/examples/django/django-db-router.markdown @@ -0,0 +1,522 @@ +title: django.db router Example Code +category: page +slug: django-db-router-examples +sortorder: 500011168 +toc: False +sidebartitle: django.db router +meta: Python example code for the router callable from the django.db module of the Django project. + + +router is a callable within the django.db module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / admin / placeholderadmin.py**](https://github.com/divio/django-cms/blob/develop/cms/admin/placeholderadmin.py) + +```python +# placeholderadmin.py +import uuid +import warnings + +from django.conf.urls import url +from django.contrib.admin.helpers import AdminForm +from django.contrib.admin.utils import get_deleted_objects +from django.core.exceptions import PermissionDenied +~~from django.db import router, transaction +from django.http import ( + HttpResponse, + HttpResponseBadRequest, + HttpResponseForbidden, + HttpResponseNotFound, + HttpResponseRedirect, +) +from django.shortcuts import get_list_or_404, get_object_or_404, render +from django.template.response import TemplateResponse +from django.utils.decorators import method_decorator +from django.utils.encoding import force_text +from django.utils import translation +from django.utils.translation import ugettext as _ +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.decorators.http import require_POST + +from six.moves.urllib.parse import parse_qsl, urlparse + +from six import get_unbound_function, get_method_function + +from cms import operations +from cms.admin.forms import PluginAddValidationForm +from cms.constants import SLUG_REGEXP +from cms.exceptions import PluginLimitReached + + +## ... source file abbreviated to get to router examples ... + + + source_placeholder.mark_as_dirty(target_language, clear_cache=False) + + self._send_post_placeholder_operation( + request, + operation=operations.CUT_PLUGIN, + token=action_token, + plugin=updated_plugin.get_bound_plugin(), + clipboard=target_placeholder, + clipboard_language=target_language, + source_language=source_language, + source_placeholder=source_placeholder, + source_parent_id=plugin.parent_id, + source_order=new_source_order, + ) + return updated_plugin + + @xframe_options_sameorigin + def delete_plugin(self, request, plugin_id): + plugin = self._get_plugin_from_id(plugin_id) + + if not self.has_delete_plugin_permission(request, plugin): + return HttpResponseForbidden(force_text( + _("You do not have permission to delete this plugin"))) + + opts = plugin._meta +~~ using = router.db_for_write(opts.model) + if DJANGO_2_0: + get_deleted_objects_additional_kwargs = { + 'opts': opts, + 'using': using, + 'user': request.user, + } + else: + get_deleted_objects_additional_kwargs = {'request': request} + deleted_objects, __, perms_needed, protected = get_deleted_objects( + [plugin], admin_site=self.admin_site, + **get_deleted_objects_additional_kwargs + ) + + if request.POST: # The user has already confirmed the deletion. + if perms_needed: + raise PermissionDenied(_("You do not have permission to delete this plugin")) + obj_display = force_text(plugin) + placeholder = plugin.placeholder + plugin_tree_order = placeholder.get_plugin_tree_order( + language=plugin.language, + parent_id=plugin.parent_id, + ) + + operation_token = self._send_pre_placeholder_operation( + + +## ... source file abbreviated to get to router examples ... + + + "object": plugin, + "deleted_objects": deleted_objects, + "perms_lacking": perms_needed, + "protected": protected, + "opts": opts, + "app_label": opts.app_label, + } + request.current_app = self.admin_site.name + return TemplateResponse( + request, "admin/cms/page/plugin/delete_confirmation.html", context + ) + + @xframe_options_sameorigin + def clear_placeholder(self, request, placeholder_id): + placeholder = get_object_or_404(Placeholder, pk=placeholder_id) + language = request.GET.get('language') + + if placeholder.pk == request.toolbar.clipboard.pk: + placeholder.clear(language) + return HttpResponseRedirect(admin_reverse('index', current_app=self.admin_site.name)) + + if not self.has_clear_placeholder_permission(request, placeholder, language): + return HttpResponseForbidden(force_text(_("You do not have permission to clear this placeholder"))) + + opts = Placeholder._meta +~~ using = router.db_for_write(Placeholder) + plugins = placeholder.get_plugins_list(language) + + if DJANGO_2_0: + get_deleted_objects_additional_kwargs = { + 'opts': opts, + 'using': using, + 'user': request.user, + } + else: + get_deleted_objects_additional_kwargs = {'request': request} + deleted_objects, __, perms_needed, protected = get_deleted_objects( + plugins, admin_site=self.admin_site, + **get_deleted_objects_additional_kwargs + ) + + obj_display = force_text(placeholder) + + if request.POST: + if perms_needed: + return HttpResponseForbidden(force_text(_("You do not have permission to clear this placeholder"))) + + operation_token = self._send_pre_placeholder_operation( + request, + operation=operations.CLEAR_PLACEHOLDER, + + +## ... source file continues with no further router examples... + +``` + + +## Example 2 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / folderadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/folderadmin.py) + +```python +# folderadmin.py +from __future__ import absolute_import, division, unicode_literals + +import itertools +import os +import re +from collections import OrderedDict + +from django import forms +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import messages +from django.contrib.admin import helpers +from django.contrib.admin.utils import capfirst, quote, unquote +from django.core.exceptions import PermissionDenied, ValidationError +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +~~from django.db import models, router +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils.encoding import force_text +from django.utils.html import escape +from django.utils.http import urlquote, urlunquote +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy, ungettext + +from .. import settings +from ..models import ( + File, Folder, FolderPermission, FolderRoot, ImagesWithMissingData, + UnsortedImages, tools, +) +from ..settings import FILER_IMAGE_MODEL, FILER_PAGINATE_BY +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import get_delete_permission +from ..utils.filer_easy_thumbnails import FilerActionThumbnailer +from ..utils.loader import load_model +from . import views +from .forms import CopyFilesAndFoldersForm, RenameFilesForm, ResizeImagesForm +from .patched.admin_utils import get_deleted_objects +from .permissions import PrimitivePermissionAwareModelAdmin + + +## ... source file abbreviated to get to router examples ... + + + return self.files_set_public_or_private(request, False, files_queryset, + folders_queryset) + + files_set_private.short_description = ugettext_lazy( + "Enable permissions for selected files") + + def files_set_public(self, request, files_queryset, folders_queryset): + return self.files_set_public_or_private(request, True, files_queryset, + folders_queryset) + + files_set_public.short_description = ugettext_lazy( + "Disable permissions for selected files") + + def delete_files_or_folders(self, request, files_queryset, folders_queryset): + opts = self.model._meta + app_label = opts.app_label + + if not self.has_delete_permission(request): + raise PermissionDenied + + current_folder = self._get_current_action_folder( + request, files_queryset, folders_queryset) + + all_protected = [] + +~~ using = router.db_for_write(self.model) + deletable_files, model_count_files, perms_needed_files, protected_files = get_deleted_objects(files_queryset, files_queryset.model._meta, request.user, self.admin_site, using) + deletable_folders, model_count_folder, perms_needed_folders, protected_folders = get_deleted_objects(folders_queryset, folders_queryset.model._meta, request.user, self.admin_site, using) + all_protected.extend(protected_files) + all_protected.extend(protected_folders) + + all_deletable_objects = [deletable_files, deletable_folders] + all_perms_needed = perms_needed_files.union(perms_needed_folders) + + if request.POST.get('post'): + if all_perms_needed: + raise PermissionDenied + n = files_queryset.count() + folders_queryset.count() + if n: + for f in files_queryset: + self.log_deletion(request, f, force_text(f)) + f.delete() + folder_ids = set() + for folder in folders_queryset: + folder_ids.add(folder.id) + folder_ids.update( + folder.get_descendants().values_list('id', flat=True)) + for f in File.objects.filter(folder__in=folder_ids): + self.log_deletion(request, f, force_text(f)) + f.delete() + + +## ... source file continues with no further router examples... + +``` + + +## Example 3 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / management / __init__.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/management/__init__.py) + +```python +# __init__.py +from django.contrib.auth import get_user_model +from django.db.models import signals +from django.utils.module_loading import import_string +~~from django.db import router +from guardian.conf import settings as guardian_settings + + +def get_init_anonymous_user(User): + kwargs = { + User.USERNAME_FIELD: guardian_settings.ANONYMOUS_USER_NAME + } + user = User(**kwargs) + user.set_unusable_password() + return user + + +def create_anonymous_user(sender, **kwargs): + User = get_user_model() +~~ if not router.allow_migrate_model(kwargs['using'], User): + return + try: + lookup = {User.USERNAME_FIELD: guardian_settings.ANONYMOUS_USER_NAME} + User.objects.using(kwargs['using']).get(**lookup) + except User.DoesNotExist: + retrieve_anonymous_function = import_string( + guardian_settings.GET_INIT_ANONYMOUS_USER) + user = retrieve_anonymous_function(User) + user.save(using=kwargs['using']) + +if guardian_settings.ANONYMOUS_USER_NAME is not None: + from django.apps import apps + guardian_app = apps.get_app_config('guardian') + signals.post_migrate.connect(create_anonymous_user, sender=guardian_app, + dispatch_uid="guardian.management.create_anonymous_user") + + + +## ... source file continues with no further router examples... + +``` + + +## Example 4 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / models.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./models.py) + +```python +# models.py +from django.core.exceptions import ImproperlyConfigured +~~from django.db import models, transaction, router +from django.db.models.signals import post_save, pre_save +from django.utils.translation import gettext_lazy as _ + +from model_utils.fields import ( + AutoCreatedField, + AutoLastModifiedField, + StatusField, + MonitorField, + UUIDField, +) +from model_utils.managers import ( + QueryManager, + SoftDeletableManager, +) + +from django.db.models.functions import Now +now = Now() + + +class TimeStampedModel(models.Model): + created = AutoCreatedField(_('created')) + modified = AutoLastModifiedField(_('modified')) + + def save(self, *args, **kwargs): + + +## ... source file abbreviated to get to router examples ... + + + + +class UUIDModel(models.Model): + id = UUIDField( + primary_key=True, + version=4, + editable=False, + ) + + class Meta: + abstract = True + + +class SaveSignalHandlingModel(models.Model): + class Meta: + abstract = True + + def save(self, signals_to_disable=None, *args, **kwargs): + + self.signals_to_disable = signals_to_disable or [] + + super().save(*args, **kwargs) + + def save_base(self, raw=False, force_insert=False, + force_update=False, using=None, update_fields=None): +~~ using = using or router.db_for_write(self.__class__, instance=self) + assert not (force_insert and (force_update or update_fields)) + assert update_fields is None or len(update_fields) > 0 + cls = origin = self.__class__ + + if cls._meta.proxy: + cls = cls._meta.concrete_model + meta = cls._meta + if not meta.auto_created and 'pre_save' not in self.signals_to_disable: + pre_save.send( + sender=origin, instance=self, raw=raw, using=using, + update_fields=update_fields, + ) + with transaction.atomic(using=using, savepoint=False): + if not raw: + self._save_parents(cls, using, update_fields) + updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) + + self._state.db = using + self._state.adding = False + + if not meta.auto_created and 'post_save' not in self.signals_to_disable: + post_save.send( + sender=origin, instance=self, created=(not updated), + update_fields=update_fields, raw=raw, using=using, + + +## ... source file continues with no further router examples... + +``` + + +## Example 5 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / models.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./models.py) + +```python +# models.py +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +~~from django.db import IntegrityError, models, router, transaction +from django.utils.text import slugify +from django.utils.translation import gettext, gettext_lazy as _ + +try: + from unidecode import unidecode +except ImportError: + + def unidecode(tag): + return tag + + +class TagBase(models.Model): + name = models.CharField(verbose_name=_("name"), unique=True, max_length=100) + slug = models.SlugField(verbose_name=_("slug"), unique=True, max_length=100) + + def __str__(self): + return self.name + + def __gt__(self, other): + return self.name.lower() > other.name.lower() + + def __lt__(self, other): + return self.name.lower() < other.name.lower() + + class Meta: + abstract = True + + def save(self, *args, **kwargs): + if self._state.adding and not self.slug: + self.slug = self.slugify(self.name) +~~ using = kwargs.get("using") or router.db_for_write( + type(self), instance=self + ) + kwargs["using"] = using + try: + with transaction.atomic(using=using): + res = super().save(*args, **kwargs) + return res + except IntegrityError: + pass + slugs = set( + type(self) + ._default_manager.filter(slug__startswith=self.slug) + .values_list("slug", flat=True) + ) + i = 1 + while True: + slug = self.slugify(self.name, i) + if slug not in slugs: + self.slug = slug + return super().save(*args, **kwargs) + i += 1 + else: + return super().save(*args, **kwargs) + + + +## ... source file continues with no further router examples... + +``` + diff --git a/content/pages/examples/django/django-db-transaction.markdown b/content/pages/examples/django/django-db-transaction.markdown new file mode 100644 index 000000000..163c44043 --- /dev/null +++ b/content/pages/examples/django/django-db-transaction.markdown @@ -0,0 +1,707 @@ +title: django.db transaction Example Code +category: page +slug: django-db-transaction-examples +sortorder: 500011169 +toc: False +sidebartitle: django.db transaction +meta: Python example code for the transaction callable from the django.db module of the Django project. + + +transaction is a callable within the django.db module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / models.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/models.py) + +```python +# models.py +from __future__ import unicode_literals + +import datetime + +from django.core import signing +~~from django.db import models, transaction +from django.utils import timezone +from django.utils.crypto import get_random_string +from django.utils.translation import gettext_lazy as _ + +from .. import app_settings as allauth_app_settings +from . import app_settings, signals +from .adapter import get_adapter +from .managers import EmailAddressManager, EmailConfirmationManager +from .utils import user_email + + +class EmailAddress(models.Model): + + user = models.ForeignKey(allauth_app_settings.USER_MODEL, + verbose_name=_('user'), + on_delete=models.CASCADE) + email = models.EmailField(unique=app_settings.UNIQUE_EMAIL, + max_length=app_settings.EMAIL_MAX_LENGTH, + verbose_name=_('e-mail address')) + verified = models.BooleanField(verbose_name=_('verified'), default=False) + primary = models.BooleanField(verbose_name=_('primary'), default=False) + + objects = EmailAddressManager() + + + +## ... source file abbreviated to get to transaction examples ... + + + def __str__(self): + return self.email + + def set_as_primary(self, conditional=False): + old_primary = EmailAddress.objects.get_primary(self.user) + if old_primary: + if conditional: + return False + old_primary.primary = False + old_primary.save() + self.primary = True + self.save() + user_email(self.user, self.email) + self.user.save() + return True + + def send_confirmation(self, request=None, signup=False): + if app_settings.EMAIL_CONFIRMATION_HMAC: + confirmation = EmailConfirmationHMAC(self) + else: + confirmation = EmailConfirmation.create(self) + confirmation.send(request, signup=signup) + return confirmation + + def change(self, request, new_email, confirm=True): +~~ with transaction.atomic(): + user_email(self.user, new_email) + self.user.save() + self.email = new_email + self.verified = False + self.save() + if confirm: + self.send_confirmation(request) + + +class EmailConfirmation(models.Model): + + email_address = models.ForeignKey(EmailAddress, + verbose_name=_('e-mail address'), + on_delete=models.CASCADE) + created = models.DateTimeField(verbose_name=_('created'), + default=timezone.now) + sent = models.DateTimeField(verbose_name=_('sent'), null=True) + key = models.CharField(verbose_name=_('key'), max_length=64, unique=True) + + objects = EmailConfirmationManager() + + class Meta: + verbose_name = _("email confirmation") + verbose_name_plural = _("email confirmations") + + +## ... source file continues with no further transaction examples... + +``` + + +## Example 2 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / utils.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./utils.py) + +```python +# utils.py +~~from django.db import transaction + + +class atomic_if_using_transaction: + def __init__(self, using_transactions): + self.using_transactions = using_transactions + if using_transactions: +~~ self.context_manager = transaction.atomic() + + def __enter__(self): + if self.using_transactions: + self.context_manager.__enter__() + + def __exit__(self, *args): + if self.using_transactions: + self.context_manager.__exit__(*args) + + + +## ... source file continues with no further transaction examples... + +``` + + +## Example 3 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / models.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./models.py) + +```python +# models.py +from django.core.exceptions import ImproperlyConfigured +~~from django.db import models, transaction, router +from django.db.models.signals import post_save, pre_save +from django.utils.translation import gettext_lazy as _ + +from model_utils.fields import ( + AutoCreatedField, + AutoLastModifiedField, + StatusField, + MonitorField, + UUIDField, +) +from model_utils.managers import ( + QueryManager, + SoftDeletableManager, +) + +from django.db.models.functions import Now +now = Now() + + +class TimeStampedModel(models.Model): + created = AutoCreatedField(_('created')) + modified = AutoLastModifiedField(_('modified')) + + def save(self, *args, **kwargs): + + +## ... source file abbreviated to get to transaction examples ... + + +class SaveSignalHandlingModel(models.Model): + class Meta: + abstract = True + + def save(self, signals_to_disable=None, *args, **kwargs): + + self.signals_to_disable = signals_to_disable or [] + + super().save(*args, **kwargs) + + def save_base(self, raw=False, force_insert=False, + force_update=False, using=None, update_fields=None): + using = using or router.db_for_write(self.__class__, instance=self) + assert not (force_insert and (force_update or update_fields)) + assert update_fields is None or len(update_fields) > 0 + cls = origin = self.__class__ + + if cls._meta.proxy: + cls = cls._meta.concrete_model + meta = cls._meta + if not meta.auto_created and 'pre_save' not in self.signals_to_disable: + pre_save.send( + sender=origin, instance=self, raw=raw, using=using, + update_fields=update_fields, + ) +~~ with transaction.atomic(using=using, savepoint=False): + if not raw: + self._save_parents(cls, using, update_fields) + updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) + + self._state.db = using + self._state.adding = False + + if not meta.auto_created and 'post_save' not in self.signals_to_disable: + post_save.send( + sender=origin, instance=self, created=(not updated), + update_fields=update_fields, raw=raw, using=using, + ) + + self.signals_to_disable = [] + + + +## ... source file continues with no further transaction examples... + +``` + + +## Example 4 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / models.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./models.py) + +```python +# models.py +import logging +from datetime import timedelta +from urllib.parse import parse_qsl, urlparse + +from django.apps import apps +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +~~from django.db import models, transaction +from django.urls import reverse +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ + +from .generators import generate_client_id, generate_client_secret +from .scopes import get_scopes_backend +from .settings import oauth2_settings +from .validators import RedirectURIValidator, WildcardSet + + +logger = logging.getLogger(__name__) + + +class AbstractApplication(models.Model): + CLIENT_CONFIDENTIAL = "confidential" + CLIENT_PUBLIC = "public" + CLIENT_TYPES = ( + (CLIENT_CONFIDENTIAL, _("Confidential")), + (CLIENT_PUBLIC, _("Public")), + ) + + GRANT_AUTHORIZATION_CODE = "authorization-code" + GRANT_IMPLICIT = "implicit" + GRANT_PASSWORD = "password" + + +## ... source file abbreviated to get to transaction examples ... + + + class Meta(AbstractAccessToken.Meta): + swappable = "OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL" + + +class AbstractRefreshToken(models.Model): + id = models.BigAutoField(primary_key=True) + user = models.ForeignKey( + settings.AUTH_USER_MODEL, on_delete=models.CASCADE, + related_name="%(app_label)s_%(class)s" + ) + token = models.CharField(max_length=255) + application = models.ForeignKey( + oauth2_settings.APPLICATION_MODEL, on_delete=models.CASCADE) + access_token = models.OneToOneField( + oauth2_settings.ACCESS_TOKEN_MODEL, on_delete=models.SET_NULL, blank=True, null=True, + related_name="refresh_token" + ) + + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + revoked = models.DateTimeField(null=True) + + def revoke(self): + access_token_model = get_access_token_model() + refresh_token_model = get_refresh_token_model() +~~ with transaction.atomic(): + self = refresh_token_model.objects.filter( + pk=self.pk, revoked__isnull=True + ).select_for_update().first() + if not self: + return + + try: + access_token_model.objects.get(id=self.access_token_id).revoke() + except access_token_model.DoesNotExist: + pass + self.access_token = None + self.revoked = timezone.now() + self.save() + + def __str__(self): + return self.token + + class Meta: + abstract = True + unique_together = ("token", "revoked",) + + +class RefreshToken(AbstractRefreshToken): + class Meta(AbstractRefreshToken.Meta): + + +## ... source file abbreviated to get to transaction examples ... + + + +def get_access_token_model(): + return apps.get_model(oauth2_settings.ACCESS_TOKEN_MODEL) + + +def get_refresh_token_model(): + return apps.get_model(oauth2_settings.REFRESH_TOKEN_MODEL) + + +def clear_expired(): + now = timezone.now() + refresh_expire_at = None + access_token_model = get_access_token_model() + refresh_token_model = get_refresh_token_model() + grant_model = get_grant_model() + REFRESH_TOKEN_EXPIRE_SECONDS = oauth2_settings.REFRESH_TOKEN_EXPIRE_SECONDS + if REFRESH_TOKEN_EXPIRE_SECONDS: + if not isinstance(REFRESH_TOKEN_EXPIRE_SECONDS, timedelta): + try: + REFRESH_TOKEN_EXPIRE_SECONDS = timedelta(seconds=REFRESH_TOKEN_EXPIRE_SECONDS) + except TypeError: + e = "REFRESH_TOKEN_EXPIRE_SECONDS must be either a timedelta or seconds" + raise ImproperlyConfigured(e) + refresh_expire_at = now - REFRESH_TOKEN_EXPIRE_SECONDS + +~~ with transaction.atomic(): + if refresh_expire_at: + revoked = refresh_token_model.objects.filter( + revoked__lt=refresh_expire_at, + ) + expired = refresh_token_model.objects.filter( + access_token__expires__lt=refresh_expire_at, + ) + + logger.info("%s Revoked refresh tokens to be deleted", revoked.count()) + logger.info("%s Expired refresh tokens to be deleted", expired.count()) + + revoked.delete() + expired.delete() + else: + logger.info("refresh_expire_at is %s. No refresh tokens deleted.", + refresh_expire_at) + + access_tokens = access_token_model.objects.filter( + refresh_token__isnull=True, + expires__lt=now + ) + grants = grant_model.objects.filter(expires__lt=now) + + logger.info("%s Expired access tokens to be deleted", access_tokens.count()) + + +## ... source file continues with no further transaction examples... + +``` + + +## Example 5 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / views.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./views.py) + +```python +# views.py +from django.conf import settings +from django.core.exceptions import PermissionDenied +~~from django.db import connection, models, transaction +from django.http import Http404 +from django.http.response import HttpResponseBase +from django.utils.cache import cc_delim_re, patch_vary_headers +from django.utils.encoding import smart_str +from django.views.decorators.csrf import csrf_exempt +from django.views.generic import View + +from rest_framework import exceptions, status +from rest_framework.request import Request +from rest_framework.response import Response +from rest_framework.schemas import DefaultSchema +from rest_framework.settings import api_settings +from rest_framework.utils import formatting + + +def get_view_name(view): + name = getattr(view, 'name', None) + if name is not None: + return name + + name = view.__class__.__name__ + name = formatting.remove_trailing_string(name, 'View') + name = formatting.remove_trailing_string(name, 'ViewSet') + name = formatting.camelcase_to_spaces(name) + + suffix = getattr(view, 'suffix', None) + if suffix: + name += ' ' + suffix + + return name + + +def get_view_description(view, html=False): + description = getattr(view, 'description', None) + if description is None: + description = view.__class__.__doc__ or '' + + description = formatting.dedent(smart_str(description)) + if html: + return formatting.markup_description(description) + return description + + +def set_rollback(): + atomic_requests = connection.settings_dict.get('ATOMIC_REQUESTS', False) + if atomic_requests and connection.in_atomic_block: +~~ transaction.set_rollback(True) + + +def exception_handler(exc, context): + if isinstance(exc, Http404): + exc = exceptions.NotFound() + elif isinstance(exc, PermissionDenied): + exc = exceptions.PermissionDenied() + + if isinstance(exc, exceptions.APIException): + headers = {} + if getattr(exc, 'auth_header', None): + headers['WWW-Authenticate'] = exc.auth_header + if getattr(exc, 'wait', None): + headers['Retry-After'] = '%d' % exc.wait + + if isinstance(exc.detail, (list, dict)): + data = exc.detail + else: + data = {'detail': exc.detail} + + set_rollback() + return Response(data, status=exc.status_code, headers=headers) + + return None + + +## ... source file continues with no further transaction examples... + +``` + + +## Example 6 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / models.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./models.py) + +```python +# models.py +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +~~from django.db import IntegrityError, models, router, transaction +from django.utils.text import slugify +from django.utils.translation import gettext, gettext_lazy as _ + +try: + from unidecode import unidecode +except ImportError: + + def unidecode(tag): + return tag + + +class TagBase(models.Model): + name = models.CharField(verbose_name=_("name"), unique=True, max_length=100) + slug = models.SlugField(verbose_name=_("slug"), unique=True, max_length=100) + + def __str__(self): + return self.name + + def __gt__(self, other): + return self.name.lower() > other.name.lower() + + def __lt__(self, other): + return self.name.lower() < other.name.lower() + + class Meta: + abstract = True + + def save(self, *args, **kwargs): + if self._state.adding and not self.slug: + self.slug = self.slugify(self.name) + using = kwargs.get("using") or router.db_for_write( + type(self), instance=self + ) + kwargs["using"] = using + try: +~~ with transaction.atomic(using=using): + res = super().save(*args, **kwargs) + return res + except IntegrityError: + pass + slugs = set( + type(self) + ._default_manager.filter(slug__startswith=self.slug) + .values_list("slug", flat=True) + ) + i = 1 + while True: + slug = self.slugify(self.name, i) + if slug not in slugs: + self.slug = slug + return super().save(*args, **kwargs) + i += 1 + else: + return super().save(*args, **kwargs) + + def slugify(self, tag, i=None): + slug = slugify(unidecode(tag)) + if i is not None: + slug += "_%d" % i + return slug + + +## ... source file continues with no further transaction examples... + +``` + + +## Example 7 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / models.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/models.py) + +```python +# models.py +import json +import logging +from collections import defaultdict +from io import StringIO +from urllib.parse import urlparse + +from django.conf import settings +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core import checks +from django.core.cache import cache +from django.core.exceptions import ValidationError +from django.core.handlers.base import BaseHandler +from django.core.handlers.wsgi import WSGIRequest +~~from django.db import models, transaction +from django.db.models import Case, Q, Value, When +from django.db.models.functions import Concat, Lower, Substr +from django.http import Http404 +from django.http.request import split_domain_port +from django.template.response import TemplateResponse +from django.urls import NoReverseMatch, reverse +from django.utils import timezone +from django.utils.cache import patch_cache_control +from django.utils.functional import cached_property +from django.utils.text import capfirst, slugify +from django.utils.translation import gettext_lazy as _ +from modelcluster.models import ( + ClusterableModel, get_all_child_m2m_relations, get_all_child_relations) +from treebeard.mp_tree import MP_Node + +from wagtail.core.query import PageQuerySet, TreeQuerySet +from wagtail.core.signals import page_published, page_unpublished, post_page_move, pre_page_move +from wagtail.core.sites import get_site_for_hostname +from wagtail.core.url_routing import RouteResult +from wagtail.core.utils import WAGTAIL_APPEND_SLASH, camelcase_to_underscore, resolve_model_string +from wagtail.search import index + + +logger = logging.getLogger('wagtail.core') + + +## ... source file abbreviated to get to transaction examples ... + + + return self.revisions.exclude(approved_go_live_at__isnull=True).exists() + + def has_unpublished_subtree(self): + return (not self.live) and (not self.get_descendants().filter(live=True).exists()) + + def move(self, target, pos=None): + parent_before = self.get_parent() + if pos in ('first-child', 'last-child', 'sorted-child'): + parent_after = target + else: + parent_after = target.get_parent() + + old_self = Page.objects.get(id=self.id) + old_url_path = old_self.url_path + new_url_path = old_self.set_url_path(parent=parent_after) + + pre_page_move.send( + sender=self.specific_class or self.__class__, + instance=self, + parent_page_before=parent_before, + parent_page_after=parent_after, + url_path_before=old_url_path, + url_path_after=new_url_path, + ) + +~~ with transaction.atomic(): + super().move(target, pos=pos) + + new_self = Page.objects.get(id=self.id) + new_self.url_path = new_url_path + new_self.save() + + if old_url_path != new_url_path: + new_self._update_descendant_url_paths(old_url_path, new_url_path) + + post_page_move.send( + sender=self.specific_class or self.__class__, + instance=new_self, + parent_page_before=parent_before, + parent_page_after=parent_after, + url_path_before=old_url_path, + url_path_after=new_url_path, + ) + + logger.info("Page moved: \"%s\" id=%d path=%s", self.title, self.id, new_url_path) + + def copy(self, recursive=False, to=None, update_attrs=None, copy_revisions=True, keep_live=True, user=None, process_child_object=None, exclude_fields=None): + specific_self = self.specific + default_exclude_fields = ['id', 'path', 'depth', 'numchild', 'url_path', 'path', 'index_entries'] + exclude_fields = default_exclude_fields + specific_self.exclude_fields_in_copy + (exclude_fields or []) + + +## ... source file continues with no further transaction examples... + +``` + diff --git a/content/pages/examples/django/django-extensions-plug-ins.markdown b/content/pages/examples/django/django-extensions-plug-ins.markdown index eb7e5fbce..632cde7da 100644 --- a/content/pages/examples/django/django-extensions-plug-ins.markdown +++ b/content/pages/examples/django/django-extensions-plug-ins.markdown @@ -75,19 +75,31 @@ Code from django-angular is shown on: * [django.utils.html format_html](/django-utils-html-format-html-examples.html) * [django.urls.exceptions NoReverseMatch](/django-urls-exceptions-noreversematch-examples.html) +### django-appmail +[Django-Appmail](https://github.com/yunojuno/django-appmail) +([PyPI package information](https://pypi.org/project/django-appmail/)) +is a [Django](/django.html) app for handling transactional email templates. +While the project began development as a way to work with the Mandrill +transactional [API](/application-programming-interfaces.html), it is +not exclusive to that API. The project simply provides a way to store +and render email content. The library does not send or receive emails. + +Django-Appmail is open sourced under the +[MIT license](https://github.com/yunojuno/django-appmail/blob/master/LICENSE). + ### django-axes [django-axes](https://github.com/jazzband/django-axes/) ([project documentation](https://django-axes.readthedocs.io/en/latest/) and -[PyPI package information](https://pypi.org/project/django-axes/) +[PyPI package information](https://pypi.org/project/django-axes/)) is a code library for [Django](/django.html) projects to track failed login attempts against a web application. The goal of the project is to make it easier for you to stop people and scripts from hacking your Django-powered website. The code for django-axes is -[open source under the MIT liense](https://github.com/jazzband/django-axes/blob/master/LICENSE) +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) and maintained by the group of developers known as [Jazzband](https://jazzband.co/). @@ -321,6 +333,18 @@ The django-jsonfield project is open source under the [MIT license](https://github.com/dmkoch/django-jsonfield/blob/master/LICENSE). +### django-linear-migrations +[django-linear-migrations](https://github.com/adamchainz/django-linear-migrations) +([PyPI package information](https://pypi.org/project/django-linear-migrations/)) +is a [Django](/django.html) code library to mitigate conflicting database +migrations, which can cause non-deterministic behavior in different +environments. The +[introductory blog post by the package author](https://adamj.eu/tech/2020/12/10/introducing-django-linear-migrations/) +does a good job of explaining the problem and how this library prevents +the issue. This library is open sourced under the +[MIT license](https://github.com/adamchainz/django-linear-migrations/blob/master/LICENSE). + + ### django-loginas [django-loginas](https://github.com/skorokithakis/django-loginas) ([PyPI package information](https://pypi.org/project/django-loginas/)) @@ -331,6 +355,15 @@ django-loginas is open source under the [BSD 3-Clause "New" or "Revised" License](https://github.com/skorokithakis/django-loginas/blob/master/LICENSE). +### django-markdown-view +[django-markdown-view](https://github.com/rgs258/django-markdown-view) +([PyPI package information](https://pypi.org/project/django-markdown-view/)) +is a Django extension for serving [Markdown](/markdown.html) files as +[Django templates](/django-templates.html). The project is open +sourced under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/rgs258/django-markdown-view/blob/master/LICENSE). + + ### django-migration-linter [django-migration-linter](https://github.com/3YOURMIND/django-migration-linter) ([PyPI package information](https://pypi.org/project/django-migration-linter/)) @@ -461,6 +494,29 @@ The project is open sourced under the [Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). +### Django Request Token +[Django Request Token](https://github.com/yunojuno/django-request-token) +([PyPI package information](https://pypi.org/project/django-request-token/0.13/)) +encapsulates the logic for issuing expiring and one-time tokens +with a [Django](/django.html) web application to use with protected URLs. +Note that [PostgreSQL](/postgresql.html) as your backend +[database](/databases.html) is a dependency for using this project. + +The Django Request Token project is open sourced under the +[MIT license](https://github.com/yunojuno/django-request-token/blob/master/LICENSE). + + +### django-rq +[django-rq](https://github.com/rq/django-rq) +([PyPI package information](https://pypi.org/project/django-rq/)) +is an [RQ](/redis-queue-rq.html)-based [task queue](/task-queues.html) +that integrates with [Django](/django.html) as an app. This project +is useful when you need a lightweight task queue and do not want +to go through configuring [Celery](/celery.html) in your project. +django-rq is open sourced under the +[MIT license](https://github.com/rq/django-rq/blob/master/LICENSE.txt). + + ### django-simple-task [django-simple-task](https://github.com/ericls/django-simple-task) ([project documentation](https://django-simple-task.readthedocs.io/) @@ -536,6 +592,35 @@ and maintained by the collaborative developer community group [Jazzband](https://jazzband.co/). +### django-user-visit +[django-user-visit](https://github.com/yunojuno/django-user-visit) +([PyPI package information](https://pypi.org/project/django-user-visit/)) +is a [Django](/django.html) app and +[middleware](https://docs.djangoproject.com/en/stable/topics/http/middleware/) +for tracking daily user visits to your web application. The goal +is to record per user per day instead of for every request a user +sends to the application. The project is provided as open source +under the +[MIT license](https://github.com/yunojuno/django-user-visit/blob/master/LICENSE). + + +### django-version-checks +[django-version-checks](https://github.com/adamchainz/django-version-checks) +([PyPI package](https://pypi.org/project/django-version-checks/)) +is a code library to ensure external system dependencies match +desired versions. For example, a specific version of +[PostgreSQL](/postgresql.html) or [MySQL](/mysql.html) as your database +backend. This is different from using `pip` and a `requirements.txt` file, +because those are Python dependencies, rather than system-wide software. +The +[introductory blog post](https://adamj.eu/tech/2020/12/14/introducing-django-version-checks/) +for the project has some good reasons why these external dependencies +can cause problems if they vary from the expected versions. + +django-version-checks is provided as open source under the +[MIT license](https://github.com/adamchainz/django-version-checks/blob/master/LICENSE). + + ### django-webshell [django-webshell](https://github.com/onrik/django-webshell) is an extension for executing arbitrary code in the @@ -575,6 +660,16 @@ The code for django-wiki is provided as open source under the [GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). +### elasticsearch-django +[elasticsearch-django](https://github.com/yunojuno/elasticsearch-django) +([PyPI package information](https://pypi.org/project/elasticsearch-django/)) +is a [Django](/django.html) app for managing +[ElasticSearch](https://github.com/elastic/elasticsearch) indexes +populated by [Django ORM](/django-orm.html) models. The project is +available as open source under the +[MIT license](https://github.com/yunojuno/elasticsearch-django/blob/master/LICENSE). + + ### pytest-django [pytest-django](https://github.com/pytest-dev/pytest-django) ([project documentation](https://pytest-django.readthedocs.io/en/latest/) diff --git a/content/pages/examples/django/django-forms-baseform.markdown b/content/pages/examples/django/django-forms-baseform.markdown new file mode 100644 index 000000000..c7e06434c --- /dev/null +++ b/content/pages/examples/django/django-forms-baseform.markdown @@ -0,0 +1,125 @@ +title: django.forms BaseForm Example Code +category: page +slug: django-forms-baseform-examples +sortorder: 500011255 +toc: False +sidebartitle: django.forms BaseForm +meta: Python example code for the BaseForm class from the django.forms module of the Django project. + + +BaseForm is a class within the django.forms module of the Django project. + + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / templatetags / wiki_tags.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/templatetags/wiki_tags.py) + +```python +# wiki_tags.py +import re + +from django import template +from django.apps import apps +from django.conf import settings as django_settings +from django.contrib.contenttypes.models import ContentType +from django.db.models import Model +~~from django.forms import BaseForm +from django.template.defaultfilters import striptags +from django.utils.http import urlquote +from django.utils.safestring import mark_safe +from wiki import models +from wiki.conf import settings +from wiki.core.plugins import registry as plugin_registry + +register = template.Library() + + +_cache = {} + + +@register.simple_tag(takes_context=True) +def article_for_object(context, obj): + if not isinstance(obj, Model): + raise TypeError( + "A Wiki article can only be associated to a Django Model " + "instance, not %s" % type(obj) + ) + + content_type = ContentType.objects.get_for_model(obj) + + if True or obj not in _cache: + + +## ... source file abbreviated to get to BaseForm examples ... + + +@register.inclusion_tag("wiki/includes/render.html", takes_context=True) +def wiki_render(context, article, preview_content=None): + + if preview_content: + content = article.render(preview_content=preview_content) + elif article.current_revision: + content = article.get_cached_content(user=context.get("user")) + else: + content = None + + context.update( + { + "article": article, + "content": content, + "preview": preview_content is not None, + "plugins": plugin_registry.get_plugins(), + "STATIC_URL": django_settings.STATIC_URL, + "CACHE_TIMEOUT": settings.CACHE_TIMEOUT, + } + ) + return context + + +@register.inclusion_tag("wiki/includes/form.html", takes_context=True) +def wiki_form(context, form_obj): +~~ if not isinstance(form_obj, BaseForm): + raise TypeError( + "Error including form, it's not a form, it's a %s" % type(form_obj) + ) + context.update({"form": form_obj}) + return context + + +@register.inclusion_tag("wiki/includes/messages.html", takes_context=True) +def wiki_messages(context): + + messages = context.get("messages", []) + for message in messages: + message.css_class = settings.MESSAGE_TAG_CSS_CLASS[message.level] + context.update({"messages": messages}) + return context + + +@register.filter +def get_content_snippet(content, keyword, max_words=30): + + def clean_text(content): + + content = striptags(content) + words = content.split() + + +## ... source file continues with no further BaseForm examples... + +``` + diff --git a/content/pages/examples/django/django-forms-checkboxinput.markdown b/content/pages/examples/django/django-forms-checkboxinput.markdown new file mode 100644 index 000000000..9b80d9c35 --- /dev/null +++ b/content/pages/examples/django/django-forms-checkboxinput.markdown @@ -0,0 +1,115 @@ +title: django.forms CheckboxInput Example Code +category: page +slug: django-forms-checkboxinput-examples +sortorder: 500011258 +toc: False +sidebartitle: django.forms CheckboxInput +meta: Python example code for the CheckboxInput class from the django.forms module of the Django project. + + +CheckboxInput is a class within the django.forms module of the Django project. + + +## Example 1 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / templatetags / jet_tags.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/templatetags/jet_tags.py) + +```python +# jet_tags.py +from __future__ import unicode_literals +import json +import os +from django import template +try: + from django.core.urlresolvers import reverse +except ImportError: # Django 1.11 + from django.urls import reverse + +~~from django.forms import CheckboxInput, ModelChoiceField, Select, ModelMultipleChoiceField, SelectMultiple +from django.contrib.admin.widgets import RelatedFieldWidgetWrapper +from django.utils.formats import get_format +from django.utils.safestring import mark_safe +from django.utils.encoding import smart_text +from jet import settings, VERSION +from jet.models import Bookmark +from jet.utils import get_model_instance_label, get_model_queryset, get_possible_language_codes, \ + get_admin_site, get_menu_items + +try: + from urllib.parse import parse_qsl +except ImportError: + from urlparse import parse_qsl + + +register = template.Library() +assignment_tag = register.assignment_tag if hasattr(register, 'assignment_tag') else register.simple_tag + + +@assignment_tag +def jet_get_date_format(): + return get_format('DATE_INPUT_FORMATS')[0] + + +@assignment_tag +def jet_get_time_format(): + return get_format('TIME_INPUT_FORMATS')[0] + + +@assignment_tag +def jet_get_datetime_format(): + return get_format('DATETIME_INPUT_FORMATS')[0] + + +@assignment_tag(takes_context=True) +def jet_get_menu(context): + return get_menu_items(context) + + +@assignment_tag +def jet_get_bookmarks(user): + if user is None: + return None + return Bookmark.objects.filter(user=user.pk) + + +@register.filter +def jet_is_checkbox(field): +~~ return field.field.widget.__class__.__name__ == CheckboxInput().__class__.__name__ + + +@register.filter +def jet_select2_lookups(field): + if hasattr(field, 'field') and \ + (isinstance(field.field, ModelChoiceField) or isinstance(field.field, ModelMultipleChoiceField)): + qs = field.field.queryset + model = qs.model + + if getattr(model, 'autocomplete_search_fields', None) and getattr(field.field, 'autocomplete', True): + choices = [] + app_label = model._meta.app_label + model_name = model._meta.object_name + + attrs = { + 'class': 'ajax', + 'data-app-label': app_label, + 'data-model': model_name, + 'data-ajax--url': reverse('jet:model_lookup') + } + + initial_value = field.value() + + if hasattr(field, 'field') and isinstance(field.field, ModelMultipleChoiceField): + + +## ... source file continues with no further CheckboxInput examples... + +``` + diff --git a/content/pages/examples/django/django-forms-checkboxselectmultiple.markdown b/content/pages/examples/django/django-forms-checkboxselectmultiple.markdown new file mode 100644 index 000000000..e424a6977 --- /dev/null +++ b/content/pages/examples/django/django-forms-checkboxselectmultiple.markdown @@ -0,0 +1,61 @@ +title: django.forms CheckboxSelectMultiple Example Code +category: page +slug: django-forms-checkboxselectmultiple-examples +sortorder: 500011259 +toc: False +sidebartitle: django.forms CheckboxSelectMultiple +meta: Python example code for the CheckboxSelectMultiple class from the django.forms module of the Django project. + + +CheckboxSelectMultiple is a class within the django.forms module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / gears / widgets.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/gears/widgets.py) + +```python +# widgets.py +~~from django.forms import FileInput, CheckboxSelectMultiple, Select + + +class CustomFileInput(FileInput): + template_name = 'gears/widgets/file_input.html' + accept = '' + show_file_name = True + + +~~class CustomCheckboxSelectMultiple(CheckboxSelectMultiple): + template_name = 'gears/widgets/checkbox_multiple_select.html' + hide_label = False + hide_apply_btn = False + + class Media: + js = ('gears/js/checkbox_multiple_select.js',) + + def __init__(self, *args, **kwargs): + self.hide_label = kwargs.pop('hide_label', False) + self.hide_apply_btn = kwargs.pop('hide_apply_btn', False) + super().__init__(*args, **kwargs) + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + context['widget'].update({ + 'hide_label': self.hide_label, + 'hide_apply_btn': self.hide_apply_btn, + }) + return context + + +class DropdownSelectSubmit(Select): + template_name = 'gears/widgets/dropdown_select_submit.html' + empty_label = 'Not selected' + + +## ... source file continues with no further CheckboxSelectMultiple examples... + +``` + diff --git a/content/pages/examples/django/django-forms-datefield.markdown b/content/pages/examples/django/django-forms-datefield.markdown new file mode 100644 index 000000000..9d97fbfa3 --- /dev/null +++ b/content/pages/examples/django/django-forms-datefield.markdown @@ -0,0 +1,529 @@ +title: django.forms DateField Python Code Examples +category: page +slug: django-forms-datefield-examples +sortorder: 500013118 +toc: False +sidebartitle: django.forms DateField +meta: Python code examples to show how to use the DateField class within the forms module of the Django project. + + +The [DateField](https://github.com/django/django/blob/master/django/forms/fields.py) +([documentation](https://docs.djangoproject.com/en/stable/ref/forms/fields/#datefield)) +class in the `django.forms` module in the [Django](/django.html) +[web framework](/web-frameworks.html) provides a mechanism for safely handling +dates, but not times, as input from an HTTP POST request. The request is +typically generated by an [HTML](/hypertext-markup-language-html.html) form +created from a Django [web application](/web-development.html). + + +## Example 1 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / fields.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./fields.py) + +```python +from collections import namedtuple +from datetime import datetime, time + +~~from django import forms +from django.utils.dateparse import parse_datetime +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +from .conf import settings +from .constants import EMPTY_VALUES +from .utils import handle_timezone +from .widgets import ( + BaseCSVWidget, + CSVWidget, + DateRangeWidget, + LookupChoiceWidget, + RangeWidget +) + + +class RangeField(forms.MultiValueField): + widget = RangeWidget + + def __init__(self, fields=None, *args, **kwargs): + if fields is None: + fields = ( + forms.DecimalField(), + forms.DecimalField()) + super().__init__(fields, *args, **kwargs) + + def compress(self, data_list): + if data_list: + return slice(*data_list) + return None + + +class DateRangeField(RangeField): + widget = DateRangeWidget + + def __init__(self, *args, **kwargs): +~~ fields = ( +~~ forms.DateField(), +~~ forms.DateField()) +~~ super().__init__(fields, *args, **kwargs) + + def compress(self, data_list): + if data_list: + start_date, stop_date = data_list + if start_date: + start_date = handle_timezone( + datetime.combine(start_date, time.min), + False + ) + if stop_date: + stop_date = handle_timezone( + datetime.combine(stop_date, time.max), + False + ) + return slice(start_date, stop_date) + return None + + +## ... source file continues with no further DateField examples ... + +``` + + +## Example 2 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / fields.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./fields.py) + +```python +import django +~~from django import forms +import decimal + +from .widgets import (TextInput, HiddenInput, CheckboxInput, Select, + ClearableFileInput, SelectMultiple, DateInput, + DateTimeInput, TimeInput, URLInput, NumberInput, + EmailInput, NullBooleanSelect, SlugInput, IPAddressInput, + SplitDateTimeWidget, SplitHiddenDateTimeWidget, + MultipleHiddenInput) + +__all__ = ( + 'Field', 'CharField', 'IntegerField', 'DateField', 'TimeField', + 'DateTimeField', 'EmailField', 'FileField', 'ImageField', 'URLField', + 'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField', + 'FloatField', 'DecimalField', 'SlugField', 'RegexField', + 'GenericIPAddressField', 'TypedChoiceField', 'FilePathField', + 'TypedMultipleChoiceField', 'ComboField', 'MultiValueField', + 'SplitDateTimeField', +) +if django.VERSION < (1, 9): + __all__ += ('IPAddressField',) + + +class Field(forms.Field): + widget = TextInput + hidden_widget = HiddenInput + + +class CharField(Field, forms.CharField): + widget = TextInput + + def widget_attrs(self, widget): + attrs = super(CharField, self).widget_attrs(widget) + if attrs is None: + attrs = {} + if self.max_length is not None and isinstance(widget, (TextInput, HiddenInput)): + # The HTML attribute is maxlength, not max_length. + attrs.update({'maxlength': str(self.max_length)}) + return attrs + + +class BooleanField(Field, forms.BooleanField): + widget = CheckboxInput + + +class NullBooleanField(Field, forms.NullBooleanField): + widget = NullBooleanSelect + + +class ChoiceField(Field, forms.ChoiceField): + widget = Select + + +class TypedChoiceField(ChoiceField, forms.TypedChoiceField): + widget = Select + + +class FilePathField(ChoiceField, forms.FilePathField): + widget = Select + + +class FileField(Field, forms.FileField): + widget = ClearableFileInput + + +class ImageField(Field, forms.ImageField): + widget = ClearableFileInput + + +class MultipleChoiceField(Field, forms.MultipleChoiceField): + widget = SelectMultiple + hidden_widget = MultipleHiddenInput + + +class TypedMultipleChoiceField(MultipleChoiceField, + forms.TypedMultipleChoiceField): + pass + + +~~class DateField(Field, forms.DateField): +~~ widget = DateInput + + +## ... source file continues with no further DateField examples ... + +``` + + +## Example 3 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / filters.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./filters.py) + +```python +from django.contrib.admin import RelatedFieldListFilter +from django.utils.encoding import smart_text +from django.utils.html import format_html +try: + from django.core.urlresolvers import reverse +except ImportError: # Django 1.11 + from django.urls import reverse + +try: + from django.contrib.admin.utils import get_model_from_relation +except ImportError: # Django 1.6 + from django.contrib.admin.util import get_model_from_relation + +try: + from django.forms.utils import flatatt +except ImportError: # Django 1.6 + from django.forms.util import flatatt + + +class RelatedFieldAjaxListFilter(RelatedFieldListFilter): + template = 'jet/related_field_ajax_list_filter.html' + ajax_attrs = None + + def has_output(self): + return True + + def field_choices(self, field, request, model_admin): + model = field.remote_field.model if hasattr(field, 'remote_field') else field.related_field.model + app_label = model._meta.app_label + model_name = model._meta.object_name + + self.ajax_attrs = format_html('{0}', flatatt({ + 'data-app-label': app_label, + 'data-model': model_name, + 'data-ajax--url': reverse('jet:model_lookup'), + 'data-queryset--lookup': self.lookup_kwarg + })) + + if self.lookup_val is None: + return [] + + other_model = get_model_from_relation(field) + if hasattr(field, 'rel'): + rel_name = field.rel.get_related_field().name + else: + rel_name = other_model._meta.pk.name + + queryset = model._default_manager.filter(**{rel_name: self.lookup_val}).all() + return [(x._get_pk_val(), smart_text(x)) for x in queryset] + + +try: + from collections import OrderedDict +~~ from django import forms + from django.contrib.admin.widgets import AdminDateWidget + from rangefilter.filter import DateRangeFilter as OriginalDateRangeFilter + from django.utils.translation import ugettext as _ + + + class DateRangeFilter(OriginalDateRangeFilter): + def get_template(self): + return 'rangefilter/date_filter.html' + + def _get_form_fields(self): + # this is here, because in parent DateRangeFilter AdminDateWidget + # could be imported from django-suit +~~ return OrderedDict(( +~~ (self.lookup_kwarg_gte, forms.DateField( +~~ label='', +~~ widget=AdminDateWidget(attrs={'placeholder': _('From date')}), +~~ localize=True, +~~ required=False +~~ )), +~~ (self.lookup_kwarg_lte, forms.DateField( +~~ label='', +~~ widget=AdminDateWidget(attrs={'placeholder': _('To date')}), +~~ localize=True, +~~ required=False +~~ )), +~~ )) + + @staticmethod + def _get_media(): + css = [ + 'style.css', + ] + return forms.Media( + css={'all': ['range_filter/css/%s' % path for path in css]} + ) +except ImportError: + pass + +``` + + +## Example 4 from register +[register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is +open source under the +[GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). +This web application makes it easier for people to register as organ donors. +You can see the application live at +[https://register.organize.org/](https://register.organize.org/). + +[**register / registration / forms.py**](https://github.com/ORGAN-IZE/register/blob/master/registration/./forms.py) + +```python +from __future__ import unicode_literals + +import logging +import re +import collections +import datetime + +~~import django.forms +import django.forms.utils +import django.forms.widgets +import django.core.validators +import django.core.exceptions +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ +from django.utils.safestring import mark_safe + +import form_utils.forms +import requests +import dateutil.parser +import validate_email + +logger = logging.getLogger(__name__) + + +## ... source file abbreviated to get to the DateField example ... + +def register_form_generator(conf): + fieldsets = [] + fields = collections.OrderedDict() + for index, fieldset_def in enumerate(conf['fieldsets']): + fieldset_title = _(fieldset_def['title']) + fieldset_fields = fieldset_def['fields'] + + if not fieldset_fields: + continue + fieldset = (unicode(index), {'legend': fieldset_title, 'fields': []}, ) + + has_booleans = False + + for field_def in fieldset_def['fields']: + field_name = field_def['field_name'] + field_type = field_def.get('type') + label = _(field_def['human_name']) or '' + + is_required = field_def.get('required', False) + max_length = field_def.get('length') + initial = field_def.get('default') + if field_def.get('help_text'): + help_text = _(field_def.get('help_text')) + else: + help_text = '' + # process choices to add internationalization + choices = field_def.get('choices') + if choices: + choices = [(a, _(b)) for a, b in choices] + is_editable = field_def.get('editable', True) + min_value = field_def.get('min_value') + + d = { + 'label': label, + } + + if field_type == 'string': + d['required'] = is_required + d['initial'] = initial + if choices and is_editable: + d['help_text'] = help_text + d['choices'] = choices + d['widget'] = django.forms.RadioSelect + field_class = django.forms.ChoiceField + elif field_name == 'email': + d['max_length'] = max_length + d['help_text'] = help_text + field_class = django.forms.EmailField + elif field_name == 'license_id' \ + and 'license_id_formats' in conf: + d['max_length'] = max_length + license_id_formats = '{}{}{}'.format( + _('

Valid state License IDs should look like: '), + ', '.join(map(unicode, conf['license_id_formats'])), '

') + help_text = '{}{}{}'.format('

', unicode(help_text), '

') + license_id_formats = '{}{}'.format(license_id_formats, help_text) + d['help_text'] = mark_safe(license_id_formats) + field_class = django.forms.CharField + else: + d['max_length'] = max_length + d['help_text'] = help_text + field_class = django.forms.CharField + elif field_type == 'date': + d['required'] = is_required + d['initial'] = initial + d['help_text'] = help_text + if min_value: + d['validators'] = [validate_date_generator(min_value), ] +~~ field_class = django.forms.DateField + elif field_type == 'boolean': + has_booleans = True + d['initial'] = initial + # this must be false otherwise checkbox must be checked + if field_name == 'agree_to_tos': + d['help_text'] = mark_safe(help_text) + d['label'] = mark_safe(label) + else: + d['required'] = False + d['help_text'] = help_text + field_class = django.forms.BooleanField + else: + raise Exception('Unknown field type: {}'.format(field_type)) + + fields[field_name] = field_class(**d) + fieldset[1]['fields'].append(field_name) + + widget = fields[field_name].widget + if not is_editable: + if isinstance(widget, django.forms.Select): + widget.attrs['disabled'] = 'disabled' + else: + widget.attrs['readonly'] = 'readonly' + if field_type == 'date': + widget.attrs['placeholder'] = '__/__/____' + widget.attrs['class'] = 'date' + if field_name == 'phone_number': + widget.attrs['placeholder'] = '(___) ___-____' + widget.attrs['class'] = 'phonenumber' + if field_name == 'ssn': + widget.attrs['placeholder'] = '____' + widget.attrs['class'] = 'ssn' + + if has_booleans: + fieldset[1]['classes'] = ['checkboxes', ] + fieldsets.append(fieldset) + + cls_name = 'RegisterForm{}'.format( + RE_NON_ALPHA.sub('', conf['title'].title())).encode( + 'ascii', errors='ignore') + + cls = type( + cls_name, + (form_utils.forms.BetterBaseForm, django.forms.BaseForm, ), { + 'base_fieldsets': fieldsets, + 'base_fields': fields, + 'base_row_attrs': {}, + 'clean': register_form_clean, + 'clean_birthdate': register_form_clean_birthdate, + 'clean_phone_number': register_form_clean_phone_number, + 'clean_ssn': register_form_clean_ssn, + 'clean_license_id': register_form_clean_license_id, + 'api_errors': {}, + 'skip_api_error_validation': False, + 'validate_organ_tissue_selection': conf.get('validate_organ_tissue_selection', None), + }) + return cls + + +class RevokeForm(django.forms.Form): + email = django.forms.EmailField(label=_('Email')) + first_name = django.forms.CharField( + label=_('First Name'), max_length=150, min_length=1) + middle_name = django.forms.CharField( + label=_('Middle Name'), max_length=150, min_length=0, required=False) + last_name = django.forms.CharField( + label=_('Last Name'), max_length=150, min_length=1) + postal_code = django.forms.CharField( + label=_('Postal Code'), + max_length=5, min_length=5, validators=[validate_postal_code]) + gender = django.forms.ChoiceField( + label=_('Gender'), choices=CHOICES_GENDER, + widget=django.forms.RadioSelect) +~~ birthdate = django.forms.DateField( +~~ label=_('Birthdate'), +~~ widget=django.forms.DateInput( +~~ attrs={'placeholder': '__/__/____', 'class': 'date',})) + # agree_to_tos = django.forms.BooleanField( + # label=mark_safe(_('In order to revoke my organ and tissue donation status through Organize, I agree to ORGANIZE\'s ' + # 'Terms of Service and Privacy Policy.')), + # widget=django.forms.widgets.CheckboxInput( + # attrs={'required': 'required', })) + agree_to_tos = django.forms.BooleanField(label='', widget=django.forms.widgets.CheckboxInput(attrs={'required': 'required', })) + + def clean_email(self): + email = self.cleaned_data['email'] + if settings.DISABLE_EMAIL_VALIDATION: + logger.warning( + 'Email validation disabled: DISABLE_EMAIL_VALIDATION is set') + return email + # use mailgun email address validator to check this email + if not hasattr(settings, 'MAILGUN_PUBLIC_API_KEY'): + logger.warning( + 'Cannot validate email: MAILGUN_PUBLIC_API_KEY not set') + return email + r = requests.get( + 'https://api.mailgun.net/v2/address/validate', + data={'address': email, }, + auth=('api', settings.MAILGUN_PUBLIC_API_KEY)) + if r.status_code == 200: + if r.json()['is_valid']: + return email + logger.warning('Cannot validate email: {}'.format(r.text)) + raise django.forms.ValidationError(_('Enter a valid email.')) + +## ... source file continues with no further DateField examples ... + +``` + diff --git a/content/pages/examples/django/django-forms-dateinput.markdown b/content/pages/examples/django/django-forms-dateinput.markdown new file mode 100644 index 000000000..bedd29ab9 --- /dev/null +++ b/content/pages/examples/django/django-forms-dateinput.markdown @@ -0,0 +1,120 @@ +title: django.forms DateInput Example Code +category: page +slug: django-forms-dateinput-examples +sortorder: 500011262 +toc: False +sidebartitle: django.forms DateInput +meta: Python example code for the DateInput class from the django.forms module of the Django project. + + +DateInput is a class within the django.forms module of the Django project. + + +## Example 1 from register +[register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is +open source under the +[GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). +This web application makes it easier for people to register as organ donors. +You can see the application live at +[https://register.organize.org/](https://register.organize.org/). + +[**register / registration / forms.py**](https://github.com/ORGAN-IZE/register/blob/master/registration/./forms.py) + +```python +# forms.py +from __future__ import unicode_literals + +import logging +import re +import collections +import datetime + +~~import django.forms +~~import django.forms.utils +~~import django.forms.widgets +import django.core.validators +import django.core.exceptions +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ +from django.utils.safestring import mark_safe + +import form_utils.forms +import requests +import dateutil.parser +import validate_email + +logger = logging.getLogger(__name__) + + +REGISTRATION_CONFIGURATION_NAME = 'registration_configuration' + +RE_NON_DECIMAL = re.compile(r'[^\d]+') +RE_NON_ALPHA = re.compile('[\W]+') +RE_POSTAL_CODE = re.compile(r'^[0-9]{5}$') +validate_postal_code = django.core.validators.RegexValidator( + RE_POSTAL_CODE, _("Enter a valid postal code consisting 5 numbers."), 'invalid') + + +CHOICES_GENDER = ( + + +## ... source file abbreviated to get to DateInput examples ... + + + 'clean_ssn': register_form_clean_ssn, + 'clean_license_id': register_form_clean_license_id, + 'api_errors': {}, + 'skip_api_error_validation': False, + 'validate_organ_tissue_selection': conf.get('validate_organ_tissue_selection', None), + }) + return cls + + +class RevokeForm(django.forms.Form): + email = django.forms.EmailField(label=_('Email')) + first_name = django.forms.CharField( + label=_('First Name'), max_length=150, min_length=1) + middle_name = django.forms.CharField( + label=_('Middle Name'), max_length=150, min_length=0, required=False) + last_name = django.forms.CharField( + label=_('Last Name'), max_length=150, min_length=1) + postal_code = django.forms.CharField( + label=_('Postal Code'), + max_length=5, min_length=5, validators=[validate_postal_code]) + gender = django.forms.ChoiceField( + label=_('Gender'), choices=CHOICES_GENDER, + widget=django.forms.RadioSelect) + birthdate = django.forms.DateField( + label=_('Birthdate'), +~~ widget=django.forms.DateInput( + attrs={'placeholder': '__/__/____', 'class': 'date',})) + agree_to_tos = django.forms.BooleanField(label='', widget=django.forms.widgets.CheckboxInput(attrs={'required': 'required', })) + + def clean_email(self): + email = self.cleaned_data['email'] + if settings.DISABLE_EMAIL_VALIDATION: + logger.warning( + 'Email validation disabled: DISABLE_EMAIL_VALIDATION is set') + return email + if not hasattr(settings, 'MAILGUN_PUBLIC_API_KEY'): + logger.warning( + 'Cannot validate email: MAILGUN_PUBLIC_API_KEY not set') + return email + r = requests.get( + 'https://api.mailgun.net/v2/address/validate', + data={'address': email, }, + auth=('api', settings.MAILGUN_PUBLIC_API_KEY)) + if r.status_code == 200: + if r.json()['is_valid']: + return email + logger.warning('Cannot validate email: {}'.format(r.text)) + raise django.forms.ValidationError(_('Enter a valid email.')) + + + + +## ... source file continues with no further DateInput examples... + +``` + diff --git a/content/pages/examples/django/django-forms-datetimefield.markdown b/content/pages/examples/django/django-forms-datetimefield.markdown new file mode 100644 index 000000000..bf9a7f20a --- /dev/null +++ b/content/pages/examples/django/django-forms-datetimefield.markdown @@ -0,0 +1,498 @@ +title: django.forms DateTimeField Code Examples +category: page +slug: django-forms-datetimefield-examples +sortorder: 500013119 +toc: False +sidebartitle: django.forms DateTimeField +meta: Python code examples that show how to use DateTimeField from the forms module of the Django project. + + +The [DateTimeField](https://github.com/django/django/blob/master/django/forms/fields.py) +([documentation](https://docs.djangoproject.com/en/stable/ref/forms/fields/#datetimefield)) +class in the `django.forms` module in the [Django](/django.html) +[web framework](/web-frameworks.html) provides a mechanism for safely handling +dates and times as input from HTTP POST requests. The requests are +usually generated by an [HTML](/hypertext-markup-language-html.html) form +created from a Django [web application](/web-development.html). + + +## Example 1 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / fields.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./fields.py) + +```python +from collections import namedtuple +from datetime import datetime, time + +~~from django import forms +from django.utils.dateparse import parse_datetime +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +from .conf import settings +from .constants import EMPTY_VALUES +from .utils import handle_timezone +from .widgets import ( + BaseCSVWidget, + CSVWidget, + DateRangeWidget, + LookupChoiceWidget, + RangeWidget +) + + +class RangeField(forms.MultiValueField): + widget = RangeWidget + + def __init__(self, fields=None, *args, **kwargs): + if fields is None: + fields = ( + forms.DecimalField(), + forms.DecimalField()) + super().__init__(fields, *args, **kwargs) + + def compress(self, data_list): + if data_list: + return slice(*data_list) + return None + + +class DateRangeField(RangeField): + widget = DateRangeWidget + + def __init__(self, *args, **kwargs): + fields = ( + forms.DateField(), + forms.DateField()) + super().__init__(fields, *args, **kwargs) + + def compress(self, data_list): + if data_list: + start_date, stop_date = data_list + if start_date: + start_date = handle_timezone( + datetime.combine(start_date, time.min), + False + ) + if stop_date: + stop_date = handle_timezone( + datetime.combine(stop_date, time.max), + False + ) + return slice(start_date, stop_date) + return None + + +class DateTimeRangeField(RangeField): + widget = DateRangeWidget + + def __init__(self, *args, **kwargs): +~~ fields = ( +~~ forms.DateTimeField(), +~~ forms.DateTimeField()) +~~ super().__init__(fields, *args, **kwargs) + + +class IsoDateTimeRangeField(RangeField): + widget = DateRangeWidget + + def __init__(self, *args, **kwargs): + fields = ( + IsoDateTimeField(), + IsoDateTimeField()) + super().__init__(fields, *args, **kwargs) + + +class TimeRangeField(RangeField): + widget = DateRangeWidget + + def __init__(self, *args, **kwargs): + fields = ( + forms.TimeField(), + forms.TimeField()) + super().__init__(fields, *args, **kwargs) + + +class Lookup(namedtuple('Lookup', ('value', 'lookup_expr'))): + def __new__(cls, value, lookup_expr): + if value in EMPTY_VALUES or lookup_expr in EMPTY_VALUES: + raise ValueError( + "Empty values ([], (), {}, '', None) are not " + "valid Lookup arguments. Return None instead." + ) + + return super().__new__(cls, value, lookup_expr) + + +class LookupChoiceField(forms.MultiValueField): + default_error_messages = { + 'lookup_required': _('Select a lookup.'), + } + + def __init__(self, field, lookup_choices, *args, **kwargs): + empty_label = kwargs.pop('empty_label', settings.EMPTY_CHOICE_LABEL) + fields = (field, ChoiceField(choices=lookup_choices, empty_label=empty_label)) + widget = LookupChoiceWidget(widgets=[f.widget for f in fields]) + kwargs['widget'] = widget + kwargs['help_text'] = field.help_text + super().__init__(fields, *args, **kwargs) + + def compress(self, data_list): + if len(data_list) == 2: + value, lookup_expr = data_list + if value not in EMPTY_VALUES: + if lookup_expr not in EMPTY_VALUES: + return Lookup(value=value, lookup_expr=lookup_expr) + else: + raise forms.ValidationError( + self.error_messages['lookup_required'], + code='lookup_required') + return None + + +~~class IsoDateTimeField(forms.DateTimeField): +~~ """ +~~ Supports 'iso-8601' date format too which is out the scope of +~~ the ``datetime.strptime`` standard library + +~~ # ISO 8601: ``http://www.w3.org/TR/NOTE-datetime`` + +~~ Based on Gist example by David Medina https://gist.github.com/copitux/5773821 +~~ """ +~~ ISO_8601 = 'iso-8601' +~~ input_formats = [ISO_8601] + +~~ def strptime(self, value, format): +~~ value = force_str(value) + +~~ if format == self.ISO_8601: +~~ parsed = parse_datetime(value) +~~ if parsed is None: # Continue with other formats if doesn't match +~~ raise ValueError +~~ return handle_timezone(parsed) +~~ return super().strptime(value, format) + + +## ... source file continues with no further DateTimeField examples ... + +``` + + +## Example 2 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / fields.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./fields.py) + +```python +import django +~~from django import forms +import decimal + +from .widgets import (TextInput, HiddenInput, CheckboxInput, Select, + ClearableFileInput, SelectMultiple, DateInput, + DateTimeInput, TimeInput, URLInput, NumberInput, + EmailInput, NullBooleanSelect, SlugInput, IPAddressInput, + SplitDateTimeWidget, SplitHiddenDateTimeWidget, + MultipleHiddenInput) + +__all__ = ( + 'Field', 'CharField', 'IntegerField', 'DateField', 'TimeField', + 'DateTimeField', 'EmailField', 'FileField', 'ImageField', 'URLField', + 'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField', + 'FloatField', 'DecimalField', 'SlugField', 'RegexField', + 'GenericIPAddressField', 'TypedChoiceField', 'FilePathField', + 'TypedMultipleChoiceField', 'ComboField', 'MultiValueField', + 'SplitDateTimeField', +) +if django.VERSION < (1, 9): + __all__ += ('IPAddressField',) + + +class Field(forms.Field): + widget = TextInput + hidden_widget = HiddenInput + + +class CharField(Field, forms.CharField): + widget = TextInput + + def widget_attrs(self, widget): + attrs = super(CharField, self).widget_attrs(widget) + if attrs is None: + attrs = {} + if self.max_length is not None and isinstance(widget, (TextInput, HiddenInput)): + # The HTML attribute is maxlength, not max_length. + attrs.update({'maxlength': str(self.max_length)}) + return attrs + + +class BooleanField(Field, forms.BooleanField): + widget = CheckboxInput + + +class NullBooleanField(Field, forms.NullBooleanField): + widget = NullBooleanSelect + + +class ChoiceField(Field, forms.ChoiceField): + widget = Select + + +class TypedChoiceField(ChoiceField, forms.TypedChoiceField): + widget = Select + + +class FilePathField(ChoiceField, forms.FilePathField): + widget = Select + + +class FileField(Field, forms.FileField): + widget = ClearableFileInput + + +class ImageField(Field, forms.ImageField): + widget = ClearableFileInput + + +class MultipleChoiceField(Field, forms.MultipleChoiceField): + widget = SelectMultiple + hidden_widget = MultipleHiddenInput + + +class TypedMultipleChoiceField(MultipleChoiceField, + forms.TypedMultipleChoiceField): + pass + + +class DateField(Field, forms.DateField): + widget = DateInput + + +~~class DateTimeField(Field, forms.DateTimeField): +~~ widget = DateTimeInput + + +class TimeField(Field, forms.TimeField): + widget = TimeInput + + +class FloatField(Field, forms.FloatField): + widget = NumberInput + + def widget_attrs(self, widget): + attrs = super(FloatField, self).widget_attrs(widget) or {} + if self.min_value is not None: + attrs['min'] = self.min_value + if self.max_value is not None: + attrs['max'] = self.max_value + if 'step' not in widget.attrs: + attrs.setdefault('step', 'any') + return attrs + + +class IntegerField(Field, forms.IntegerField): + widget = NumberInput + + def __init__(self, *args, **kwargs): + kwargs.setdefault('widget', NumberInput if not kwargs.get('localize') else self.widget) + super(IntegerField, self).__init__(*args, **kwargs) + + def widget_attrs(self, widget): + attrs = super(IntegerField, self).widget_attrs(widget) or {} + if self.min_value is not None: + attrs['min'] = self.min_value + if self.max_value is not None: + attrs['max'] = self.max_value + return attrs + + +class DecimalField(Field, forms.DecimalField): + widget = NumberInput + + def __init__(self, *args, **kwargs): + kwargs.setdefault('widget', NumberInput if not kwargs.get('localize') else self.widget) + super(DecimalField, self).__init__(*args, **kwargs) + + def widget_attrs(self, widget): + attrs = super(DecimalField, self).widget_attrs(widget) or {} + if self.min_value is not None: + attrs['min'] = self.min_value + if self.max_value is not None: + attrs['max'] = self.max_value + if self.decimal_places is not None: + attrs['step'] = decimal.Decimal('0.1') ** self.decimal_places + return attrs + + +class EmailField(Field, forms.EmailField): + widget = EmailInput + + +class URLField(Field, forms.URLField): + widget = URLInput + + +class SlugField(Field, forms.SlugField): + widget = SlugInput + + +class RegexField(Field, forms.RegexField): + widget = TextInput + + def __init__(self, regex, js_regex=None, max_length=None, min_length=None, + error_message=None, *args, **kwargs): + self.js_regex = js_regex + super(RegexField, self).__init__(regex, max_length, min_length, + *args, **kwargs) + + def widget_attrs(self, widget): + attrs = super(RegexField, self).widget_attrs(widget) or {} + if self.js_regex is not None: + attrs['pattern'] = self.js_regex + return attrs + + +if django.VERSION < (1, 9): + class IPAddressField(Field, forms.IPAddressField): + widget = IPAddressInput + + +class GenericIPAddressField(Field, forms.GenericIPAddressField): + pass + + +class ComboField(Field, forms.ComboField): + pass + + +class MultiValueField(Field, forms.MultiValueField): + pass + + +class SplitDateTimeField(forms.SplitDateTimeField): + widget = SplitDateTimeWidget + hidden_widget = SplitHiddenDateTimeWidget + + def __init__(self, *args, **kwargs): + super(SplitDateTimeField, self).__init__(*args, **kwargs) + for widget in self.widget.widgets: + widget.is_required = self.required + +``` + + +## Example 3 from django-mongonaut +[django-mongonaut](https://github.com/jazzband/django-mongonaut) +([project documentation](https://django-mongonaut.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-mongonaut/)) +provides an introspective interface for working with +[MongoDB](/mongodb.html) via mongoengine. The project has its own new code +to map MongoDB to the [Django](/django.html) Admin interface. + +django-mongonaut's highlighted features include automatic introspection of +mongoengine documents, the ability to constrain who sees what and what +they can do and full control for adding, editing and deleting documents. + +The django-mongonaut project is open sourced under the +[MIT License](https://github.com/jazzband/django-mongonaut/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-mongonaut / mongonaut / forms / widgets.py**](https://github.com/jazzband/django-mongonaut/blob/master/mongonaut/forms/widgets.py) + +```python +# -*- coding: utf-8 -*- + +""" Widgets for mongonaut forms""" + +~~from django import forms + +from mongoengine.base import ObjectIdField +from mongoengine.fields import BooleanField +from mongoengine.fields import DateTimeField +from mongoengine.fields import EmbeddedDocumentField +from mongoengine.fields import ListField +from mongoengine.fields import ReferenceField +from mongoengine.fields import FloatField +from mongoengine.fields import EmailField +from mongoengine.fields import DecimalField +from mongoengine.fields import URLField +from mongoengine.fields import IntField +from mongoengine.fields import StringField +from mongoengine.fields import GeoPointField + + +def get_widget(model_field, disabled=False): + """Choose which widget to display for a field.""" + + attrs = get_attrs(model_field, disabled) + + if hasattr(model_field, "max_length") and not model_field.max_length: + return forms.Textarea(attrs=attrs) + + elif isinstance(model_field, DateTimeField): + return forms.DateTimeInput(attrs=attrs) + + elif isinstance(model_field, BooleanField): + return forms.CheckboxInput(attrs=attrs) + + elif isinstance(model_field, ReferenceField) or model_field.choices: + return forms.Select(attrs=attrs) + + elif (isinstance(model_field, ListField) or + isinstance(model_field, EmbeddedDocumentField) or + isinstance(model_field, GeoPointField)): + return None + + else: + return forms.TextInput(attrs=attrs) + + +def get_attrs(model_field, disabled=False): + """Set attributes on the display widget.""" + attrs = {} + attrs['class'] = 'span6 xlarge' + if disabled or isinstance(model_field, ObjectIdField): + attrs['class'] += ' disabled' + attrs['readonly'] = 'readonly' + return attrs + + +def get_form_field_class(model_field): + """Gets the default form field for a mongoenigne field.""" + + FIELD_MAPPING = { + IntField: forms.IntegerField, + StringField: forms.CharField, + FloatField: forms.FloatField, + BooleanField: forms.BooleanField, +~~ DateTimeField: forms.DateTimeField, + DecimalField: forms.DecimalField, + URLField: forms.URLField, + EmailField: forms.EmailField + } + + return FIELD_MAPPING.get(model_field.__class__, forms.CharField) + +``` + + diff --git a/content/pages/examples/django/django-forms-emailfield.markdown b/content/pages/examples/django/django-forms-emailfield.markdown index 2155cafce..3cdcafb49 100644 --- a/content/pages/examples/django/django-forms-emailfield.markdown +++ b/content/pages/examples/django/django-forms-emailfield.markdown @@ -1,7 +1,7 @@ title: django.forms EmailField Python Code Examples category: page slug: django-forms-emailfield-examples -sortorder: 500013120 +sortorder: 500013124 toc: False sidebartitle: django.forms EmailField meta: View Python code examples that show how to use the EmailField class within the forms module of the Django open source project. diff --git a/content/pages/examples/django/django-forms-field.markdown b/content/pages/examples/django/django-forms-field.markdown new file mode 100644 index 000000000..6d38d49e3 --- /dev/null +++ b/content/pages/examples/django/django-forms-field.markdown @@ -0,0 +1,66 @@ +title: django.forms Field Example Code +category: page +slug: django-forms-field-examples +sortorder: 500011264 +toc: False +sidebartitle: django.forms Field +meta: Python example code for the Field class from the django.forms module of the Django project. + + +Field is a class within the django.forms module of the Django project. + + +## Example 1 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / forms.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./forms.py) + +```python +# forms.py +from django.db import DatabaseError +~~from django.forms import ModelForm, Field, ValidationError, BooleanField, CharField +from django.forms.widgets import CheckboxInput, Select + +from explorer.app_settings import EXPLORER_DEFAULT_CONNECTION, EXPLORER_CONNECTIONS +from explorer.models import Query, MSG_FAILED_BLACKLIST + + +~~class SqlField(Field): + + def validate(self, value): + + query = Query(sql=value) + + passes_blacklist, failing_words = query.passes_blacklist() + + error = MSG_FAILED_BLACKLIST % ', '.join(failing_words) if not passes_blacklist else None + + if error: + raise ValidationError( + error, + code="InvalidSql" + ) + + +class QueryForm(ModelForm): + + sql = SqlField() + snapshot = BooleanField(widget=CheckboxInput, required=False) + connection = CharField(widget=Select, required=False) + + def __init__(self, *args, **kwargs): + super(QueryForm, self).__init__(*args, **kwargs) + + +## ... source file continues with no further Field examples... + +``` + diff --git a/content/pages/examples/django/django-forms-fileinput.markdown b/content/pages/examples/django/django-forms-fileinput.markdown new file mode 100644 index 000000000..be0a370d1 --- /dev/null +++ b/content/pages/examples/django/django-forms-fileinput.markdown @@ -0,0 +1,55 @@ +title: django.forms FileInput Example Code +category: page +slug: django-forms-fileinput-examples +sortorder: 500011265 +toc: False +sidebartitle: django.forms FileInput +meta: Python example code for the FileInput class from the django.forms module of the Django project. + + +FileInput is a class within the django.forms module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / gears / widgets.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/gears/widgets.py) + +```python +# widgets.py +~~from django.forms import FileInput, CheckboxSelectMultiple, Select + + +~~class CustomFileInput(FileInput): + template_name = 'gears/widgets/file_input.html' + accept = '' + show_file_name = True + + +class CustomCheckboxSelectMultiple(CheckboxSelectMultiple): + template_name = 'gears/widgets/checkbox_multiple_select.html' + hide_label = False + hide_apply_btn = False + + class Media: + js = ('gears/js/checkbox_multiple_select.js',) + + def __init__(self, *args, **kwargs): + self.hide_label = kwargs.pop('hide_label', False) + self.hide_apply_btn = kwargs.pop('hide_apply_btn', False) + super().__init__(*args, **kwargs) + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + context['widget'].update({ + 'hide_label': self.hide_label, + 'hide_apply_btn': self.hide_apply_btn, + }) + + +## ... source file continues with no further FileInput examples... + +``` + diff --git a/content/pages/examples/django/django-forms-filepathfield.markdown b/content/pages/examples/django/django-forms-filepathfield.markdown new file mode 100644 index 000000000..b56800554 --- /dev/null +++ b/content/pages/examples/django/django-forms-filepathfield.markdown @@ -0,0 +1,136 @@ +title: django.forms FilePathField Example Code +category: page +slug: django-forms-filepathfield-examples +sortorder: 500011266 +toc: False +sidebartitle: django.forms FilePathField +meta: Python example code for the FilePathField class from the django.forms module of the Django project. + + +FilePathField is a class within the django.forms module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / fields.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./fields.py) + +```python +# fields.py +import copy +import datetime +import decimal +import functools +import inspect +import re +import uuid +import warnings +from collections import OrderedDict +from collections.abc import Mapping + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import ( + EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator, + MinValueValidator, ProhibitNullCharactersValidator, RegexValidator, + URLValidator, ip_address_validators +) +~~from django.forms import FilePathField as DjangoFilePathField +from django.forms import ImageField as DjangoImageField +from django.utils import timezone +from django.utils.dateparse import ( + parse_date, parse_datetime, parse_duration, parse_time +) +from django.utils.duration import duration_string +from django.utils.encoding import is_protected_type, smart_str +from django.utils.formats import localize_input, sanitize_separators +from django.utils.ipv6 import clean_ipv6_address +from django.utils.timezone import utc +from django.utils.translation import gettext_lazy as _ +from pytz.exceptions import InvalidTimeError + +from rest_framework import ( + ISO_8601, RemovedInDRF313Warning, RemovedInDRF314Warning +) +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.settings import api_settings +from rest_framework.utils import html, humanize_datetime, json, representation +from rest_framework.utils.formatting import lazy_format +from rest_framework.validators import ProhibitSurrogateCharactersValidator + + +class empty: + + +## ... source file abbreviated to get to FilePathField examples ... + + + def get_value(self, dictionary): + if self.field_name not in dictionary: + if getattr(self.root, 'partial', False): + return empty + if html.is_html_input(dictionary): + return dictionary.getlist(self.field_name) + return dictionary.get(self.field_name, empty) + + def to_internal_value(self, data): + if isinstance(data, str) or not hasattr(data, '__iter__'): + self.fail('not_a_list', input_type=type(data).__name__) + if not self.allow_empty and len(data) == 0: + self.fail('empty') + + return { + super(MultipleChoiceField, self).to_internal_value(item) + for item in data + } + + def to_representation(self, value): + return { + self.choice_strings_to_values.get(str(item), item) for item in value + } + + +~~class FilePathField(ChoiceField): + default_error_messages = { + 'invalid_choice': _('"{input}" is not a valid path choice.') + } + + def __init__(self, path, match=None, recursive=False, allow_files=True, + allow_folders=False, required=None, **kwargs): + field = DjangoFilePathField( + path, match=match, recursive=recursive, allow_files=allow_files, + allow_folders=allow_folders, required=required + ) + kwargs['choices'] = field.choices + super().__init__(**kwargs) + + + +class FileField(Field): + default_error_messages = { + 'required': _('No file was submitted.'), + 'invalid': _('The submitted data was not a file. Check the encoding type on the form.'), + 'no_name': _('No filename could be determined.'), + 'empty': _('The submitted file is empty.'), + 'max_length': _('Ensure this filename has at most {max_length} characters (it has {length}).'), + } + + + +## ... source file continues with no further FilePathField examples... + +``` + diff --git a/content/pages/examples/django/django-forms-form.markdown b/content/pages/examples/django/django-forms-form.markdown new file mode 100644 index 000000000..b7b244c07 --- /dev/null +++ b/content/pages/examples/django/django-forms-form.markdown @@ -0,0 +1,313 @@ +title: django.forms Form Example Code +category: page +slug: django-forms-form-examples +sortorder: 500011267 +toc: False +sidebartitle: django.forms Form +meta: Python example code for the Form class from the django.forms module of the Django project. + + +Form is a class within the django.forms module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / chair / forms.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/chair/forms.py) + +```python +# forms.py +from functools import reduce + +from django import forms +from django.contrib.auth import get_user_model +from django.db import models +from django.db.models import Q, F, Count, Max, Subquery, OuterRef, Value +from django.db.models.functions import Concat +~~from django.forms import MultipleChoiceField, ChoiceField, Form +from django.urls import reverse +from django.utils.translation import ugettext_lazy as _ + +from django_countries import countries + +from conferences.models import Conference, ArtifactDescriptor +from gears.widgets import CustomCheckboxSelectMultiple, CustomFileInput +from review.models import Reviewer, Review, ReviewStats +from review.utilities import get_average_score +from submissions.models import Submission, Attachment +from users.models import Profile + +User = get_user_model() + + +def clean_data_to_int(iterable, empty=None): + return [int(x) if x != '' else None for x in iterable] + + +def q_or(disjuncts, default=True): + if disjuncts: + return reduce(lambda acc, d: acc | d, disjuncts) + return Q(pk__isnull=(not default)) # otherwise, check whether PK is null + + + +## ... source file abbreviated to get to Form examples ... + + + available_reviewers = Reviewer.objects.exclude( + Q(pk__in=assigned_reviewers) | Q(user__in=authors_users) + ) + profiles = { + rev: rev.user.profile for rev in available_reviewers + } + reviewers = list(available_reviewers) + reviewers.sort(key=lambda r: r.reviews.count()) + self.fields['reviewer'].choices = ( + (rev.pk, + f'{profiles[rev].get_full_name()} ({rev.reviews.count()}) - ' + f'{profiles[rev].affiliation}, ' + f'{profiles[rev].get_country_display()}') + for rev in reviewers + ) + + def save(self): + reviewer = Reviewer.objects.get(pk=self.cleaned_data['reviewer']) + review = Review.objects.create( + reviewer=reviewer, stage=self.review_stage) + return review + + + + +~~class ExportSubmissionsForm(Form): + ORDER_COLUMN = '#' + ID_COLUMN = 'ID' + AUTHORS_COLUMN = 'AUTHORS' + TITLE_COLUMN = 'TITLE' + COUNTRY_COLUMN = 'COUNTRY' + STYPE_COLUMN = 'TYPE' + REVIEW_PAPER_COLUMN = 'REVIEW_MANUSCRIPT' + REVIEW_SCORE_COLUMN = 'REVIEW_SCORE' + STATUS_COLUMN = 'STATUS' + TOPICS_COLUMN = 'TOPICS' + + COLUMNS = ( + (ORDER_COLUMN, ORDER_COLUMN), + (ID_COLUMN, ID_COLUMN), + (TITLE_COLUMN, TITLE_COLUMN), + (AUTHORS_COLUMN, AUTHORS_COLUMN), + (COUNTRY_COLUMN, COUNTRY_COLUMN), + (STYPE_COLUMN, STYPE_COLUMN), + (REVIEW_PAPER_COLUMN, REVIEW_PAPER_COLUMN), + (REVIEW_SCORE_COLUMN, REVIEW_SCORE_COLUMN), + (STATUS_COLUMN, STATUS_COLUMN), + (TOPICS_COLUMN, TOPICS_COLUMN), + ) + + + +## ... source file continues with no further Form examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / wizards / views.py**](https://github.com/divio/django-cms/blob/develop/cms/wizards/views.py) + +```python +# views.py + +import os + +from django.conf import settings +from django.core.exceptions import PermissionDenied +from django.core.files.storage import FileSystemStorage +~~from django.forms import Form +from django.template.response import SimpleTemplateResponse +from django.urls import NoReverseMatch + +from formtools.wizard.views import SessionWizardView + +from cms.models import Page +from cms.utils import get_current_site +from cms.utils.i18n import get_site_language_from_request + +from .wizard_pool import wizard_pool +from .forms import ( + WizardStep1Form, + WizardStep2BaseForm, + step2_form_factory, +) + + +class WizardCreateView(SessionWizardView): + template_name = 'cms/wizards/start.html' + file_storage = FileSystemStorage( + location=os.path.join(settings.MEDIA_ROOT, 'wizard_tmp_files')) + + form_list = [ + ('0', WizardStep1Form), + + +## ... source file continues with no further Form examples... + +``` + + +## Example 3 from django-mongonaut +[django-mongonaut](https://github.com/jazzband/django-mongonaut) +([project documentation](https://django-mongonaut.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-mongonaut/)) +provides an introspective interface for working with +[MongoDB](/mongodb.html) via mongoengine. The project has its own new code +to map MongoDB to the [Django](/django.html) Admin interface. + +django-mongonaut's highlighted features include automatic introspection of +mongoengine documents, the ability to constrain who sees what and what +they can do and full control for adding, editing and deleting documents. + +The django-mongonaut project is open sourced under the +[MIT License](https://github.com/jazzband/django-mongonaut/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-mongonaut / mongonaut / views.py**](https://github.com/jazzband/django-mongonaut/blob/master/mongonaut/./views.py) + +```python +# views.py +import math + +from django.contrib import messages +from django.urls import reverse +~~from django.forms import Form +from django.http import HttpResponseForbidden +from django.http import Http404 +from django.utils.functional import cached_property +from django.views.generic.edit import DeletionMixin +from django.views.generic import ListView +from django.views.generic import TemplateView +from django.views.generic.edit import FormView +from mongoengine.fields import EmbeddedDocumentField, ListField + +from mongonaut.forms import MongoModelForm +from mongonaut.mixins import MongonautFormViewMixin +from mongonaut.mixins import MongonautViewMixin +from mongonaut.utils import is_valid_object_id + + +class IndexView(MongonautViewMixin, ListView): + + template_name = "mongonaut/index.html" + queryset = [] + permission = 'has_view_permission' + + def get_queryset(self): + return self.get_mongoadmins() + + + +## ... source file abbreviated to get to Form examples ... + + + self.ident = self.kwargs.get('id') + self.document = self.document_type.objects.get(pk=self.ident) + + context['document'] = self.document + context['app_label'] = self.app_label + context['document_name'] = self.document_name + context['form_action'] = reverse('document_detail_edit_form', args=[self.kwargs.get('app_label'), + self.kwargs.get('document_name'), + self.kwargs.get('id')]) + + return context + + def get_form(self): #get_form(self, Form) leads to "get_form() missing 1 required positional argument: 'Form'" error." + self.set_mongoadmin() + context = self.set_permissions_in_context({}) + + if not context['has_edit_permission']: + return HttpResponseForbidden("You do not have permissions to edit this content.") + + self.document_type = getattr(self.models, self.document_name) + self.ident = self.kwargs.get('id') + try: + self.document = self.document_type.objects.get(pk=self.ident) + except self.document_type.DoesNotExist: + raise Http404 +~~ self.form = Form() + + if self.request.method == 'POST': + self.form = self.process_post_form('Your changes have been saved.') + else: + self.form = MongoModelForm(model=self.document_type, instance=self.document).get_form() + return self.form + + +class DocumentAddFormView(MongonautViewMixin, FormView, MongonautFormViewMixin): + + template_name = "mongonaut/document_add_form.html" + form_class = Form + success_url = '/' + permission = 'has_add_permission' + + def get_success_url(self): + self.set_mongonaut_base() + return reverse('document_detail', kwargs={'app_label': self.app_label, 'document_name': self.document_name, 'id': str(self.new_document.id)}) + + def get_context_data(self, **kwargs): + context = super(DocumentAddFormView, self).get_context_data(**kwargs) + self.set_mongoadmin() + context = self.set_permissions_in_context(context) + self.document_type = getattr(self.models, self.document_name) + + context['app_label'] = self.app_label + context['document_name'] = self.document_name + context['form_action'] = reverse('document_detail_add_form', args=[self.kwargs.get('app_label'), + self.kwargs.get('document_name')]) + + return context + + def get_form(self): + self.set_mongonaut_base() + self.document_type = getattr(self.models, self.document_name) +~~ self.form = Form() + + if self.request.method == 'POST': + self.form = self.process_post_form('Your new document has been added and saved.') + else: + self.form = MongoModelForm(model=self.document_type).get_form() + return self.form + + +class DocumentDeleteView(DeletionMixin, MongonautViewMixin, TemplateView): + + success_url = "/" + template_name = "mongonaut/document_delete.html" + + def get_success_url(self): + self.set_mongonaut_base() + messages.add_message(self.request, messages.INFO, 'Your document has been deleted.') + return reverse('document_list', kwargs={'app_label': self.app_label, 'document_name': self.document_name}) + + def get_object(self): + self.set_mongoadmin() + self.document_type = getattr(self.models, self.document_name) + self.ident = self.kwargs.get('id') + self.document = self.document_type.objects.get(pk=self.ident) + return self.document + + +## ... source file continues with no further Form examples... + +``` + diff --git a/content/pages/examples/django/django-forms-hiddeninput.markdown b/content/pages/examples/django/django-forms-hiddeninput.markdown new file mode 100644 index 000000000..a1a870cd7 --- /dev/null +++ b/content/pages/examples/django/django-forms-hiddeninput.markdown @@ -0,0 +1,213 @@ +title: django.forms HiddenInput Example Code +category: page +slug: django-forms-hiddeninput-examples +sortorder: 500011268 +toc: False +sidebartitle: django.forms HiddenInput +meta: Python example code for the HiddenInput class from the django.forms module of the Django project. + + +HiddenInput is a class within the django.forms module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / review / forms.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/review/forms.py) + +```python +# forms.py +from django import forms +~~from django.forms import Form, HiddenInput, CharField, ChoiceField, ModelForm + +from conferences.models import ProceedingType, ProceedingVolume +from review.models import Review, check_review_details, ReviewDecision + + +class EditReviewForm(forms.ModelForm): + class Meta: + model = Review + fields = [ + 'technical_merit', 'relevance', 'originality', 'clarity', + 'details', 'submitted' + ] + + submitted = forms.BooleanField(required=False) + technical_merit = forms.ChoiceField(choices=Review.SCORE_CHOICES, required=False) + relevance = forms.ChoiceField(choices=Review.SCORE_CHOICES, required=False) + originality = forms.ChoiceField(choices=Review.SCORE_CHOICES, required=False) + details = forms.CharField(widget=forms.Textarea(attrs={'rows': '5'}), required=False) + + def clean(self): + cleaned_data = super().clean() + if cleaned_data['submitted']: + is_incomplete = False + for score_field in self.instance.score_fields().keys(): + if not cleaned_data[score_field]: + self.add_error(score_field, 'Must select a score') + is_incomplete = True + stype = self.instance.paper.stype + if not check_review_details(cleaned_data['details'], stype): + self.add_error( + 'details', + f'Review details must have at least ' + f'{stype.min_num_words_in_review} words' + ) + is_incomplete = True + if is_incomplete: + self.cleaned_data['submitted'] = False + raise forms.ValidationError('Review is incomplete') + return cleaned_data + + +class UpdateReviewDecisionForm(ModelForm): + class Meta: + model = ReviewDecision + fields = ['decision_type'] + + +class UpdateVolumeForm(Form): +~~ volume = CharField(widget=HiddenInput(), required=False) + + def __init__(self, *args, instance=None, **kwargs): + if not instance: + raise ValueError('Decision instance is required') + self.instance = instance + kwargs.update({ + 'initial': { + 'volume': str(instance.volume.pk) if instance.volume else '', + } + }) + super().__init__(*args, **kwargs) + self.volume = None + + def clean_volume(self): + try: + pk = int(self.cleaned_data['volume']) + volumes = ProceedingVolume.objects.filter(pk=pk) + self.volume = volumes.first() if volumes.count() else None + except ValueError: + self.volume = None + return self.cleaned_data['volume'] + + def save(self, commit=True): + self.instance.volume = self.volume + + +## ... source file continues with no further HiddenInput examples... + +``` + + +## Example 2 from django-flexible-subscriptions +[django-flexible-subscriptions](https://github.com/studybuffalo/django-flexible-subscriptions) +([project documentation](https://django-flexible-subscriptions.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-flexible-subscriptions/)) +provides boilerplate code for adding subscription and recurrent billing +to [Django](/django.html) web applications. Various payment providers +can be added on the back end to run the transactions. + +The django-flexible-subscriptions project is open sourced under the +[GNU General Public License v3.0](https://github.com/studybuffalo/django-flexible-subscriptions/blob/master/LICENSE). + +[**django-flexible-subscriptions / subscriptions / views.py**](https://github.com/studybuffalo/django-flexible-subscriptions/blob/master/subscriptions/./views.py) + +```python +# views.py +from copy import copy + +from django.contrib import messages +from django.contrib.auth import get_user_model +from django.contrib.auth.mixins import ( + LoginRequiredMixin, PermissionRequiredMixin +) +from django.contrib.messages.views import SuccessMessageMixin +~~from django.forms import HiddenInput +from django.forms.models import inlineformset_factory +from django.http import HttpResponseRedirect +from django.http.response import HttpResponseNotAllowed, HttpResponseNotFound +from django.shortcuts import get_object_or_404 +from django.template.response import TemplateResponse +from django.urls import reverse_lazy +from django.utils import timezone + +from subscriptions import models, forms, abstract + + +class DashboardView(PermissionRequiredMixin, abstract.TemplateView): + permission_required = 'subscriptions.subscriptions' + raise_exception = True + template_name = 'subscriptions/dashboard.html' + + +class TagListView(PermissionRequiredMixin, abstract.ListView): + model = models.PlanTag + permission_required = 'subscriptions.subscriptions' + raise_exception = True + context_object_name = 'tags' + template_name = 'subscriptions/tag_list.html' + + + +## ... source file abbreviated to get to HiddenInput examples ... + + + payment_transaction = self.process_payment( + payment_form=payment_form, + plan_cost_form=plan_cost_form, + ) + + if payment_transaction: + subscription = self.setup_subscription( + request.user, plan_cost_form.cleaned_data['plan_cost'] + ) + + transaction = self.record_transaction( + subscription, + self.retrieve_transaction_date(payment_transaction) + ) + + return HttpResponseRedirect( + self.get_success_url(transaction_id=transaction.id) + ) + + messages.error(request, 'Error processing payment') + + return self.render_confirmation(request, **kwargs) + + def hide_form(self, form): + for _, field in form.fields.items(): +~~ field.widget = HiddenInput() + + return form + + def process_payment(self, *args, **kwargs): # pylint: disable=unused-argument + return True + + def setup_subscription(self, request_user, plan_cost): + current_date = timezone.now() + + subscription = models.UserSubscription.objects.create( + user=request_user, + subscription=plan_cost, + date_billing_start=current_date, + date_billing_end=None, + date_billing_last=current_date, + date_billing_next=plan_cost.next_billing_datetime(current_date), + active=True, + cancelled=False, + ) + + try: + group = self.subscription_plan.group + group.user_set.add(request_user) + except AttributeError: + + +## ... source file continues with no further HiddenInput examples... + +``` + diff --git a/content/pages/examples/django/django-forms-imagefield.markdown b/content/pages/examples/django/django-forms-imagefield.markdown new file mode 100644 index 000000000..fe8f3b7aa --- /dev/null +++ b/content/pages/examples/django/django-forms-imagefield.markdown @@ -0,0 +1,137 @@ +title: django.forms ImageField Example Code +category: page +slug: django-forms-imagefield-examples +sortorder: 500011269 +toc: False +sidebartitle: django.forms ImageField +meta: Python example code for the ImageField class from the django.forms module of the Django project. + + +ImageField is a class within the django.forms module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / fields.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./fields.py) + +```python +# fields.py +import copy +import datetime +import decimal +import functools +import inspect +import re +import uuid +import warnings +from collections import OrderedDict +from collections.abc import Mapping + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import ( + EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator, + MinValueValidator, ProhibitNullCharactersValidator, RegexValidator, + URLValidator, ip_address_validators +) +from django.forms import FilePathField as DjangoFilePathField +~~from django.forms import ImageField as DjangoImageField +from django.utils import timezone +from django.utils.dateparse import ( + parse_date, parse_datetime, parse_duration, parse_time +) +from django.utils.duration import duration_string +from django.utils.encoding import is_protected_type, smart_str +from django.utils.formats import localize_input, sanitize_separators +from django.utils.ipv6 import clean_ipv6_address +from django.utils.timezone import utc +from django.utils.translation import gettext_lazy as _ +from pytz.exceptions import InvalidTimeError + +from rest_framework import ( + ISO_8601, RemovedInDRF313Warning, RemovedInDRF314Warning +) +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.settings import api_settings +from rest_framework.utils import html, humanize_datetime, json, representation +from rest_framework.utils.formatting import lazy_format +from rest_framework.validators import ProhibitSurrogateCharactersValidator + + +class empty: + pass + + +## ... source file abbreviated to get to ImageField examples ... + + + if not self.allow_empty_file and not file_size: + self.fail('empty') + if self.max_length and len(file_name) > self.max_length: + self.fail('max_length', max_length=self.max_length, length=len(file_name)) + + return data + + def to_representation(self, value): + if not value: + return None + + use_url = getattr(self, 'use_url', api_settings.UPLOADED_FILES_USE_URL) + if use_url: + try: + url = value.url + except AttributeError: + return None + request = self.context.get('request', None) + if request is not None: + return request.build_absolute_uri(url) + return url + + return value.name + + +~~class ImageField(FileField): + default_error_messages = { + 'invalid_image': _( + 'Upload a valid image. The file you uploaded was either not an image or a corrupted image.' + ), + } + + def __init__(self, *args, **kwargs): + self._DjangoImageField = kwargs.pop('_DjangoImageField', DjangoImageField) + super().__init__(*args, **kwargs) + + def to_internal_value(self, data): + file_object = super().to_internal_value(data) + django_field = self._DjangoImageField() + django_field.error_messages = self.error_messages + return django_field.clean(file_object) + + + +class _UnvalidatedField(Field): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.allow_blank = True + self.allow_null = True + + + +## ... source file continues with no further ImageField examples... + +``` + diff --git a/content/pages/examples/django/django-forms-integerfield.markdown b/content/pages/examples/django/django-forms-integerfield.markdown index e5cd5198e..c754b66ce 100644 --- a/content/pages/examples/django/django-forms-integerfield.markdown +++ b/content/pages/examples/django/django-forms-integerfield.markdown @@ -1,7 +1,7 @@ title: django.forms IntegerField Python Code Examples category: page slug: django-forms-integerfield-examples -sortorder: 500013120 +sortorder: 500013125 toc: False sidebartitle: django.forms IntegerField meta: View Python code examples that show how to use the IntegerField class within the forms module of the Django open source project. diff --git a/content/pages/examples/django/django-forms-media.markdown b/content/pages/examples/django/django-forms-media.markdown new file mode 100644 index 000000000..22f4fab39 --- /dev/null +++ b/content/pages/examples/django/django-forms-media.markdown @@ -0,0 +1,109 @@ +title: django.forms Media Example Code +category: page +slug: django-forms-media-examples +sortorder: 500011270 +toc: False +sidebartitle: django.forms Media +meta: Python example code for the Media class from the django.forms module of the Django project. + + +Media is a class within the django.forms module of the Django project. + + +## Example 1 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / admin / menu.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/admin/menu.py) + +```python +# menu.py +~~from django.forms import Media, MediaDefiningClass +from django.forms.utils import flatatt +from django.template.loader import render_to_string +from django.utils.safestring import mark_safe +from django.utils.text import slugify + +from wagtail.core import hooks + + +class MenuItem(metaclass=MediaDefiningClass): + template = 'wagtailadmin/shared/menu_item.html' + + def __init__(self, label, url, name=None, classnames='', icon_name='', attrs=None, order=1000): + self.label = label + self.url = url + self.classnames = classnames + self.icon_name = icon_name + self.name = (name or slugify(str(label))) + self.order = order + + if attrs: + self.attr_string = flatatt(attrs) + else: + self.attr_string = "" + + + +## ... source file abbreviated to get to Media examples ... + + + def render_html(self, request): + context = self.get_context(request) + return render_to_string(self.template, context, request=request) + + +class Menu: + def __init__(self, register_hook_name, construct_hook_name=None): + self.register_hook_name = register_hook_name + self.construct_hook_name = construct_hook_name + self._registered_menu_items = None + + @property + def registered_menu_items(self): + if self._registered_menu_items is None: + self._registered_menu_items = [fn() for fn in hooks.get_hooks(self.register_hook_name)] + return self._registered_menu_items + + def menu_items_for_request(self, request): + return [item for item in self.registered_menu_items if item.is_shown(request)] + + def active_menu_items(self, request): + return [item for item in self.menu_items_for_request(request) if item.is_active(request)] + + @property + def media(self): +~~ media = Media() + for item in self.registered_menu_items: + media += item.media + return media + + def render_html(self, request): + menu_items = self.menu_items_for_request(request) + + if self.construct_hook_name: + for fn in hooks.get_hooks(self.construct_hook_name): + fn(request, menu_items) + + rendered_menu_items = [] + for item in sorted(menu_items, key=lambda i: i.order): + rendered_menu_items.append(item.render_html(request)) + return mark_safe(''.join(rendered_menu_items)) + + +class SubmenuMenuItem(MenuItem): + template = 'wagtailadmin/shared/menu_submenu_item.html' + + def __init__(self, label, menu, **kwargs): + self.menu = menu + super().__init__(label, '#', **kwargs) + + + +## ... source file continues with no further Media examples... + +``` + diff --git a/content/pages/examples/django/django-forms-mediadefiningclass.markdown b/content/pages/examples/django/django-forms-mediadefiningclass.markdown new file mode 100644 index 000000000..f27021174 --- /dev/null +++ b/content/pages/examples/django/django-forms-mediadefiningclass.markdown @@ -0,0 +1,107 @@ +title: django.forms MediaDefiningClass Example Code +category: page +slug: django-forms-mediadefiningclass-examples +sortorder: 500011271 +toc: False +sidebartitle: django.forms MediaDefiningClass +meta: Python example code for the MediaDefiningClass class from the django.forms module of the Django project. + + +MediaDefiningClass is a class within the django.forms module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / toolbar_base.py**](https://github.com/divio/django-cms/blob/develop/cms/./toolbar_base.py) + +```python +# toolbar_base.py +~~from django.forms import MediaDefiningClass + +from six import with_metaclass + +from cms.exceptions import LanguageError +from cms.utils import get_current_site, get_language_from_request +from cms.utils.i18n import get_language_object + + +~~class CMSToolbar(with_metaclass(MediaDefiningClass)): + supported_apps = None + + def __init__(self, request, toolbar, is_current_app, app_path): + self.request = request + self.toolbar = toolbar + self.is_current_app = is_current_app + self.app_path = app_path + self.current_site = get_current_site() + try: + self.current_lang = get_language_object(get_language_from_request(self.request), self.current_site.pk)['code'] + except LanguageError: + self.current_lang = None + + def populate(self): + pass + + def post_template_populate(self): + pass + + @classmethod + def check_current_app(cls, key, app_name): + if cls.supported_apps is None: + local_apps = ".".join(key.split(".")[:-2]), + else: + + +## ... source file continues with no further MediaDefiningClass examples... + +``` + + +## Example 2 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / admin / menu.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/admin/menu.py) + +```python +# menu.py +~~from django.forms import Media, MediaDefiningClass +from django.forms.utils import flatatt +from django.template.loader import render_to_string +from django.utils.safestring import mark_safe +from django.utils.text import slugify + +from wagtail.core import hooks + + +class MenuItem(metaclass=MediaDefiningClass): + template = 'wagtailadmin/shared/menu_item.html' + + def __init__(self, label, url, name=None, classnames='', icon_name='', attrs=None, order=1000): + self.label = label + self.url = url + self.classnames = classnames + self.icon_name = icon_name + self.name = (name or slugify(str(label))) + self.order = order + + if attrs: + self.attr_string = flatatt(attrs) + else: + self.attr_string = "" + + + +## ... source file continues with no further MediaDefiningClass examples... + +``` + diff --git a/content/pages/examples/django/django-forms-modelchoicefield.markdown b/content/pages/examples/django/django-forms-modelchoicefield.markdown new file mode 100644 index 000000000..a9900a6a7 --- /dev/null +++ b/content/pages/examples/django/django-forms-modelchoicefield.markdown @@ -0,0 +1,121 @@ +title: django.forms ModelChoiceField Example Code +category: page +slug: django-forms-modelchoicefield-examples +sortorder: 500011272 +toc: False +sidebartitle: django.forms ModelChoiceField +meta: Python example code for the ModelChoiceField class from the django.forms module of the Django project. + + +ModelChoiceField is a class within the django.forms module of the Django project. + + +## Example 1 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / templatetags / jet_tags.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/templatetags/jet_tags.py) + +```python +# jet_tags.py +from __future__ import unicode_literals +import json +import os +from django import template +try: + from django.core.urlresolvers import reverse +except ImportError: # Django 1.11 + from django.urls import reverse + +~~from django.forms import CheckboxInput, ModelChoiceField, Select, ModelMultipleChoiceField, SelectMultiple +from django.contrib.admin.widgets import RelatedFieldWidgetWrapper +from django.utils.formats import get_format +from django.utils.safestring import mark_safe +from django.utils.encoding import smart_text +from jet import settings, VERSION +from jet.models import Bookmark +from jet.utils import get_model_instance_label, get_model_queryset, get_possible_language_codes, \ + get_admin_site, get_menu_items + +try: + from urllib.parse import parse_qsl +except ImportError: + from urlparse import parse_qsl + + +register = template.Library() +assignment_tag = register.assignment_tag if hasattr(register, 'assignment_tag') else register.simple_tag + + +@assignment_tag +def jet_get_date_format(): + return get_format('DATE_INPUT_FORMATS')[0] + + + + +## ... source file abbreviated to get to ModelChoiceField examples ... + + + app_label = model._meta.app_label + model_name = model._meta.object_name + + attrs = { + 'class': 'ajax', + 'data-app-label': app_label, + 'data-model': model_name, + 'data-ajax--url': reverse('jet:model_lookup') + } + + initial_value = field.value() + + if hasattr(field, 'field') and isinstance(field.field, ModelMultipleChoiceField): + if initial_value: + initial_objects = model.objects.filter(pk__in=initial_value) + choices.extend( + [(initial_object.pk, get_model_instance_label(initial_object)) + for initial_object in initial_objects] + ) + + if isinstance(field.field.widget, RelatedFieldWidgetWrapper): + field.field.widget.widget = SelectMultiple(attrs) + else: + field.field.widget = SelectMultiple(attrs) + field.field.choices = choices +~~ elif hasattr(field, 'field') and isinstance(field.field, ModelChoiceField): + if initial_value: + try: + initial_object = model.objects.get(pk=initial_value) + attrs['data-object-id'] = initial_value + choices.append((initial_object.pk, get_model_instance_label(initial_object))) + except model.DoesNotExist: + pass + + if isinstance(field.field.widget, RelatedFieldWidgetWrapper): + field.field.widget.widget = Select(attrs) + else: + field.field.widget = Select(attrs) + field.field.choices = choices + + return field + + +@assignment_tag(takes_context=True) +def jet_get_current_theme(context): + if 'request' in context and 'JET_THEME' in context['request'].COOKIES: + theme = context['request'].COOKIES['JET_THEME'] + if isinstance(settings.JET_THEMES, list) and len(settings.JET_THEMES) > 0: + for conf_theme in settings.JET_THEMES: + if isinstance(conf_theme, dict) and conf_theme.get('theme') == theme: + + +## ... source file continues with no further ModelChoiceField examples... + +``` + diff --git a/content/pages/examples/django/django-forms-modelform.markdown b/content/pages/examples/django/django-forms-modelform.markdown new file mode 100644 index 000000000..e48ce14a2 --- /dev/null +++ b/content/pages/examples/django/django-forms-modelform.markdown @@ -0,0 +1,202 @@ +title: django.forms ModelForm Example Code +category: page +slug: django-forms-modelform-examples +sortorder: 500011273 +toc: False +sidebartitle: django.forms ModelForm +meta: Python example code for the ModelForm class from the django.forms module of the Django project. + + +ModelForm is a class within the django.forms module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / proceedings / forms.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/proceedings/forms.py) + +```python +# forms.py +~~from django.forms import ModelForm + +from gears.widgets import DropdownSelectSubmit +from proceedings.models import CameraReady + + +EMPTY_VOLUME_LABEL = '(no volume)' + + +~~class UpdateVolumeForm(ModelForm): + + class Meta: + model = CameraReady + fields = ['volume'] + widgets = { + 'volume': DropdownSelectSubmit( + empty_label=EMPTY_VOLUME_LABEL, + label_class='font-weight-normal dccn-text-small', + empty_label_class='text-warning-18', + nonempty_label_class='text-success-18', + ) + } + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['volume'].queryset = self.instance.proc_type.volumes.all() + self.fields['volume'].empty_label = EMPTY_VOLUME_LABEL + + + +## ... source file continues with no further ModelForm examples... + +``` + + +## Example 2 from django-flexible-subscriptions +[django-flexible-subscriptions](https://github.com/studybuffalo/django-flexible-subscriptions) +([project documentation](https://django-flexible-subscriptions.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-flexible-subscriptions/)) +provides boilerplate code for adding subscription and recurrent billing +to [Django](/django.html) web applications. Various payment providers +can be added on the back end to run the transactions. + +The django-flexible-subscriptions project is open sourced under the +[GNU General Public License v3.0](https://github.com/studybuffalo/django-flexible-subscriptions/blob/master/LICENSE). + +[**django-flexible-subscriptions / subscriptions / forms.py**](https://github.com/studybuffalo/django-flexible-subscriptions/blob/master/subscriptions/./forms.py) + +```python +# forms.py +from django import forms +from django.core import validators +~~from django.forms import ModelForm +from django.utils import timezone + +from subscriptions.conf import SETTINGS +from subscriptions.models import SubscriptionPlan, PlanCost + + +def assemble_cc_years(): + cc_years = [] + now = timezone.now() + + for year in range(now.year, now.year + 60): + cc_years.append((year, year)) + + return cc_years + + +~~class SubscriptionPlanForm(ModelForm): + class Meta: + model = SubscriptionPlan + fields = [ + 'plan_name', 'plan_description', 'group', 'tags', 'grace_period', + ] + + +~~class PlanCostForm(ModelForm): + class Meta: + model = PlanCost + fields = ['recurrence_period', 'recurrence_unit', 'cost'] + + +class PaymentForm(forms.Form): + CC_MONTHS = ( + ('1', '01 - January'), + ('2', '02 - February'), + ('3', '03 - March'), + ('4', '04 - April'), + ('5', '05 - May'), + ('6', '06 - June'), + ('7', '07 - July'), + ('8', '08 - August'), + ('9', '09 - September'), + ('10', '10 - October'), + ('11', '11 - November'), + ('12', '12 - December'), + ) + CC_YEARS = assemble_cc_years() + + cardholder_name = forms.CharField( + label='Cardholder name', + + +## ... source file continues with no further ModelForm examples... + +``` + + +## Example 3 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / forms.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./forms.py) + +```python +# forms.py +from django.db import DatabaseError +~~from django.forms import ModelForm, Field, ValidationError, BooleanField, CharField +from django.forms.widgets import CheckboxInput, Select + +from explorer.app_settings import EXPLORER_DEFAULT_CONNECTION, EXPLORER_CONNECTIONS +from explorer.models import Query, MSG_FAILED_BLACKLIST + + +class SqlField(Field): + + def validate(self, value): + + query = Query(sql=value) + + passes_blacklist, failing_words = query.passes_blacklist() + + error = MSG_FAILED_BLACKLIST % ', '.join(failing_words) if not passes_blacklist else None + + if error: + raise ValidationError( + error, + code="InvalidSql" + ) + + +~~class QueryForm(ModelForm): + + sql = SqlField() + snapshot = BooleanField(widget=CheckboxInput, required=False) + connection = CharField(widget=Select, required=False) + + def __init__(self, *args, **kwargs): + super(QueryForm, self).__init__(*args, **kwargs) + self.fields['connection'].widget.choices = self.connections + if not self.instance.connection: + self.initial['connection'] = EXPLORER_DEFAULT_CONNECTION + self.fields['connection'].widget.attrs['class'] = 'form-control' + + def clean(self): + if self.instance and self.data.get('created_by_user', None): + self.cleaned_data['created_by_user'] = self.instance.created_by_user + return super(QueryForm, self).clean() + + @property + def created_by_user_email(self): + return self.instance.created_by_user.email if self.instance.created_by_user else '--' + + @property + def created_at_time(self): + return self.instance.created_at.strftime('%Y-%m-%d') + + +## ... source file continues with no further ModelForm examples... + +``` + diff --git a/content/pages/examples/django/django-forms-modelmultiplechoicefield.markdown b/content/pages/examples/django/django-forms-modelmultiplechoicefield.markdown new file mode 100644 index 000000000..6680b5dfc --- /dev/null +++ b/content/pages/examples/django/django-forms-modelmultiplechoicefield.markdown @@ -0,0 +1,121 @@ +title: django.forms ModelMultipleChoiceField Example Code +category: page +slug: django-forms-modelmultiplechoicefield-examples +sortorder: 500011274 +toc: False +sidebartitle: django.forms ModelMultipleChoiceField +meta: Python example code for the ModelMultipleChoiceField class from the django.forms module of the Django project. + + +ModelMultipleChoiceField is a class within the django.forms module of the Django project. + + +## Example 1 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / templatetags / jet_tags.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/templatetags/jet_tags.py) + +```python +# jet_tags.py +from __future__ import unicode_literals +import json +import os +from django import template +try: + from django.core.urlresolvers import reverse +except ImportError: # Django 1.11 + from django.urls import reverse + +~~from django.forms import CheckboxInput, ModelChoiceField, Select, ModelMultipleChoiceField, SelectMultiple +from django.contrib.admin.widgets import RelatedFieldWidgetWrapper +from django.utils.formats import get_format +from django.utils.safestring import mark_safe +from django.utils.encoding import smart_text +from jet import settings, VERSION +from jet.models import Bookmark +from jet.utils import get_model_instance_label, get_model_queryset, get_possible_language_codes, \ + get_admin_site, get_menu_items + +try: + from urllib.parse import parse_qsl +except ImportError: + from urlparse import parse_qsl + + +register = template.Library() +assignment_tag = register.assignment_tag if hasattr(register, 'assignment_tag') else register.simple_tag + + +@assignment_tag +def jet_get_date_format(): + return get_format('DATE_INPUT_FORMATS')[0] + + + + +## ... source file abbreviated to get to ModelMultipleChoiceField examples ... + + +def jet_is_checkbox(field): + return field.field.widget.__class__.__name__ == CheckboxInput().__class__.__name__ + + +@register.filter +def jet_select2_lookups(field): + if hasattr(field, 'field') and \ + (isinstance(field.field, ModelChoiceField) or isinstance(field.field, ModelMultipleChoiceField)): + qs = field.field.queryset + model = qs.model + + if getattr(model, 'autocomplete_search_fields', None) and getattr(field.field, 'autocomplete', True): + choices = [] + app_label = model._meta.app_label + model_name = model._meta.object_name + + attrs = { + 'class': 'ajax', + 'data-app-label': app_label, + 'data-model': model_name, + 'data-ajax--url': reverse('jet:model_lookup') + } + + initial_value = field.value() + +~~ if hasattr(field, 'field') and isinstance(field.field, ModelMultipleChoiceField): + if initial_value: + initial_objects = model.objects.filter(pk__in=initial_value) + choices.extend( + [(initial_object.pk, get_model_instance_label(initial_object)) + for initial_object in initial_objects] + ) + + if isinstance(field.field.widget, RelatedFieldWidgetWrapper): + field.field.widget.widget = SelectMultiple(attrs) + else: + field.field.widget = SelectMultiple(attrs) + field.field.choices = choices + elif hasattr(field, 'field') and isinstance(field.field, ModelChoiceField): + if initial_value: + try: + initial_object = model.objects.get(pk=initial_value) + attrs['data-object-id'] = initial_value + choices.append((initial_object.pk, get_model_instance_label(initial_object))) + except model.DoesNotExist: + pass + + if isinstance(field.field.widget, RelatedFieldWidgetWrapper): + field.field.widget.widget = Select(attrs) + else: + + +## ... source file continues with no further ModelMultipleChoiceField examples... + +``` + diff --git a/content/pages/examples/django/django-forms-multiplechoicefield.markdown b/content/pages/examples/django/django-forms-multiplechoicefield.markdown new file mode 100644 index 000000000..2faa61d74 --- /dev/null +++ b/content/pages/examples/django/django-forms-multiplechoicefield.markdown @@ -0,0 +1,269 @@ +title: django.forms MultipleChoiceField Example Code +category: page +slug: django-forms-multiplechoicefield-examples +sortorder: 500011275 +toc: False +sidebartitle: django.forms MultipleChoiceField +meta: Python example code for the MultipleChoiceField class from the django.forms module of the Django project. + + +MultipleChoiceField is a class within the django.forms module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / chair / forms.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/chair/forms.py) + +```python +# forms.py +from functools import reduce + +from django import forms +from django.contrib.auth import get_user_model +from django.db import models +from django.db.models import Q, F, Count, Max, Subquery, OuterRef, Value +from django.db.models.functions import Concat +~~from django.forms import MultipleChoiceField, ChoiceField, Form +from django.urls import reverse +from django.utils.translation import ugettext_lazy as _ + +from django_countries import countries + +from conferences.models import Conference, ArtifactDescriptor +from gears.widgets import CustomCheckboxSelectMultiple, CustomFileInput +from review.models import Reviewer, Review, ReviewStats +from review.utilities import get_average_score +from submissions.models import Submission, Attachment +from users.models import Profile + +User = get_user_model() + + +def clean_data_to_int(iterable, empty=None): + return [int(x) if x != '' else None for x in iterable] + + +def q_or(disjuncts, default=True): + if disjuncts: + return reduce(lambda acc, d: acc | d, disjuncts) + return Q(pk__isnull=(not default)) # otherwise, check whether PK is null + + + +## ... source file abbreviated to get to MultipleChoiceField examples ... + + + ) + + Q1 = 'Q1' + Q2 = 'Q2' + Q3 = 'Q3' + Q4 = 'Q4' + QUARTILE_CHOICES = ((Q1, 'Q1'), (Q2, 'Q2'), (Q3, 'Q3'), (Q4, 'Q4')) + + ORDER_BY_PK = 'PK' + ORDER_BY_TITLE = 'TITLE' + ORDER_BY_SCORE = 'SCORE' + ORDER_CHOICES = ( + (ORDER_BY_PK, 'Order by ID'), + (ORDER_BY_SCORE, 'Order by score'), + (ORDER_BY_TITLE, 'Order by title'), + ) + + DIRECTION_CHOICES = (('ASC', 'Ascending'), ('DESC', 'Descending')) + + class Meta: + model = Conference + fields = [] + + term = forms.CharField(required=False) + +~~ completion = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple(attrs={ + 'btn_class': 'btn btn-link dccn-link dccn-text-small', + 'label_class': 'dccn-text-0', + }), required=False, choices=COMPLETION_CHOICES) + +~~ types = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False) + +~~ topics = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False) + +~~ status = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False, + choices=Submission.STATUS_CHOICE) + +~~ countries = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False) + +~~ affiliations = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False) + +~~ proc_types = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple( + attrs={'label': 'Proceedings'}), required=False) + +~~ volumes = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False) + +~~ quartiles = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False, + choices=QUARTILE_CHOICES) + +~~ artifacts = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False) + + order = ChoiceField(required=False, choices=ORDER_CHOICES) + direction = ChoiceField(required=False, choices=DIRECTION_CHOICES) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + assert isinstance(self.instance, Conference) + self.fields['types'].choices = [ + (x.pk, x.name) for x in self.instance.submissiontype_set.all()] + self.fields['topics'].choices = [ + (x.pk, x.name) for x in self.instance.topic_set.all()] + self.fields['proc_types'].choices = [('', 'Not defined')] + [ + (x.pk, x.name) for x in self.instance.proceedingtype_set.all()] + self.fields['volumes'].choices = [('', 'Not defined')] + [ + (vol_pk, vol_name) for (vol_pk, vol_name) in + self.instance.proceedingtype_set.values_list( + 'volumes__pk', 'volumes__name').distinct()] + self.fields['artifacts'].choices = [ + (x.pk, f'{x.name} ({x.proc_type.name}') for x in + ArtifactDescriptor.objects.filter( + proc_type__conference=self.instance)] + + profiles_data = Profile.objects.filter( + + +## ... source file abbreviated to get to MultipleChoiceField examples ... + + + term = forms.CharField(required=False) + + authorship = forms.MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False, + choices=AUTHORSHIP_CHOICES, + ) + + countries = forms.MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False, + ) + + affiliations = forms.MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False, + ) + + graduation = forms.MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False, + choices=GRADUATION_CHOICES, + ) + + membership = forms.MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False, + choices=MEMBERSHIP_CHOICES, + ) + +~~ reviewer = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple, required=False, + choices=REVIEWER_CHOICES) + + order = ChoiceField(required=False, choices=ORDER_CHOICES) + direction = ChoiceField(required=False, choices=DIRECTION_CHOICES) + + columns = forms.MultipleChoiceField( + required=False, choices=COLUMNS, + widget=CustomCheckboxSelectMultiple + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + assert isinstance(self.instance, Conference) + countries_dict = dict(countries) + + self.fields['countries'].choices = [ + (code, countries_dict[code]) for code in + Profile.objects.filter(country__isnull=False).values_list( + 'country', flat=True).order_by('country').distinct()] + + self.fields['affiliations'].choices = [ + (aff, aff) for aff in + Profile.objects.values_list('affiliation', flat=True).order_by( + + +## ... source file abbreviated to get to MultipleChoiceField examples ... + + +class ExportSubmissionsForm(Form): + ORDER_COLUMN = '#' + ID_COLUMN = 'ID' + AUTHORS_COLUMN = 'AUTHORS' + TITLE_COLUMN = 'TITLE' + COUNTRY_COLUMN = 'COUNTRY' + STYPE_COLUMN = 'TYPE' + REVIEW_PAPER_COLUMN = 'REVIEW_MANUSCRIPT' + REVIEW_SCORE_COLUMN = 'REVIEW_SCORE' + STATUS_COLUMN = 'STATUS' + TOPICS_COLUMN = 'TOPICS' + + COLUMNS = ( + (ORDER_COLUMN, ORDER_COLUMN), + (ID_COLUMN, ID_COLUMN), + (TITLE_COLUMN, TITLE_COLUMN), + (AUTHORS_COLUMN, AUTHORS_COLUMN), + (COUNTRY_COLUMN, COUNTRY_COLUMN), + (STYPE_COLUMN, STYPE_COLUMN), + (REVIEW_PAPER_COLUMN, REVIEW_PAPER_COLUMN), + (REVIEW_SCORE_COLUMN, REVIEW_SCORE_COLUMN), + (STATUS_COLUMN, STATUS_COLUMN), + (TOPICS_COLUMN, TOPICS_COLUMN), + ) + +~~ columns = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple(hide_apply_btn=True), + required=False, choices=COLUMNS) + +~~ status = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple(hide_apply_btn=True), + required=False, choices=Submission.STATUS_CHOICE) + +~~ countries = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple(hide_apply_btn=True), + required=False) + +~~ topics = MultipleChoiceField( + widget=CustomCheckboxSelectMultiple(hide_apply_btn=True), + required=False) + + def __init__(self, *args, conference=None, **kwargs): + super().__init__(*args, **kwargs) + if conference is None: + raise ValueError('conference must be provided') + self.conference = conference + self.fields['columns'].initial = [ + self.ORDER_COLUMN, self.ID_COLUMN, self.TITLE_COLUMN, + self.AUTHORS_COLUMN, self.STATUS_COLUMN] + countries_list = list( + set(p.country for p in Profile.objects.all() if p.country)) + countries_list.sort(key=lambda cnt: cnt.name) + self.fields['countries'].choices = [ + (cnt.code, cnt.name) for cnt in countries_list] + self.fields['topics'].choices = [ + (t.pk, t.name) for t in self.conference.topic_set.all()] + + def apply(self, request): + submissions = Submission.objects.filter(conference=self.conference) + if self.cleaned_data['status']: + submissions = submissions.filter( + status__in=self.cleaned_data['status']) + + +## ... source file continues with no further MultipleChoiceField examples... + +``` + diff --git a/content/pages/examples/django/django-forms-select.markdown b/content/pages/examples/django/django-forms-select.markdown new file mode 100644 index 000000000..9a7f7ca44 --- /dev/null +++ b/content/pages/examples/django/django-forms-select.markdown @@ -0,0 +1,195 @@ +title: django.forms Select Example Code +category: page +slug: django-forms-select-examples +sortorder: 500011276 +toc: False +sidebartitle: django.forms Select +meta: Python example code for the Select class from the django.forms module of the Django project. + + +Select is a class within the django.forms module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / gears / widgets.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/gears/widgets.py) + +```python +# widgets.py +~~from django.forms import FileInput, CheckboxSelectMultiple, Select + + +class CustomFileInput(FileInput): + template_name = 'gears/widgets/file_input.html' + accept = '' + show_file_name = True + + +class CustomCheckboxSelectMultiple(CheckboxSelectMultiple): + template_name = 'gears/widgets/checkbox_multiple_select.html' + hide_label = False + hide_apply_btn = False + + class Media: + js = ('gears/js/checkbox_multiple_select.js',) + + def __init__(self, *args, **kwargs): + self.hide_label = kwargs.pop('hide_label', False) + self.hide_apply_btn = kwargs.pop('hide_apply_btn', False) + super().__init__(*args, **kwargs) + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + context['widget'].update({ + 'hide_label': self.hide_label, + 'hide_apply_btn': self.hide_apply_btn, + }) + return context + + +~~class DropdownSelectSubmit(Select): + template_name = 'gears/widgets/dropdown_select_submit.html' + empty_label = 'Not selected' + label_class = '' + empty_label_class = 'text-warning' + nonempty_label_class = 'text-success' + + class Media: + js = ('gears/js/dropdown_select_submit.js',) + + def __init__(self, *args, **kwargs): + self.empty_label = kwargs.pop('empty_label', 'Not selected') + self.label_class = kwargs.pop('label_class', '') + self.empty_label_class = kwargs.pop('empty_label_class', 'text-warning') + self.nonempty_label_class = kwargs.pop( + 'nonempty_label_class', 'text-success') + super().__init__(*args, **kwargs) + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + widget = context['widget'] + widget['label_class'] = self.label_class + widget['empty_label_class'] = self.empty_label_class + widget['nonempty_label_class'] = self.nonempty_label_class + widget['label'] = self.empty_label + + +## ... source file continues with no further Select examples... + +``` + + +## Example 2 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / templatetags / jet_tags.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/templatetags/jet_tags.py) + +```python +# jet_tags.py +from __future__ import unicode_literals +import json +import os +from django import template +try: + from django.core.urlresolvers import reverse +except ImportError: # Django 1.11 + from django.urls import reverse + +~~from django.forms import CheckboxInput, ModelChoiceField, Select, ModelMultipleChoiceField, SelectMultiple +from django.contrib.admin.widgets import RelatedFieldWidgetWrapper +from django.utils.formats import get_format +from django.utils.safestring import mark_safe +from django.utils.encoding import smart_text +from jet import settings, VERSION +from jet.models import Bookmark +from jet.utils import get_model_instance_label, get_model_queryset, get_possible_language_codes, \ + get_admin_site, get_menu_items + +try: + from urllib.parse import parse_qsl +except ImportError: + from urlparse import parse_qsl + + +register = template.Library() +assignment_tag = register.assignment_tag if hasattr(register, 'assignment_tag') else register.simple_tag + + +@assignment_tag +def jet_get_date_format(): + return get_format('DATE_INPUT_FORMATS')[0] + + + + +## ... source file abbreviated to get to Select examples ... + + + initial_value = field.value() + + if hasattr(field, 'field') and isinstance(field.field, ModelMultipleChoiceField): + if initial_value: + initial_objects = model.objects.filter(pk__in=initial_value) + choices.extend( + [(initial_object.pk, get_model_instance_label(initial_object)) + for initial_object in initial_objects] + ) + + if isinstance(field.field.widget, RelatedFieldWidgetWrapper): + field.field.widget.widget = SelectMultiple(attrs) + else: + field.field.widget = SelectMultiple(attrs) + field.field.choices = choices + elif hasattr(field, 'field') and isinstance(field.field, ModelChoiceField): + if initial_value: + try: + initial_object = model.objects.get(pk=initial_value) + attrs['data-object-id'] = initial_value + choices.append((initial_object.pk, get_model_instance_label(initial_object))) + except model.DoesNotExist: + pass + + if isinstance(field.field.widget, RelatedFieldWidgetWrapper): +~~ field.field.widget.widget = Select(attrs) + else: +~~ field.field.widget = Select(attrs) + field.field.choices = choices + + return field + + +@assignment_tag(takes_context=True) +def jet_get_current_theme(context): + if 'request' in context and 'JET_THEME' in context['request'].COOKIES: + theme = context['request'].COOKIES['JET_THEME'] + if isinstance(settings.JET_THEMES, list) and len(settings.JET_THEMES) > 0: + for conf_theme in settings.JET_THEMES: + if isinstance(conf_theme, dict) and conf_theme.get('theme') == theme: + return theme + return settings.JET_DEFAULT_THEME + + +@assignment_tag +def jet_get_themes(): + return settings.JET_THEMES + + +@assignment_tag +def jet_get_current_version(): + return VERSION + + +## ... source file continues with no further Select examples... + +``` + diff --git a/content/pages/examples/django/django-forms-selectmultiple.markdown b/content/pages/examples/django/django-forms-selectmultiple.markdown new file mode 100644 index 000000000..571f1b1ce --- /dev/null +++ b/content/pages/examples/django/django-forms-selectmultiple.markdown @@ -0,0 +1,123 @@ +title: django.forms SelectMultiple Example Code +category: page +slug: django-forms-selectmultiple-examples +sortorder: 500011277 +toc: False +sidebartitle: django.forms SelectMultiple +meta: Python example code for the SelectMultiple class from the django.forms module of the Django project. + + +SelectMultiple is a class within the django.forms module of the Django project. + + +## Example 1 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / templatetags / jet_tags.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/templatetags/jet_tags.py) + +```python +# jet_tags.py +from __future__ import unicode_literals +import json +import os +from django import template +try: + from django.core.urlresolvers import reverse +except ImportError: # Django 1.11 + from django.urls import reverse + +~~from django.forms import CheckboxInput, ModelChoiceField, Select, ModelMultipleChoiceField, SelectMultiple +from django.contrib.admin.widgets import RelatedFieldWidgetWrapper +from django.utils.formats import get_format +from django.utils.safestring import mark_safe +from django.utils.encoding import smart_text +from jet import settings, VERSION +from jet.models import Bookmark +from jet.utils import get_model_instance_label, get_model_queryset, get_possible_language_codes, \ + get_admin_site, get_menu_items + +try: + from urllib.parse import parse_qsl +except ImportError: + from urlparse import parse_qsl + + +register = template.Library() +assignment_tag = register.assignment_tag if hasattr(register, 'assignment_tag') else register.simple_tag + + +@assignment_tag +def jet_get_date_format(): + return get_format('DATE_INPUT_FORMATS')[0] + + + + +## ... source file abbreviated to get to SelectMultiple examples ... + + + model = qs.model + + if getattr(model, 'autocomplete_search_fields', None) and getattr(field.field, 'autocomplete', True): + choices = [] + app_label = model._meta.app_label + model_name = model._meta.object_name + + attrs = { + 'class': 'ajax', + 'data-app-label': app_label, + 'data-model': model_name, + 'data-ajax--url': reverse('jet:model_lookup') + } + + initial_value = field.value() + + if hasattr(field, 'field') and isinstance(field.field, ModelMultipleChoiceField): + if initial_value: + initial_objects = model.objects.filter(pk__in=initial_value) + choices.extend( + [(initial_object.pk, get_model_instance_label(initial_object)) + for initial_object in initial_objects] + ) + + if isinstance(field.field.widget, RelatedFieldWidgetWrapper): +~~ field.field.widget.widget = SelectMultiple(attrs) + else: +~~ field.field.widget = SelectMultiple(attrs) + field.field.choices = choices + elif hasattr(field, 'field') and isinstance(field.field, ModelChoiceField): + if initial_value: + try: + initial_object = model.objects.get(pk=initial_value) + attrs['data-object-id'] = initial_value + choices.append((initial_object.pk, get_model_instance_label(initial_object))) + except model.DoesNotExist: + pass + + if isinstance(field.field.widget, RelatedFieldWidgetWrapper): + field.field.widget.widget = Select(attrs) + else: + field.field.widget = Select(attrs) + field.field.choices = choices + + return field + + +@assignment_tag(takes_context=True) +def jet_get_current_theme(context): + if 'request' in context and 'JET_THEME' in context['request'].COOKIES: + theme = context['request'].COOKIES['JET_THEME'] + if isinstance(settings.JET_THEMES, list) and len(settings.JET_THEMES) > 0: + + +## ... source file continues with no further SelectMultiple examples... + +``` + diff --git a/content/pages/examples/django/django-forms-typedchoicefield.markdown b/content/pages/examples/django/django-forms-typedchoicefield.markdown new file mode 100644 index 000000000..10fb85a86 --- /dev/null +++ b/content/pages/examples/django/django-forms-typedchoicefield.markdown @@ -0,0 +1,171 @@ +title: django.forms TypedChoiceField Python Code Examples +category: page +slug: django-forms-typedchoicefield-examples +sortorder: 500013129 +toc: False +sidebartitle: django.forms TypedChoiceField +meta: View code examples that show how to use the TypedChoiceField class within the forms module of Django. + + +[TypedChoiceField](https://github.com/django/django/blob/master/django/forms/fields.py) +([documentation](https://docs.djangoproject.com/en/stable/ref/forms/fields/#typedchoicefield)), +from the [Django](/django.html) `forms` module, enables safe handling of +pre-defined selections collected via an HTTP POST request from an +[HTML](/hypertext-markup-language-html.html) form submission. + +TypedChoiceField can either be imported from `django.forms` or +`django.forms.fields`. `django.forms` is more commonly used because it +is less characters for the equivalent effect. + + +## Example 1 from dmd-interpreter +[dmd-interpreter](https://github.com/mitchalexbailey/dmd-interpreter) +([running web app](http://www.dmd.nl/DOVE)) +is a Python tool to aggregate clinically relevant information related +to variants in the DMD gene and display that [data](/data.html) to a user +with a [Django](/django.html) web application. + +[**dmd-interpreter / interpreter / forms.py**](https://github.com/mitchalexbailey/dmd-interpreter/blob/master/interpreter/./forms.py) + +```python +# forms.py +~~from django import forms + +choices = [(True,'Yes'),(False,'No')] + +class IndexForm(forms.Form): + mutation = forms.CharField(label = 'Mutation', max_length = 100) + +class ACMGForm(forms.Form): +~~ pvs1 = forms.TypedChoiceField(label = 'Does the variant cause a premature stop codon (nonsense)?', choices=choices, widget=forms.RadioSelect) +~~ pvs2 = forms.TypedChoiceField(label = 'Does the variant cause a frameshift?', choices=choices, widget=forms.RadioSelect) +~~ pvs3 = forms.TypedChoiceField(label = 'Does the variant cause a multiexon deletion involving key functional domains?', choices=choices, widget=forms.RadioSelect) +~~ pvs4 = forms.TypedChoiceField(label = 'Does the variant cause a change in splice site?', choices=choices, widget=forms.RadioSelect) +~~ pvs5 = forms.TypedChoiceField(label = 'Does the variant cause a change in initiation codon?', choices=choices, widget=forms.RadioSelect) +~~ ps1 = forms.TypedChoiceField(label = 'Is there a reported pathogenic variant causing the same amino acid change?', choices=choices, widget=forms.RadioSelect) +~~ ps2 = forms.TypedChoiceField(label = 'Is the variant de novo (confirmed to not be present in either parent)?', choices=choices, widget=forms.RadioSelect) +~~ ps3 = forms.TypedChoiceField(label = 'Are there well-established in vitro studies predicting a damaging effect of this variant on the gene or gene product?', choices=choices, widget=forms.RadioSelect) +~~ ps4 = forms.TypedChoiceField(label = 'Is this variant more prevalence in affected individuals versus controls? (OR > 5.0)', choices=choices, widget=forms.RadioSelect) +~~ pm1 = forms.TypedChoiceField(label = 'Is this variant located in a mutational hot spot and/or critical functional domain?', choices=choices, widget=forms.RadioSelect) +~~ pm2 = forms.TypedChoiceField(label = 'Is the variant absent from controls (autosomal dominant), or found at an extremely low frequency (autosomal recessive)? (Ex. in ExAC or 1000 genomes)', choices=choices, widget=forms.RadioSelect) +~~ pm3 = forms.TypedChoiceField(label = 'Is this variant in a gene linked to an autosomal recessive condition and in trans with a pathogenic variant?', choices=choices, widget=forms.RadioSelect) +~~ pm4 = forms.TypedChoiceField(label = 'Does the variant change the protein length (while preserving reading frame; deletion, insertion, stop-loss)?', choices=choices, widget=forms.RadioSelect) +~~ pm5 = forms.TypedChoiceField(label = 'Does the variant cause a missense change at a residue where a different change is known to be pathogenic?', choices=choices, widget=forms.RadioSelect) +~~ pm6 = forms.TypedChoiceField(label = 'Do you think the variant is de novo but there has not been confirmation (sequencing of parents)?', choices=choices, widget=forms.RadioSelect) +~~ pp1 = forms.TypedChoiceField(label = 'Is the variant in a known disease-causing gene and has it co-segregated with affected family members?', choices=choices, widget=forms.RadioSelect) +~~ pp2 = forms.TypedChoiceField(label = 'Is the variant in a gene where disease-causing variants are not commonly missense, and in which missense variants are a common mechanism of disease?', choices=choices, widget=forms.RadioSelect) +~~ pp3 = forms.TypedChoiceField(label = 'Do multiple in silico functional predication tools support a deleterious effect on the gene or gene product?', choices=choices, widget=forms.RadioSelect) +~~ pp4 = forms.TypedChoiceField(label = 'Does the patient\'s phenotype and/or family history strongly indicate a disease with a single genetic ontology?', choices=choices, widget=forms.RadioSelect) +~~ pp5 = forms.TypedChoiceField(label = 'Does a reputable source report the variant as pathogenic (but the evidence is not available)?', choices=choices, widget=forms.RadioSelect) +``` + + +# Example 2 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / forms / fields.py**](https://github.com/jrief/django-angular/blob/master/djng/forms/fields.py) + +```python +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import re +import mimetypes + +from django.conf import settings +from django.contrib.staticfiles.storage import staticfiles_storage +from django.core import signing +from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.core.files.storage import default_storage +from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile +from django.urls import reverse_lazy +~~from django.forms import fields, models as model_fields, widgets +from django.utils.html import format_html +from django.utils.module_loading import import_string +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext_lazy as _, ungettext_lazy + +from djng import app_settings +from .widgets import DropFileWidget, DropImageWidget + + +## ... source file abbreviated to get to the TypedChoiceField examples ... + +~~class TypedChoiceField(MultipleFieldMixin, fields.TypedChoiceField): +~~ def get_potential_errors(self): +~~ if isinstance(self.widget, widgets.RadioSelect): +~~ errors = self.get_multiple_choices_required() +~~ else: +~~ errors = self.get_input_required_errors() +~~ return errors + + + +## ... source file continues with no further examples ... +``` + + +## Example 3 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / filters.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./filters.py) + +```python +from collections import OrderedDict +from datetime import timedelta + +~~from django import forms +from django.db.models import Q +from django.db.models.constants import LOOKUP_SEP +from django.forms.utils import pretty_name +from django.utils.itercompat import is_iterable +from django.utils.timezone import now +from django.utils.translation import gettext_lazy as _ + +from .conf import settings +from .constants import EMPTY_VALUES +from .fields import ( + BaseCSVField, + BaseRangeField, + ChoiceField, + DateRangeField, + DateTimeRangeField, + IsoDateTimeField, + IsoDateTimeRangeField, + LookupChoiceField, + ModelChoiceField, + ModelMultipleChoiceField, + MultipleChoiceField, + RangeField, + TimeRangeField +) +from .utils import get_model_field, label_for_filter + + +## ... source file abbreviated to get to code examples ... + + +~~class TypedChoiceFilter(Filter): +~~ field_class = forms.TypedChoiceField + + +class UUIDFilter(Filter): + field_class = forms.UUIDField + + +## ... source file continues with no further TypedChoiceField examples ... + +``` + diff --git a/content/pages/examples/django/django-forms-validationerror.markdown b/content/pages/examples/django/django-forms-validationerror.markdown new file mode 100644 index 000000000..59a18ace7 --- /dev/null +++ b/content/pages/examples/django/django-forms-validationerror.markdown @@ -0,0 +1,502 @@ +title: django.forms ValidationError Example Code +category: page +slug: django-forms-validationerror-examples +sortorder: 500011278 +toc: False +sidebartitle: django.forms ValidationError +meta: Python example code for the ValidationError class from the django.forms module of the Django project. + + +ValidationError is a class within the django.forms module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / socialaccount / helpers.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/helpers.py) + +```python +# helpers.py +from django.contrib import messages +~~from django.forms import ValidationError +from django.http import HttpResponseRedirect +from django.shortcuts import render +from django.urls import reverse + +from allauth.account import app_settings as account_settings +from allauth.account.adapter import get_adapter as get_account_adapter +from allauth.account.utils import complete_signup, perform_login, user_username +from allauth.exceptions import ImmediateHttpResponse + +from . import app_settings, signals +from .adapter import get_adapter +from .models import SocialLogin +from .providers.base import AuthError, AuthProcess + + +def _process_signup(request, sociallogin): + auto_signup = get_adapter(request).is_auto_signup_allowed( + request, + sociallogin) + if not auto_signup: + request.session['socialaccount_sociallogin'] = sociallogin.serialize() + url = reverse('socialaccount_signup') + ret = HttpResponseRedirect(url) + else: + if account_settings.USER_MODEL_USERNAME_FIELD: + username = user_username(sociallogin.user) + try: + get_account_adapter(request).clean_username(username) +~~ except ValidationError: + user_username(sociallogin.user, '') + if not get_adapter(request).is_open_for_signup( + request, + sociallogin): + return render( + request, + "account/signup_closed." + + account_settings.TEMPLATE_EXTENSION) + get_adapter(request).save_user(request, sociallogin, form=None) + ret = complete_social_signup(request, sociallogin) + return ret + + +def _login_social_account(request, sociallogin): + return perform_login(request, sociallogin.user, + email_verification=app_settings.EMAIL_VERIFICATION, + redirect_url=sociallogin.get_redirect_url(request), + signal_kwargs={"sociallogin": sociallogin}) + + +def render_authentication_error(request, + provider_id, + error=AuthError.UNKNOWN, + exception=None, + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 2 from django-jsonfield +[django-jsonfield](https://github.com/dmkoch/django-jsonfield) +([jsonfield on PyPi](https://pypi.org/project/jsonfield/)) is a +[Django](/django.html) code library that makes it easier to store validated +JSON in a [Django object-relational mapper (ORM)](/django-orm.html) database +model. + +The django-jsonfield project is open source under the +[MIT license](https://github.com/dmkoch/django-jsonfield/blob/master/LICENSE). + +[**django-jsonfield / src/jsonfield / fields.py**](https://github.com/dmkoch/django-jsonfield/blob/master/src/jsonfield/./fields.py) + +```python +# fields.py +import copy +import json +import warnings + +from django.db import models +~~from django.forms import ValidationError +from django.utils.translation import gettext_lazy as _ + +from . import forms +from .encoder import JSONEncoder +from .json import JSONString, checked_loads + +DEFAULT_DUMP_KWARGS = { + 'cls': JSONEncoder, +} + +DEFAULT_LOAD_KWARGS = {} + +INVALID_JSON_WARNING = ( + '{0!s} failed to load invalid json ({1}) from the database. The value has ' + 'been returned as a string instead.' +) + + +class JSONFieldMixin(models.Field): + form_class = forms.JSONField + + def __init__(self, *args, dump_kwargs=None, load_kwargs=None, **kwargs): + self.dump_kwargs = DEFAULT_DUMP_KWARGS if dump_kwargs is None else dump_kwargs + self.load_kwargs = DEFAULT_LOAD_KWARGS if load_kwargs is None else load_kwargs + + super().__init__(*args, **kwargs) + + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + + if self.dump_kwargs != DEFAULT_DUMP_KWARGS: + kwargs['dump_kwargs'] = self.dump_kwargs + if self.load_kwargs != DEFAULT_LOAD_KWARGS: + kwargs['load_kwargs'] = self.load_kwargs + + return name, path, args, kwargs + + def to_python(self, value): + try: + return checked_loads(value, **self.load_kwargs) + except ValueError: +~~ raise ValidationError(_("Enter valid JSON.")) + + def from_db_value(self, value, expression, connection): + if value is None: + return None + + try: + return checked_loads(value, **self.load_kwargs) + except json.JSONDecodeError: + warnings.warn(INVALID_JSON_WARNING.format(self, value), RuntimeWarning) + return JSONString(value) + + def get_prep_value(self, value): + if self.null and value is None: + return None + return json.dumps(value, **self.dump_kwargs) + + def value_to_string(self, obj): + value = self.value_from_object(obj) + return json.dumps(value, **self.dump_kwargs) + + def formfield(self, **kwargs): + kwargs.setdefault('form_class', self.form_class) + if issubclass(kwargs['form_class'], forms.JSONField): + kwargs.setdefault('dump_kwargs', self.dump_kwargs) + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 3 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / forms.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./forms.py) + +```python +# forms.py +from django.db import DatabaseError +~~from django.forms import ModelForm, Field, ValidationError, BooleanField, CharField +from django.forms.widgets import CheckboxInput, Select + +from explorer.app_settings import EXPLORER_DEFAULT_CONNECTION, EXPLORER_CONNECTIONS +from explorer.models import Query, MSG_FAILED_BLACKLIST + + +class SqlField(Field): + + def validate(self, value): + + query = Query(sql=value) + + passes_blacklist, failing_words = query.passes_blacklist() + + error = MSG_FAILED_BLACKLIST % ', '.join(failing_words) if not passes_blacklist else None + + if error: +~~ raise ValidationError( + error, + code="InvalidSql" + ) + + +class QueryForm(ModelForm): + + sql = SqlField() + snapshot = BooleanField(widget=CheckboxInput, required=False) + connection = CharField(widget=Select, required=False) + + def __init__(self, *args, **kwargs): + super(QueryForm, self).__init__(*args, **kwargs) + self.fields['connection'].widget.choices = self.connections + if not self.instance.connection: + self.initial['connection'] = EXPLORER_DEFAULT_CONNECTION + self.fields['connection'].widget.attrs['class'] = 'form-control' + + def clean(self): + if self.instance and self.data.get('created_by_user', None): + self.cleaned_data['created_by_user'] = self.instance.created_by_user + return super(QueryForm, self).clean() + + @property + + +## ... source file continues with no further ValidationError examples... + +``` + + +## Example 4 from register +[register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is +open source under the +[GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). +This web application makes it easier for people to register as organ donors. +You can see the application live at +[https://register.organize.org/](https://register.organize.org/). + +[**register / registration / forms.py**](https://github.com/ORGAN-IZE/register/blob/master/registration/./forms.py) + +```python +# forms.py +from __future__ import unicode_literals + +import logging +import re +import collections +import datetime + +~~import django.forms +~~import django.forms.utils +~~import django.forms.widgets +import django.core.validators +import django.core.exceptions +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ +from django.utils.safestring import mark_safe + +import form_utils.forms +import requests +import dateutil.parser +import validate_email + +logger = logging.getLogger(__name__) + + +REGISTRATION_CONFIGURATION_NAME = 'registration_configuration' + +RE_NON_DECIMAL = re.compile(r'[^\d]+') +RE_NON_ALPHA = re.compile('[\W]+') +RE_POSTAL_CODE = re.compile(r'^[0-9]{5}$') +validate_postal_code = django.core.validators.RegexValidator( + RE_POSTAL_CODE, _("Enter a valid postal code consisting 5 numbers."), 'invalid') + + +CHOICES_GENDER = ( + + +## ... source file abbreviated to get to ValidationError examples ... + + +class StateLookupForm(django.forms.Form): + email = django.forms.EmailField(label=_('Email'), help_text=_('so we can send you confirmation of your registration')) + postal_code = django.forms.CharField( + label=_('Postal Code'), + max_length=5, min_length=5, validators=[validate_postal_code], + help_text=_('to determine which series of state-based questions we will ask next')) + + def clean_email(self): + email = self.cleaned_data['email'] + if settings.DISABLE_EMAIL_VALIDATION: + logger.warning('Email validation disabled: DISABLE_EMAIL_VALIDATION ' + 'is set') + return email + if not hasattr(settings, 'MAILGUN_PUBLIC_API_KEY'): + logger.warning( + 'Cannot validate email: MAILGUN_PUBLIC_API_KEY not set') + return email + r = requests.get( + 'https://api.mailgun.net/v2/address/validate', + data={'address': email, }, + auth=('api', settings.MAILGUN_PUBLIC_API_KEY)) + if r.status_code == 200: + if r.json()['is_valid']: + return email + logger.warning('Cannot validate email: {}'.format(r.text)) +~~ raise django.forms.ValidationError(_('Enter a valid email.')) + + +class UPENNStateLookupForm(StateLookupForm): + error_css_class = 'invalid-data-error' + email = django.forms.EmailField(label='') + postal_code = django.forms.CharField(label='', max_length=5, min_length=5, validators=[validate_postal_code]) + + email.widget.attrs['placeholder'] = 'EMAIL' + email.widget.attrs['class'] = 'upenn-text-field' + + postal_code.widget.attrs['placeholder'] = 'POSTAL CODE' + postal_code.widget.attrs['class'] = 'upenn-text-field' + + +def register_form_clean(self): + cleaned_data = super(self.__class__, self).clean() + + if self.validate_organ_tissue_selection: + organ_choices = [value for key, value in cleaned_data.items() if key.startswith('include')] + if organ_choices: + if not any(organ_choices): +~~ raise django.forms.ValidationError(_('At least one organ/tissue needs to be selected')) + + if self.api_errors and not self.skip_api_error_validation: + for k, v in self.api_errors.items(): + if k in self.fields: + self.add_error(k, v) + + return cleaned_data + + +def register_form_clean_license_id(self): + license_id = self.cleaned_data['license_id'] + if self.fields['license_id'].required and is_license_id_not_applicable(license_id): +~~ raise django.forms.ValidationError(_('License ID is required.')) + return license_id + + +def is_license_id_not_applicable(license_id): + not_applicable_list = ['na', 'n/a', ] + if license_id.lower() in not_applicable_list: + return True + return False + + +def register_form_clean_birthdate(self): + date = self.cleaned_data['birthdate'] + if not date: + return date + if date >= datetime.date.today(): +~~ raise django.forms.ValidationError(_('Enter an accurate birthdate.')) + return date + + +def register_form_clean_phone_number(self): + phone_number = self.cleaned_data['phone_number'] + if not phone_number: + return phone_number + phone_number = RE_NON_DECIMAL.sub('', phone_number) + if phone_number.startswith('1'): + phone_number = phone_number[1:] + if len(phone_number) != 10: +~~ raise django.forms.ValidationError( + _('Enter an accurate phone number including area code.')) + return phone_number + + +def register_form_clean_ssn(self): + ssn = self.cleaned_data['ssn'] + if not ssn: + return ssn + if len(ssn) != 4: +~~ raise django.forms.ValidationError( + _('Enter the last 4 digits of your social security number.')) + try: + int(ssn) + except ValueError: +~~ raise django.forms.ValidationError(_('Enter only digits.')) + return ssn + + +def validate_date_generator(min_value): + min_value = dateutil.parser.parse(min_value).date() + + def validate_date(date): + if date < min_value: +~~ raise django.forms.ValidationError( + _('Date must be later than %(date)s.') % + {'date': min_value.strftime('%m/%d/%Y'), }, + code='minimum') + + return validate_date + + +def register_form_generator(conf): + fieldsets = [] + fields = collections.OrderedDict() + for index, fieldset_def in enumerate(conf['fieldsets']): + fieldset_title = _(fieldset_def['title']) + fieldset_fields = fieldset_def['fields'] + + if not fieldset_fields: + continue + fieldset = (unicode(index), {'legend': fieldset_title, 'fields': []}, ) + + has_booleans = False + + for field_def in fieldset_def['fields']: + field_name = field_def['field_name'] + field_type = field_def.get('type') + label = _(field_def['human_name']) or '' + + +## ... source file abbreviated to get to ValidationError examples ... + + + widget=django.forms.RadioSelect) + birthdate = django.forms.DateField( + label=_('Birthdate'), + widget=django.forms.DateInput( + attrs={'placeholder': '__/__/____', 'class': 'date',})) + agree_to_tos = django.forms.BooleanField(label='', widget=django.forms.widgets.CheckboxInput(attrs={'required': 'required', })) + + def clean_email(self): + email = self.cleaned_data['email'] + if settings.DISABLE_EMAIL_VALIDATION: + logger.warning( + 'Email validation disabled: DISABLE_EMAIL_VALIDATION is set') + return email + if not hasattr(settings, 'MAILGUN_PUBLIC_API_KEY'): + logger.warning( + 'Cannot validate email: MAILGUN_PUBLIC_API_KEY not set') + return email + r = requests.get( + 'https://api.mailgun.net/v2/address/validate', + data={'address': email, }, + auth=('api', settings.MAILGUN_PUBLIC_API_KEY)) + if r.status_code == 200: + if r.json()['is_valid']: + return email + logger.warning('Cannot validate email: {}'.format(r.text)) +~~ raise django.forms.ValidationError(_('Enter a valid email.')) + + +class EmailNextOfKinForm(django.forms.Form): + to = MultiEmailField(label=_('To'), max_length=300, help_text=_('Enter one or more emails separated by commas.')) + subject = django.forms.CharField(label=_('Subject'), max_length=250) + body = django.forms.CharField(label=_('Body'), widget=django.forms.widgets.Textarea()) + + def clean_to(self): + emails = self.cleaned_data['to'] + if settings.DISABLE_EMAIL_VALIDATION: + logger.warning('Email validation disabled: DISABLE_EMAIL_VALIDATION is set') + return emails + if not hasattr(settings, 'MAILGUN_PUBLIC_API_KEY'): + logger.warning('Cannot validate email: MAILGUN_PUBLIC_API_KEY not set') + return emails + valid_emails = [] + invalid_emails = [] + for email in emails: + r = requests.get('https://api.mailgun.net/v2/address/validate', + data={'address': email, }, + auth=('api', settings.MAILGUN_PUBLIC_API_KEY)) + if r.status_code == 200 and r.json()['is_valid']: + valid_emails.append(email) + else: + logger.warning('Cannot validate email: {}'.format(r.text)) + invalid_emails.append(email) + if invalid_emails: +~~ raise django.forms.ValidationError(_('Enter valid email addresses.')) + else: + return valid_emails + + + +## ... source file continues with no further ValidationError examples... + +``` + diff --git a/content/pages/examples/django/django-shortcuts-get-list-or-404.markdown b/content/pages/examples/django/django-shortcuts-get-list-or-404.markdown new file mode 100644 index 000000000..70a07e08a --- /dev/null +++ b/content/pages/examples/django/django-shortcuts-get-list-or-404.markdown @@ -0,0 +1,125 @@ +title: django.shortcuts get_list_or_404 Example Code +category: page +slug: django-shortcuts-get-list-or-404-examples +sortorder: 500011345 +toc: False +sidebartitle: django.shortcuts get_list_or_404 +meta: Python example code for the get_list_or_404 callable from the django.shortcuts module of the Django project. + + +get_list_or_404 is a callable within the django.shortcuts module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / admin / placeholderadmin.py**](https://github.com/divio/django-cms/blob/develop/cms/admin/placeholderadmin.py) + +```python +# placeholderadmin.py +import uuid +import warnings + +from django.conf.urls import url +from django.contrib.admin.helpers import AdminForm +from django.contrib.admin.utils import get_deleted_objects +from django.core.exceptions import PermissionDenied +from django.db import router, transaction +from django.http import ( + HttpResponse, + HttpResponseBadRequest, + HttpResponseForbidden, + HttpResponseNotFound, + HttpResponseRedirect, +) +~~from django.shortcuts import get_list_or_404, get_object_or_404, render +from django.template.response import TemplateResponse +from django.utils.decorators import method_decorator +from django.utils.encoding import force_text +from django.utils import translation +from django.utils.translation import ugettext as _ +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.decorators.http import require_POST + +from six.moves.urllib.parse import parse_qsl, urlparse + +from six import get_unbound_function, get_method_function + +from cms import operations +from cms.admin.forms import PluginAddValidationForm +from cms.constants import SLUG_REGEXP +from cms.exceptions import PluginLimitReached +from cms.models.placeholdermodel import Placeholder +from cms.models.placeholderpluginmodel import PlaceholderReference +from cms.models.pluginmodel import CMSPlugin +from cms.plugin_pool import plugin_pool +from cms.signals import pre_placeholder_operation, post_placeholder_operation +from cms.toolbar.utils import get_plugin_tree_as_json +from cms.utils import copy_plugins, get_current_site +from cms.utils.compat import DJANGO_2_0 + + +## ... source file abbreviated to get to get_list_or_404 examples ... + + + operation=operation, + request=request, + language=self._get_operation_language(request), + token=token, + origin=self._get_operation_origin(request), + **kwargs + ) + return token + + def _send_post_placeholder_operation(self, request, operation, token, **kwargs): + if not request.GET.get('cms_path'): + return + + post_placeholder_operation.send( + sender=self.__class__, + operation=operation, + request=request, + language=self._get_operation_language(request), + token=token, + origin=self._get_operation_origin(request), + **kwargs + ) + + def _get_plugin_from_id(self, plugin_id): + queryset = CMSPlugin.objects.values_list('plugin_type', flat=True) +~~ plugin_type = get_list_or_404(queryset, pk=plugin_id)[0] + plugin_class = plugin_pool.get_plugin(plugin_type) + real_queryset = plugin_class.get_render_queryset().select_related('parent', 'placeholder') + return get_object_or_404(real_queryset, pk=plugin_id) + + def get_urls(self): + info = "%s_%s" % (self.model._meta.app_label, self.model._meta.model_name) + pat = lambda regex, fn: url(regex, self.admin_site.admin_view(fn), name='%s_%s' % (info, fn.__name__)) + url_patterns = [ + pat(r'copy-plugins/$', self.copy_plugins), + pat(r'add-plugin/$', self.add_plugin), + pat(r'edit-plugin/(%s)/$' % SLUG_REGEXP, self.edit_plugin), + pat(r'delete-plugin/(%s)/$' % SLUG_REGEXP, self.delete_plugin), + pat(r'clear-placeholder/(%s)/$' % SLUG_REGEXP, self.clear_placeholder), + pat(r'move-plugin/$', self.move_plugin), + ] + return url_patterns + super(PlaceholderAdminMixin, self).get_urls() + + def has_add_plugin_permission(self, request, placeholder, plugin_type): + return placeholder.has_add_plugin_permission(request.user, plugin_type) + + def has_change_plugin_permission(self, request, plugin): + placeholder = plugin.placeholder + return placeholder.has_change_plugin_permission(request.user, plugin) + + + +## ... source file continues with no further get_list_or_404 examples... + +``` + diff --git a/content/pages/examples/django/django-shortcuts-get-object-or-404.markdown b/content/pages/examples/django/django-shortcuts-get-object-or-404.markdown new file mode 100644 index 000000000..529114790 --- /dev/null +++ b/content/pages/examples/django/django-shortcuts-get-object-or-404.markdown @@ -0,0 +1,1530 @@ +title: django.shortcuts get_object_or_404 Example Code +category: page +slug: django-shortcuts-get-object-or-404-examples +sortorder: 500011346 +toc: False +sidebartitle: django.shortcuts get_object_or_404 +meta: Python example code for the get_object_or_404 callable from the django.shortcuts module of the Django project. + + +get_object_or_404 is a callable within the django.shortcuts module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / proceedings / views.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/proceedings/views.py) + +```python +# views.py +from django.http import JsonResponse +~~from django.shortcuts import render, get_object_or_404 +from django.views.decorators.http import require_POST + +from conferences.utilities import validate_chair_access +from proceedings.forms import UpdateVolumeForm +from proceedings.models import CameraReady + + +@require_POST +def update_volume(request, camera_id): +~~ camera = get_object_or_404(CameraReady, id=camera_id) + validate_chair_access(request.user, camera.submission.conference) + form = UpdateVolumeForm(request.POST, instance=camera) + if form.is_valid(): + form.save() + return JsonResponse(status=200, data={}) + return JsonResponse(status=500, data={}) + + + +## ... source file continues with no further get_object_or_404 examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / admin / placeholderadmin.py**](https://github.com/divio/django-cms/blob/develop/cms/admin/placeholderadmin.py) + +```python +# placeholderadmin.py +import uuid +import warnings + +from django.conf.urls import url +from django.contrib.admin.helpers import AdminForm +from django.contrib.admin.utils import get_deleted_objects +from django.core.exceptions import PermissionDenied +from django.db import router, transaction +from django.http import ( + HttpResponse, + HttpResponseBadRequest, + HttpResponseForbidden, + HttpResponseNotFound, + HttpResponseRedirect, +) +~~from django.shortcuts import get_list_or_404, get_object_or_404, render +from django.template.response import TemplateResponse +from django.utils.decorators import method_decorator +from django.utils.encoding import force_text +from django.utils import translation +from django.utils.translation import ugettext as _ +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.decorators.http import require_POST + +from six.moves.urllib.parse import parse_qsl, urlparse + +from six import get_unbound_function, get_method_function + +from cms import operations +from cms.admin.forms import PluginAddValidationForm +from cms.constants import SLUG_REGEXP +from cms.exceptions import PluginLimitReached +from cms.models.placeholdermodel import Placeholder +from cms.models.placeholderpluginmodel import PlaceholderReference +from cms.models.pluginmodel import CMSPlugin +from cms.plugin_pool import plugin_pool +from cms.signals import pre_placeholder_operation, post_placeholder_operation +from cms.toolbar.utils import get_plugin_tree_as_json +from cms.utils import copy_plugins, get_current_site +from cms.utils.compat import DJANGO_2_0 + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + token=token, + origin=self._get_operation_origin(request), + **kwargs + ) + return token + + def _send_post_placeholder_operation(self, request, operation, token, **kwargs): + if not request.GET.get('cms_path'): + return + + post_placeholder_operation.send( + sender=self.__class__, + operation=operation, + request=request, + language=self._get_operation_language(request), + token=token, + origin=self._get_operation_origin(request), + **kwargs + ) + + def _get_plugin_from_id(self, plugin_id): + queryset = CMSPlugin.objects.values_list('plugin_type', flat=True) + plugin_type = get_list_or_404(queryset, pk=plugin_id)[0] + plugin_class = plugin_pool.get_plugin(plugin_type) + real_queryset = plugin_class.get_render_queryset().select_related('parent', 'placeholder') +~~ return get_object_or_404(real_queryset, pk=plugin_id) + + def get_urls(self): + info = "%s_%s" % (self.model._meta.app_label, self.model._meta.model_name) + pat = lambda regex, fn: url(regex, self.admin_site.admin_view(fn), name='%s_%s' % (info, fn.__name__)) + url_patterns = [ + pat(r'copy-plugins/$', self.copy_plugins), + pat(r'add-plugin/$', self.add_plugin), + pat(r'edit-plugin/(%s)/$' % SLUG_REGEXP, self.edit_plugin), + pat(r'delete-plugin/(%s)/$' % SLUG_REGEXP, self.delete_plugin), + pat(r'clear-placeholder/(%s)/$' % SLUG_REGEXP, self.clear_placeholder), + pat(r'move-plugin/$', self.move_plugin), + ] + return url_patterns + super(PlaceholderAdminMixin, self).get_urls() + + def has_add_plugin_permission(self, request, placeholder, plugin_type): + return placeholder.has_add_plugin_permission(request.user, plugin_type) + + def has_change_plugin_permission(self, request, plugin): + placeholder = plugin.placeholder + return placeholder.has_change_plugin_permission(request.user, plugin) + + def has_delete_plugin_permission(self, request, plugin): + placeholder = plugin.placeholder + return placeholder.has_delete_plugin_permission(request.user, plugin) + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + + plugin = getattr(plugin_instance, 'saved_object', None) + + if plugin: + plugin.placeholder.mark_as_dirty(plugin.language, clear_cache=False) + + if plugin_instance._operation_token: + tree_order = placeholder.get_plugin_tree_order(plugin.parent_id) + self._send_post_placeholder_operation( + request, + operation=operations.ADD_PLUGIN, + token=plugin_instance._operation_token, + plugin=plugin, + placeholder=plugin.placeholder, + tree_order=tree_order, + ) + return response + + @method_decorator(require_POST) + @xframe_options_sameorigin + @transaction.atomic + def copy_plugins(self, request): + source_placeholder_id = request.POST['source_placeholder_id'] + target_language = request.POST['target_language'] + target_placeholder_id = request.POST['target_placeholder_id'] +~~ source_placeholder = get_object_or_404(Placeholder, pk=source_placeholder_id) +~~ target_placeholder = get_object_or_404(Placeholder, pk=target_placeholder_id) + + if not target_language or not target_language in get_language_list(): + return HttpResponseBadRequest(force_text(_("Language must be set to a supported language!"))) + + copy_to_clipboard = target_placeholder.pk == request.toolbar.clipboard.pk + source_plugin_id = request.POST.get('source_plugin_id', None) + + if copy_to_clipboard and source_plugin_id: + new_plugin = self._copy_plugin_to_clipboard( + request, + source_placeholder, + target_placeholder, + ) + new_plugins = [new_plugin] + elif copy_to_clipboard: + new_plugin = self._copy_placeholder_to_clipboard( + request, + source_placeholder, + target_placeholder, + ) + new_plugins = [new_plugin] + else: + new_plugins = self._add_plugins_from_placeholder( + request, + source_placeholder, + target_placeholder, + ) + data = get_plugin_tree_as_json(request, new_plugins) + return HttpResponse(data, content_type='application/json') + + def _copy_plugin_to_clipboard(self, request, source_placeholder, target_placeholder): + source_language = request.POST['source_language'] + source_plugin_id = request.POST.get('source_plugin_id') + target_language = request.POST['target_language'] + +~~ source_plugin = get_object_or_404( + CMSPlugin, + pk=source_plugin_id, + language=source_language, + ) + + old_plugins = ( + CMSPlugin + .get_tree(parent=source_plugin) + .filter(placeholder=source_placeholder) + .order_by('path') + ) + + if not self.has_copy_plugins_permission(request, old_plugins): + message = _('You do not have permission to copy these plugins.') + raise PermissionDenied(force_text(message)) + + target_placeholder.clear() + + plugin_pairs = copy_plugins.copy_plugins_to( + old_plugins, + to_placeholder=target_placeholder, + to_language=target_language, + ) + return plugin_pairs[0][0] + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + + if placeholder != source_placeholder: + try: + template = self.get_placeholder_template(request, placeholder) + has_reached_plugin_limit(placeholder, plugin.plugin_type, + target_language, template=template) + except PluginLimitReached as er: + return HttpResponseBadRequest(er) + + exclude_from_order_check = ['__COPY__', str(plugin.pk)] + ordered_plugin_ids = [int(pk) for pk in order if pk not in exclude_from_order_check] + plugins_in_tree_count = ( + placeholder + .get_plugins(target_language) + .filter(parent=parent_id, pk__in=ordered_plugin_ids) + .count() + ) + + if len(ordered_plugin_ids) != plugins_in_tree_count: + message = _('order parameter references plugins in different trees') + return HttpResponseBadRequest(force_text(message)) + + move_a_plugin = not move_a_copy and not move_to_clipboard + + if parent_id and plugin.parent_id != parent_id: +~~ target_parent = get_object_or_404(CMSPlugin, pk=parent_id) + + if move_a_plugin and target_parent.placeholder_id != placeholder.pk: + return HttpResponseBadRequest(force_text( + _('parent must be in the same placeholder'))) + + if move_a_plugin and target_parent.language != target_language: + return HttpResponseBadRequest(force_text( + _('parent must be in the same language as ' + 'plugin_language'))) + elif parent_id: + target_parent = plugin.parent + else: + target_parent = None + + new_plugin = None + fetch_tree = False + + if move_a_copy and plugin.plugin_type == "PlaceholderPlugin": + new_plugins = self._paste_placeholder( + request, + plugin=plugin, + target_language=target_language, + target_placeholder=placeholder, + tree_order=order, + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + return HttpResponseRedirect(admin_reverse('index', current_app=self.admin_site.name)) + + plugin_name = force_text(plugin.get_plugin_class().name) + + if perms_needed or protected: + title = _("Cannot delete %(name)s") % {"name": plugin_name} + else: + title = _("Are you sure?") + context = { + "title": title, + "object_name": plugin_name, + "object": plugin, + "deleted_objects": deleted_objects, + "perms_lacking": perms_needed, + "protected": protected, + "opts": opts, + "app_label": opts.app_label, + } + request.current_app = self.admin_site.name + return TemplateResponse( + request, "admin/cms/page/plugin/delete_confirmation.html", context + ) + + @xframe_options_sameorigin + def clear_placeholder(self, request, placeholder_id): +~~ placeholder = get_object_or_404(Placeholder, pk=placeholder_id) + language = request.GET.get('language') + + if placeholder.pk == request.toolbar.clipboard.pk: + placeholder.clear(language) + return HttpResponseRedirect(admin_reverse('index', current_app=self.admin_site.name)) + + if not self.has_clear_placeholder_permission(request, placeholder, language): + return HttpResponseForbidden(force_text(_("You do not have permission to clear this placeholder"))) + + opts = Placeholder._meta + using = router.db_for_write(Placeholder) + plugins = placeholder.get_plugins_list(language) + + if DJANGO_2_0: + get_deleted_objects_additional_kwargs = { + 'opts': opts, + 'using': using, + 'user': request.user, + } + else: + get_deleted_objects_additional_kwargs = {'request': request} + deleted_objects, __, perms_needed, protected = get_deleted_objects( + plugins, admin_site=self.admin_site, + **get_deleted_objects_additional_kwargs + + +## ... source file continues with no further get_object_or_404 examples... + +``` + + +## Example 3 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / views.py**](https://github.com/divio/django-filer/blob/develop/filer/./views.py) + +```python +# views.py +from __future__ import absolute_import, unicode_literals + +from django.http import Http404 +~~from django.shortcuts import get_object_or_404, redirect + +from .models import File + + +def canonical(request, uploaded_at, file_id): +~~ filer_file = get_object_or_404(File, pk=file_id, is_public=True) + if (not filer_file.file or int(uploaded_at) != filer_file.canonical_time): + raise Http404('No %s matches the given query.' % File._meta.object_name) + return redirect(filer_file.url) + + + +## ... source file continues with no further get_object_or_404 examples... + +``` + + +## Example 4 from django-flexible-subscriptions +[django-flexible-subscriptions](https://github.com/studybuffalo/django-flexible-subscriptions) +([project documentation](https://django-flexible-subscriptions.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-flexible-subscriptions/)) +provides boilerplate code for adding subscription and recurrent billing +to [Django](/django.html) web applications. Various payment providers +can be added on the back end to run the transactions. + +The django-flexible-subscriptions project is open sourced under the +[GNU General Public License v3.0](https://github.com/studybuffalo/django-flexible-subscriptions/blob/master/LICENSE). + +[**django-flexible-subscriptions / subscriptions / views.py**](https://github.com/studybuffalo/django-flexible-subscriptions/blob/master/subscriptions/./views.py) + +```python +# views.py +from copy import copy + +from django.contrib import messages +from django.contrib.auth import get_user_model +from django.contrib.auth.mixins import ( + LoginRequiredMixin, PermissionRequiredMixin +) +from django.contrib.messages.views import SuccessMessageMixin +from django.forms import HiddenInput +from django.forms.models import inlineformset_factory +from django.http import HttpResponseRedirect +from django.http.response import HttpResponseNotAllowed, HttpResponseNotFound +~~from django.shortcuts import get_object_or_404 +from django.template.response import TemplateResponse +from django.urls import reverse_lazy +from django.utils import timezone + +from subscriptions import models, forms, abstract + + +class DashboardView(PermissionRequiredMixin, abstract.TemplateView): + permission_required = 'subscriptions.subscriptions' + raise_exception = True + template_name = 'subscriptions/dashboard.html' + + +class TagListView(PermissionRequiredMixin, abstract.ListView): + model = models.PlanTag + permission_required = 'subscriptions.subscriptions' + raise_exception = True + context_object_name = 'tags' + template_name = 'subscriptions/tag_list.html' + + +class TagCreateView( + PermissionRequiredMixin, SuccessMessageMixin, abstract.CreateView +): + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + +class PlanListDetailListView(PermissionRequiredMixin, abstract.DetailView): + model = models.PlanList + pk_url_kwarg = 'plan_list_id' + permission_required = 'subscriptions.subscriptions' + raise_exception = True + context_object_name = 'plan_list' + template_name = 'subscriptions/plan_list_detail_list.html' + + +class PlanListDetailCreateView( + PermissionRequiredMixin, SuccessMessageMixin, abstract.CreateView +): + model = models.PlanListDetail + fields = [ + 'plan', 'plan_list', 'html_content', 'subscribe_button_text', 'order' + ] + permission_required = 'subscriptions.subscriptions' + raise_exception = True + success_message = 'Subscription plan successfully added to plan list' + template_name = 'subscriptions/plan_list_detail_create.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + +~~ context['plan_list'] = get_object_or_404( + models.PlanList, id=self.kwargs.get('plan_list_id', None) + ) + + return context + + def get_success_url(self): + return reverse_lazy( + 'dfs_plan_list_detail_list', + kwargs={'plan_list_id': self.kwargs['plan_list_id']}, + ) + + +class PlanListDetailUpdateView( + PermissionRequiredMixin, SuccessMessageMixin, abstract.UpdateView +): + model = models.PlanListDetail + permission_required = 'subscriptions.subscriptions' + raise_exception = True + fields = [ + 'plan', 'plan_list', 'html_content', 'subscribe_button_text', 'order' + ] + success_message = 'Plan list details successfully updated' + pk_url_kwarg = 'plan_list_detail_id' + template_name = 'subscriptions/plan_list_detail_update.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + +~~ context['plan_list'] = get_object_or_404( + models.PlanList, id=self.kwargs.get('plan_list_id', None) + ) + + return context + + def get_success_url(self): + return reverse_lazy( + 'dfs_plan_list_detail_list', + kwargs={'plan_list_id': self.kwargs['plan_list_id']}, + ) + + +class PlanListDetailDeleteView(PermissionRequiredMixin, abstract.DeleteView): + model = models.PlanListDetail + permission_required = 'subscriptions.subscriptions' + raise_exception = True + context_object_name = 'plan_list_detail' + pk_url_kwarg = 'plan_list_detail_id' + success_message = 'Subscription plan successfully removed from plan list' + template_name = 'subscriptions/plan_list_detail_delete.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + +~~ context['plan_list'] = get_object_or_404( + models.PlanList, id=self.kwargs.get('plan_list_id', None) + ) + + return context + + def delete(self, request, *args, **kwargs): + messages.success(self.request, self.success_message) + return super(PlanListDetailDeleteView, self).delete( + request, *args, **kwargs + ) + + def get_success_url(self): + return reverse_lazy( + 'dfs_plan_list_detail_list', + kwargs={'plan_list_id': self.kwargs['plan_list_id']}, + ) + + +class SubscribeList(abstract.TemplateView): + context_object_name = 'plan_list' + template_name = 'subscriptions/subscribe_list.html' + + def get(self, request, *args, **kwargs): + plan_list = models.PlanList.objects.filter(active=True).first() + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + self.get_context_data(plan_list=plan_list, details=details) + ) + + return response + + return HttpResponseNotFound('No subscription plans are available') + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + context['plan_list'] = kwargs['plan_list'] + context['details'] = kwargs['details'] + + return context + + +class SubscribeView(LoginRequiredMixin, abstract.TemplateView): + confirmation = False + payment_form = forms.PaymentForm + subscription_plan = None + success_url = 'dfs_subscribe_thank_you' + template_preview = 'subscriptions/subscribe_preview.html' + template_confirmation = 'subscriptions/subscribe_confirmation.html' + + def get_object(self): +~~ return get_object_or_404( + models.SubscriptionPlan, id=self.request.POST.get('plan_id', None) + ) + + def get_context_data(self, **kwargs): + context = super(SubscribeView, self).get_context_data(**kwargs) + + context['confirmation'] = self.confirmation + + context['plan'] = self.subscription_plan + + return context + + def get_template_names(self): + conf_templates = [self.template_confirmation] + prev_templates = [self.template_preview] + + return conf_templates if self.confirmation else prev_templates + + def get_success_url(self, **kwargs): + return reverse_lazy(self.success_url, kwargs=kwargs) + + def get(self, request, *args, **kwargs): + return HttpResponseNotAllowed(['POST']) + + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + try: + return models.SubscriptionTransaction.objects.get( + id=self.kwargs['transaction_id'], + user=self.request.user, + ) + except models.SubscriptionTransaction.DoesNotExist: + return None + + def get_context_data(self, **kwargs): + context = super(SubscribeThankYouView, self).get_context_data(**kwargs) + + context[self.context_object_name] = self.get_object() + + return context + + +class SubscribeCancelView(LoginRequiredMixin, abstract.DetailView): + model = models.UserSubscription + context_object_name = 'subscription' + pk_url_kwarg = 'subscription_id' + success_message = 'Subscription successfully cancelled' + success_url = 'dfs_subscribe_user_list' + template_name = 'subscriptions/subscribe_cancel.html' + + def get_object(self, queryset=None): +~~ return get_object_or_404( + self.model, + user=self.request.user, + id=self.kwargs['subscription_id'], + ) + + def get_success_url(self): + return reverse_lazy(self.success_url) + + def post(self, request, *args, **kwargs): # pylint: disable=unused-argument + subscription = self.get_object() + subscription.date_billing_end = copy(subscription.date_billing_next) + subscription.date_billing_next = None + subscription.cancelled = True + subscription.save() + + messages.success(self.request, self.success_message) + + return HttpResponseRedirect(self.get_success_url()) + + + +## ... source file continues with no further get_object_or_404 examples... + +``` + + +## Example 5 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / admin.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./admin.py) + +```python +# admin.py +from collections import OrderedDict + +from django import forms +from django.conf import settings +from django.contrib import admin, messages +from django.contrib.admin.widgets import FilteredSelectMultiple +from django.contrib.auth import get_user_model +~~from django.shortcuts import get_object_or_404, redirect, render +from django.urls import reverse, path +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import gettext +from guardian.forms import GroupObjectPermissionsForm, UserObjectPermissionsForm +from django.contrib.auth.models import Group +from guardian.shortcuts import (get_group_perms, get_groups_with_perms, get_perms_for_model, get_user_perms, + get_users_with_perms) + + +class AdminUserObjectPermissionsForm(UserObjectPermissionsForm): + + def get_obj_perms_field_widget(self): + return FilteredSelectMultiple(_("Permissions"), False) + + +class AdminGroupObjectPermissionsForm(GroupObjectPermissionsForm): + + def get_obj_perms_field_widget(self): + return FilteredSelectMultiple(_("Permissions"), False) + + +class GuardedModelAdminMixin: + change_form_template = \ + 'admin/guardian/model/change_form.html' + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + ] + urls = myurls + urls + return urls + + def get_obj_perms_base_context(self, request, obj): + context = self.admin_site.each_context(request) + context.update({ + 'adminform': {'model_admin': self}, + 'media': self.media, + 'object': obj, + 'app_label': self.model._meta.app_label, + 'opts': self.model._meta, + 'original': str(obj), + 'has_change_permission': self.has_change_permission(request, obj), + 'model_perms': get_perms_for_model(obj), + 'title': _("Object permissions"), + }) + return context + + def obj_perms_manage_view(self, request, object_pk): + if not self.has_change_permission(request, None): + post_url = reverse('admin:index', current_app=self.admin_site.name) + return redirect(post_url) + + from django.contrib.admin.utils import unquote +~~ obj = get_object_or_404(self.get_queryset( + request), pk=unquote(object_pk)) + users_perms = OrderedDict( + sorted( + get_users_with_perms(obj, attach_perms=True, + with_group_users=False).items(), + key=lambda user: getattr( + user[0], get_user_model().USERNAME_FIELD) + ) + ) + + groups_perms = OrderedDict( + sorted( + get_groups_with_perms(obj, attach_perms=True).items(), + key=lambda group: group[0].name + ) + ) + + if request.method == 'POST' and 'submit_manage_user' in request.POST: + user_form = self.get_obj_perms_user_select_form( + request)(request.POST) + group_form = self.get_obj_perms_group_select_form( + request)(request.POST) + info = ( + self.admin_site.name, + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + return redirect(url) + else: + user_form = self.get_obj_perms_user_select_form(request)() + group_form = self.get_obj_perms_group_select_form(request)() + + context = self.get_obj_perms_base_context(request, obj) + context['users_perms'] = users_perms + context['groups_perms'] = groups_perms + context['user_form'] = user_form + context['group_form'] = group_form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_template(), context) + + def get_obj_perms_manage_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage.html' + return self.obj_perms_manage_template + + def obj_perms_manage_user_view(self, request, object_pk, user_id): + if not self.has_change_permission(request, None): + post_url = reverse('admin:index', current_app=self.admin_site.name) + return redirect(post_url) + +~~ user = get_object_or_404(get_user_model(), pk=user_id) +~~ obj = get_object_or_404(self.get_queryset(request), pk=object_pk) + form_class = self.get_obj_perms_manage_user_form(request) + form = form_class(user, obj, request.POST or None) + + if request.method == 'POST' and form.is_valid(): + form.save_obj_perms() + msg = gettext("Permissions saved.") + messages.success(request, msg) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + url = reverse( + '%s:%s_%s_permissions_manage_user' % info, + args=[obj.pk, user.pk] + ) + return redirect(url) + + context = self.get_obj_perms_base_context(request, obj) + context['user_obj'] = user + context['user_perms'] = get_user_perms(user, obj) + context['form'] = form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_user_template(), context) + + def get_obj_perms_manage_user_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage_user.html' + return self.obj_perms_manage_user_template + + def get_obj_perms_user_select_form(self, request): + return UserManage + + def get_obj_perms_group_select_form(self, request): + return GroupManage + + def get_obj_perms_manage_user_form(self, request): + return AdminUserObjectPermissionsForm + + def obj_perms_manage_group_view(self, request, object_pk, group_id): + if not self.has_change_permission(request, None): + post_url = reverse('admin:index', current_app=self.admin_site.name) + return redirect(post_url) + +~~ group = get_object_or_404(Group, id=group_id) +~~ obj = get_object_or_404(self.get_queryset(request), pk=object_pk) + form_class = self.get_obj_perms_manage_group_form(request) + form = form_class(group, obj, request.POST or None) + + if request.method == 'POST' and form.is_valid(): + form.save_obj_perms() + msg = gettext("Permissions saved.") + messages.success(request, msg) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + url = reverse( + '%s:%s_%s_permissions_manage_group' % info, + args=[obj.pk, group.id] + ) + return redirect(url) + + context = self.get_obj_perms_base_context(request, obj) + context['group_obj'] = group + context['group_perms'] = get_group_perms(group, obj) + context['form'] = form + + request.current_app = self.admin_site.name + + +## ... source file continues with no further get_object_or_404 examples... + +``` + + +## Example 6 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / generics.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./generics.py) + +```python +# generics.py +from django.core.exceptions import ValidationError +from django.db.models.query import QuerySet +from django.http import Http404 +~~from django.shortcuts import get_object_or_404 as _get_object_or_404 + +from rest_framework import mixins, views +from rest_framework.settings import api_settings + + +~~def get_object_or_404(queryset, *filter_args, **filter_kwargs): + try: + return _get_object_or_404(queryset, *filter_args, **filter_kwargs) + except (TypeError, ValueError, ValidationError): + raise Http404 + + +class GenericAPIView(views.APIView): + queryset = None + serializer_class = None + + lookup_field = 'pk' + lookup_url_kwarg = None + + filter_backends = api_settings.DEFAULT_FILTER_BACKENDS + + pagination_class = api_settings.DEFAULT_PAGINATION_CLASS + + def get_queryset(self): + assert self.queryset is not None, ( + "'%s' should either include a `queryset` attribute, " + "or override the `get_queryset()` method." + % self.__class__.__name__ + ) + + queryset = self.queryset + if isinstance(queryset, QuerySet): + queryset = queryset.all() + return queryset + + def get_object(self): + queryset = self.filter_queryset(self.get_queryset()) + + lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field + + assert lookup_url_kwarg in self.kwargs, ( + 'Expected view %s to be called with a URL keyword argument ' + 'named "%s". Fix your URL conf, or set the `.lookup_field` ' + 'attribute on the view correctly.' % + (self.__class__.__name__, lookup_url_kwarg) + ) + + filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]} +~~ obj = get_object_or_404(queryset, **filter_kwargs) + + self.check_object_permissions(self.request, obj) + + return obj + + def get_serializer(self, *args, **kwargs): + serializer_class = self.get_serializer_class() + kwargs.setdefault('context', self.get_serializer_context()) + return serializer_class(*args, **kwargs) + + def get_serializer_class(self): + assert self.serializer_class is not None, ( + "'%s' should either include a `serializer_class` attribute, " + "or override the `get_serializer_class()` method." + % self.__class__.__name__ + ) + + return self.serializer_class + + def get_serializer_context(self): + return { + 'request': self.request, + 'format': self.format_kwarg, + 'view': self + + +## ... source file continues with no further get_object_or_404 examples... + +``` + + +## Example 7 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / views.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./views.py) + +```python +# views.py +import re +import six +from collections import Counter + +try: + from django.urls import reverse_lazy +except ImportError: + from django.core.urlresolvers import reverse_lazy + +import django +from django.db import DatabaseError +from django.db.models import Count +from django.forms.models import model_to_dict +from django.http import HttpResponse, JsonResponse, HttpResponseRedirect, Http404 +~~from django.shortcuts import get_object_or_404, render +from django.views.decorators.http import require_POST +from django.utils.decorators import method_decorator +from django.views.generic import ListView +from django.views.generic.base import View +from django.views.generic.edit import CreateView, DeleteView +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.core.exceptions import ImproperlyConfigured +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.auth.views import LoginView + +from explorer import app_settings +from explorer.connections import connections +from explorer.exporters import get_exporter_class +from explorer.forms import QueryForm +from explorer.models import Query, QueryLog, MSG_FAILED_BLACKLIST +from explorer.tasks import execute_query +from explorer.utils import ( + url_get_rows, + url_get_query_id, + url_get_log_id, + url_get_params, + safe_login_prompt, + fmt_sql, + allowed_query_pks, + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + +def _export(request, query, download=True): + format = request.GET.get('format', 'csv') + exporter_class = get_exporter_class(format) + query.params = url_get_params(request) + delim = request.GET.get('delim') + exporter = exporter_class(query) + try: + output = exporter.get_output(delim=delim) + except DatabaseError as e: + msg = "Error executing query %s: %s" % (query.title, e) + return HttpResponse(msg, status=500) + response = HttpResponse(output, content_type=exporter.content_type) + if download: + response['Content-Disposition'] = 'attachment; filename="%s"' % ( + exporter.get_filename() + ) + return response + + +class DownloadQueryView(PermissionRequiredMixin, View): + + permission_required = 'view_permission' + + def get(self, request, query_id, *args, **kwargs): +~~ query = get_object_or_404(Query, pk=query_id) + return _export(request, query) + + +class DownloadFromSqlView(PermissionRequiredMixin, View): + + permission_required = 'view_permission' + + def post(self, request, *args, **kwargs): + sql = request.POST.get('sql') + connection = request.POST.get('connection') + query = Query(sql=sql, connection=connection, title='') + ql = query.log(request.user) + query.title = 'Playground - %s' % ql.id + return _export(request, query) + + +class StreamQueryView(PermissionRequiredMixin, View): + + permission_required = 'view_permission' + + def get(self, request, query_id, *args, **kwargs): +~~ query = get_object_or_404(Query, pk=query_id) + return _export(request, query, download=False) + + +class EmailCsvQueryView(PermissionRequiredMixin, View): + + permission_required = 'view_permission' + + def post(self, request, query_id, *args, **kwargs): + if request.is_ajax(): + email = request.POST.get('email', None) + if email: + execute_query.delay(query_id, email) + return JsonResponse({'message': 'message was sent successfully'}) + return JsonResponse({}, status=403) + + +class SchemaView(PermissionRequiredMixin, View): + permission_required = 'change_permission' + + @method_decorator(xframe_options_sameorigin) + def dispatch(self, *args, **kwargs): + return super(SchemaView, self).dispatch(*args, **kwargs) + + def get(self, request, *args, **kwargs): + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + +class CreateQueryView(PermissionRequiredMixin, ExplorerContextMixin, CreateView): + + permission_required = 'change_permission' + + def form_valid(self, form): + form.instance.created_by_user = self.request.user + return super(CreateQueryView, self).form_valid(form) + + form_class = QueryForm + template_name = 'explorer/query.html' + + +class DeleteQueryView(PermissionRequiredMixin, ExplorerContextMixin, DeleteView): + + permission_required = 'change_permission' + model = Query + success_url = reverse_lazy("explorer_index") + + +class PlayQueryView(PermissionRequiredMixin, ExplorerContextMixin, View): + + permission_required = 'change_permission' + + def get(self, request): + if url_get_query_id(request): +~~ query = get_object_or_404(Query, pk=url_get_query_id(request)) + return self.render_with_sql(request, query, run_query=False) + + if url_get_log_id(request): +~~ log = get_object_or_404(QueryLog, pk=url_get_log_id(request)) + query = Query(sql=log.sql, title="Playground", connection=log.connection) + return self.render_with_sql(request, query) + + return self.render() + + def post(self, request): + sql = request.POST.get('sql') + show = url_get_show(request) + query = Query(sql=sql, title="Playground", connection=request.POST.get('connection')) + passes_blacklist, failing_words = query.passes_blacklist() + error = MSG_FAILED_BLACKLIST % ', '.join(failing_words) if not passes_blacklist else None + run_query = not bool(error) if show else False + return self.render_with_sql(request, query, run_query=run_query, error=error) + + def render(self): + return self.render_template('explorer/play.html', {'title': 'Playground', 'form': QueryForm()}) + + def render_with_sql(self, request, query, run_query=True, error=None): + rows = url_get_rows(request) + fullscreen = url_get_fullscreen(request) + template = 'fullscreen' if fullscreen else 'play' + form = QueryForm(request.POST if len(request.POST) else None, instance=query) + return self.render_template('explorer/%s.html' % template, query_viewmodel(request.user, + query, + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + show = url_get_show(request) + rows = url_get_rows(request) + vm = query_viewmodel(request.user, query, form=form, run_query=show, rows=rows) + fullscreen = url_get_fullscreen(request) + template = 'fullscreen' if fullscreen else 'query' + return self.render_template('explorer/%s.html' % template, vm) + + def post(self, request, query_id): + if not app_settings.EXPLORER_PERMISSION_CHANGE(request.user): + return HttpResponseRedirect( + reverse_lazy('query_detail', kwargs={'query_id': query_id}) + ) + show = url_get_show(request) + query, form = QueryView.get_instance_and_form(request, query_id) + success = form.is_valid() and form.save() + vm = query_viewmodel(request.user, + query, + form=form, + run_query=show, + rows=url_get_rows(request), + message="Query saved." if success else None) + return self.render_template('explorer/query.html', vm) + + @staticmethod + def get_instance_and_form(request, query_id): +~~ query = get_object_or_404(Query, pk=query_id) + query.params = url_get_params(request) + form = QueryForm(request.POST if len(request.POST) else None, instance=query) + return query, form + + +def query_viewmodel(user, query, title=None, form=None, message=None, run_query=True, error=None, rows=app_settings.EXPLORER_DEFAULT_ROWS): + res = None + ql = None + if run_query: + try: + res, ql = query.execute_with_logging(user) + except DatabaseError as e: + error = str(e) + has_valid_results = not error and res and run_query + ret = { + 'tasks_enabled': app_settings.ENABLE_TASKS, + 'params': query.available_params(), + 'title': title, + 'shared': query.shared, + 'query': query, + 'form': form, + 'message': message, + 'error': error, + 'rows': rows, + + +## ... source file continues with no further get_object_or_404 examples... + +``` + + +## Example 8 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / views.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./views.py) + +```python +# views.py +from django.contrib.contenttypes.models import ContentType +~~from django.shortcuts import get_object_or_404 +from django.views.generic.list import ListView + +from taggit.models import Tag, TaggedItem + + +def tagged_object_list(request, slug, queryset, **kwargs): + if callable(queryset): + queryset = queryset() + kwargs["slug"] = slug + tag_list_view = type( + "TagListView", + (TagListMixin, ListView), + {"model": queryset.model, "queryset": queryset}, + ) + return tag_list_view.as_view()(request, **kwargs) + + +class TagListMixin: + tag_suffix = "_tag" + + def dispatch(self, request, *args, **kwargs): + slug = kwargs.pop("slug") +~~ self.tag = get_object_or_404(Tag, slug=slug) + return super().dispatch(request, *args, **kwargs) + + def get_queryset(self, **kwargs): + qs = super().get_queryset(**kwargs) + return qs.filter( + pk__in=TaggedItem.objects.filter( + tag=self.tag, content_type=ContentType.objects.get_for_model(qs.model) + ).values_list("object_id", flat=True) + ) + + def get_template_names(self): + if self.tag_suffix: + self.template_name_suffix = self.tag_suffix + self.template_name_suffix + return super().get_template_names() + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + if "extra_context" not in context: + context["extra_context"] = {} + context["extra_context"]["tag"] = self.tag + return context + + + +## ... source file continues with no further get_object_or_404 examples... + +``` + + +## Example 9 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / forms.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./forms.py) + +```python +# forms.py +__all__ = [ + "UserCreationForm", + "UserUpdateForm", + "WikiSlugField", + "SpamProtectionMixin", + "CreateRootForm", + "MoveForm", + "EditForm", + "SelectWidgetBootstrap", + "TextInputPrepend", + "CreateForm", + "DeleteForm", + "PermissionsForm", + "DirFilterForm", + "SearchForm", +] + +from datetime import timedelta + +from django import forms +from django.apps import apps +from django.contrib.auth import get_user_model +from django.core import validators +from django.core.validators import RegexValidator +from django.forms.widgets import HiddenInput +~~from django.shortcuts import get_object_or_404 +from django.urls import Resolver404, resolve +from django.utils import timezone +from django.utils.safestring import mark_safe +from django.utils.translation import gettext, gettext_lazy as _, pgettext_lazy +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.plugins.base import PluginSettingsFormMixin +from wiki.editors import getEditor + +from .forms_account_handling import UserCreationForm, UserUpdateForm + +validate_slug_numbers = RegexValidator( + r"^[0-9]+$", + _("A 'slug' cannot consist solely of numbers."), + "invalid", + inverse_match=True, +) + + +class WikiSlugField(forms.CharField): + + default_validators = [validators.validate_slug, validate_slug_numbers] + + +## ... source file abbreviated to get to get_object_or_404 examples ... + + + ), + ) + content = forms.CharField( + label=_("Type in some contents"), + help_text=_( + "This is just the initial contents of your article. After creating it, you can use more complex features like adding plugins, meta data, related articles etc..." + ), + required=False, + widget=getEditor().get_widget(), + ) # @UndefinedVariable + + +class MoveForm(forms.Form): + + destination = forms.CharField(label=_("Destination")) + slug = WikiSlugField(max_length=models.URLPath.SLUG_MAX_LENGTH) + redirect = forms.BooleanField( + label=_("Redirect pages"), + help_text=_("Create a redirect page for every moved article?"), + required=False, + ) + + def clean(self): + cd = super().clean() + if cd.get("slug"): +~~ dest_path = get_object_or_404( + models.URLPath, pk=self.cleaned_data["destination"] + ) + cd["slug"] = _clean_slug(cd["slug"], dest_path) + return cd + + +class EditForm(forms.Form, SpamProtectionMixin): + + title = forms.CharField(label=_("Title"),) + content = forms.CharField( + label=_("Contents"), required=False, widget=getEditor().get_widget() + ) # @UndefinedVariable + + summary = forms.CharField( + label=pgettext_lazy("Revision comment", "Summary"), + help_text=_( + "Give a short reason for your edit, which will be stated in the revision log." + ), + required=False, + ) + + current_revision = forms.IntegerField(required=False, widget=forms.HiddenInput()) + + def __init__(self, request, current_revision, *args, **kwargs): + + +## ... source file continues with no further get_object_or_404 examples... + +``` + + +## Example 10 from gadget-board +[gadget-board](https://github.com/mik4el/gadget-board) is a +[Django](/django.html), +[Django REST Framework (DRF)](/django-rest-framework-drf.html) and +[Angular](/angular.html) web application that is open source under the +[Apache2 license](https://github.com/mik4el/gadget-board/blob/master/LICENSE). + +[**gadget-board / web / gadgets / permissions.py**](https://github.com/mik4el/gadget-board/blob/master/web/gadgets/permissions.py) + +```python +# permissions.py +from rest_framework import permissions +~~from django.shortcuts import get_object_or_404 +from .models import Gadget + + +class CanUserAddGadgetData(permissions.BasePermission): + def has_permission(self, request, view): + if request.method in permissions.SAFE_METHODS: + return True + if request.method == "POST": + if request.user.is_authenticated: +~~ gadget = get_object_or_404(Gadget, slug=view.kwargs['gadget_slug']) + if request.user in gadget.users_can_upload.all(): + return True + return False + + def has_object_permission(self, request, view, obj): + return False + + + +## ... source file continues with no further get_object_or_404 examples... + +``` + + +## Example 11 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / views.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/views.py) + +```python +# views.py +from django.http import Http404, HttpResponse +~~from django.shortcuts import get_object_or_404, redirect +from django.urls import reverse + +from wagtail.core import hooks +from wagtail.core.forms import PasswordViewRestrictionForm +from wagtail.core.models import Page, PageViewRestriction, Site + + +def serve(request, path): + site = Site.find_for_request(request) + if not site: + raise Http404 + + path_components = [component for component in path.split('/') if component] + page, args, kwargs = site.root_page.specific.route(request, path_components) + + for fn in hooks.get_hooks('before_serve_page'): + result = fn(page, request, args, kwargs) + if isinstance(result, HttpResponse): + return result + + return page.serve(request, *args, **kwargs) + + +def authenticate_with_password(request, page_view_restriction_id, page_id): +~~ restriction = get_object_or_404(PageViewRestriction, id=page_view_restriction_id) +~~ page = get_object_or_404(Page, id=page_id).specific + + if request.method == 'POST': + form = PasswordViewRestrictionForm(request.POST, instance=restriction) + if form.is_valid(): + restriction.mark_as_passed(request) + + return redirect(form.cleaned_data['return_url']) + else: + form = PasswordViewRestrictionForm(instance=restriction) + + action_url = reverse('wagtailcore_authenticate_with_password', args=[restriction.id, page.id]) + return page.serve_password_required_response(request, form, action_url) + + + +## ... source file continues with no further get_object_or_404 examples... + +``` + diff --git a/content/pages/examples/django/django-shortcuts-redirect.markdown b/content/pages/examples/django/django-shortcuts-redirect.markdown new file mode 100644 index 000000000..31d3af0c3 --- /dev/null +++ b/content/pages/examples/django/django-shortcuts-redirect.markdown @@ -0,0 +1,1115 @@ +title: django.shortcuts redirect Example Code +category: page +slug: django-shortcuts-redirect-examples +sortorder: 500011347 +toc: False +sidebartitle: django.shortcuts redirect +meta: Python example code for the redirect callable from the django.shortcuts module of the Django project. + + +redirect is a callable within the django.shortcuts module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / registration / views.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/registration/views.py) + +```python +# views.py +from django.contrib.auth import get_user_model +from django.contrib.auth.decorators import login_required +~~from django.shortcuts import render, redirect + +from users.models import generate_avatar +from users.forms import PersonalForm, ProfessionalForm, SubscriptionsForm + +User = get_user_model() + + +@login_required +def personal(request): + profile = request.user.profile + if request.method == 'POST': + form = PersonalForm(request.POST, instance=profile) + if form.is_valid(): + form.save() + profile.avatar = generate_avatar(profile) + profile.save() +~~ return redirect('register-professional') + else: + form = PersonalForm(instance=profile) + return render(request, 'registration/personal.html', { + 'form': form + }) + +@login_required +def professional(request): + profile = request.user.profile + if request.method == 'POST': + form = ProfessionalForm(request.POST, instance=profile) + if form.is_valid(): + form.save() +~~ return redirect('register-subscriptions') + else: + form = ProfessionalForm(instance=profile) + return render(request, 'registration/professional.html', { + 'form': form + }) + + +@login_required +def subscriptions(request): + subscriptions = request.user.subscriptions + if request.method == 'POST': + form = SubscriptionsForm(request.POST, instance=subscriptions) + if form.is_valid(): + form.save() + request.user.has_finished_registration = True + request.user.save() +~~ return redirect('home') + else: + form = SubscriptionsForm(instance=subscriptions) + return render(request, 'registration/subscriptions.html', { + 'form': form + }) + + + +## ... source file continues with no further redirect examples... + +``` + + +## Example 2 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / views.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py) + +```python +# views.py +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.sites.shortcuts import get_current_site +from django.http import ( + Http404, + HttpResponsePermanentRedirect, + HttpResponseRedirect, +) +~~from django.shortcuts import redirect +from django.urls import reverse, reverse_lazy +from django.utils.decorators import method_decorator +from django.views.decorators.debug import sensitive_post_parameters +from django.views.generic.base import TemplateResponseMixin, TemplateView, View +from django.views.generic.edit import FormView + +from ..exceptions import ImmediateHttpResponse +from ..utils import get_form_class, get_request_param +from . import app_settings, signals +from .adapter import get_adapter +from .forms import ( + AddEmailForm, + ChangePasswordForm, + LoginForm, + ResetPasswordForm, + ResetPasswordKeyForm, + SetPasswordForm, + SignupForm, + UserTokenForm, +) +from .models import EmailAddress, EmailConfirmation, EmailConfirmationHMAC +from .utils import ( + complete_signup, + get_login_redirect_url, + + +## ... source file abbreviated to get to redirect examples ... + + + try: + self.object = self.get_object() + if app_settings.CONFIRM_EMAIL_ON_GET: + return self.post(*args, **kwargs) + except Http404: + self.object = None + ctx = self.get_context_data() + return self.render_to_response(ctx) + + def post(self, *args, **kwargs): + self.object = confirmation = self.get_object() + confirmation.confirm(self.request) + get_adapter(self.request).add_message( + self.request, + messages.SUCCESS, + 'account/messages/email_confirmed.txt', + {'email': confirmation.email_address.email}) + if app_settings.LOGIN_ON_EMAIL_CONFIRMATION: + resp = self.login_on_confirm(confirmation) + if resp is not None: + return resp + redirect_url = self.get_redirect_url() + if not redirect_url: + ctx = self.get_context_data() + return self.render_to_response(ctx) +~~ return redirect(redirect_url) + + def login_on_confirm(self, confirmation): + user_pk = None + user_pk_str = get_adapter(self.request).unstash_user(self.request) + if user_pk_str: + user_pk = url_str_to_user_pk(user_pk_str) + user = confirmation.email_address.user + if user_pk == user.pk and self.request.user.is_anonymous: + return perform_login(self.request, + user, + app_settings.EmailVerificationMethod.NONE, + redirect_url=self.get_redirect_url) + + return None + + def get_object(self, queryset=None): + key = self.kwargs['key'] + emailconfirmation = EmailConfirmationHMAC.from_key(key) + if not emailconfirmation: + if queryset is None: + queryset = self.get_queryset() + try: + emailconfirmation = queryset.get(key=key.lower()) + except EmailConfirmation.DoesNotExist: + + +## ... source file abbreviated to get to redirect examples ... + + + return get_form_class(app_settings.FORMS, + 'reset_password_from_key', + self.form_class) + + def dispatch(self, request, uidb36, key, **kwargs): + self.request = request + self.key = key + + if self.key == INTERNAL_RESET_URL_KEY: + self.key = self.request.session.get(INTERNAL_RESET_SESSION_KEY, '') + token_form = UserTokenForm( + data={'uidb36': uidb36, 'key': self.key}) + if token_form.is_valid(): + self.reset_user = token_form.reset_user + return super(PasswordResetFromKeyView, self).dispatch(request, + uidb36, + self.key, + **kwargs) + else: + token_form = UserTokenForm( + data={'uidb36': uidb36, 'key': self.key}) + if token_form.is_valid(): + self.request.session[INTERNAL_RESET_SESSION_KEY] = self.key + redirect_url = self.request.path.replace( + self.key, INTERNAL_RESET_URL_KEY) +~~ return redirect(redirect_url) + + self.reset_user = None + response = self.render_to_response( + self.get_context_data(token_fail=True) + ) + return _ajax_response(self.request, response, form=token_form) + + def get_context_data(self, **kwargs): + ret = super(PasswordResetFromKeyView, self).get_context_data(**kwargs) + ret['action_url'] = reverse( + 'account_reset_password_from_key', + kwargs={'uidb36': self.kwargs['uidb36'], + 'key': self.kwargs['key']}) + return ret + + def get_form_kwargs(self): + kwargs = super(PasswordResetFromKeyView, self).get_form_kwargs() + kwargs["user"] = self.reset_user + kwargs["temp_key"] = self.key + return kwargs + + def form_valid(self, form): + form.save() + get_adapter(self.request).add_message( + + +## ... source file abbreviated to get to redirect examples ... + + + + return super(PasswordResetFromKeyView, self).form_valid(form) + + +password_reset_from_key = PasswordResetFromKeyView.as_view() + + +class PasswordResetFromKeyDoneView(TemplateView): + template_name = ( + "account/password_reset_from_key_done." + + app_settings.TEMPLATE_EXTENSION) + + +password_reset_from_key_done = PasswordResetFromKeyDoneView.as_view() + + +class LogoutView(TemplateResponseMixin, View): + + template_name = "account/logout." + app_settings.TEMPLATE_EXTENSION + redirect_field_name = "next" + + def get(self, *args, **kwargs): + if app_settings.LOGOUT_ON_GET: + return self.post(*args, **kwargs) + if not self.request.user.is_authenticated: +~~ response = redirect(self.get_redirect_url()) + return _ajax_response(self.request, response) + ctx = self.get_context_data() + response = self.render_to_response(ctx) + return _ajax_response(self.request, response) + + def post(self, *args, **kwargs): + url = self.get_redirect_url() + if self.request.user.is_authenticated: + self.logout() +~~ response = redirect(url) + return _ajax_response(self.request, response) + + def logout(self): + adapter = get_adapter(self.request) + adapter.add_message( + self.request, + messages.SUCCESS, + 'account/messages/logged_out.txt') + adapter.logout(self.request) + + def get_context_data(self, **kwargs): + ctx = kwargs + redirect_field_value = get_request_param(self.request, + self.redirect_field_name) + ctx.update({ + "redirect_field_name": self.redirect_field_name, + "redirect_field_value": redirect_field_value}) + return ctx + + def get_redirect_url(self): + return ( + get_next_redirect_url( + self.request, + self.redirect_field_name) or get_adapter( + + +## ... source file continues with no further redirect examples... + +``` + + +## Example 3 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / helpers.py**](https://github.com/jazzband/django-axes/blob/master/axes/./helpers.py) + +```python +# helpers.py +from datetime import timedelta +from hashlib import md5 +from logging import getLogger +from string import Template +from typing import Callable, Optional, Type, Union +from urllib.parse import urlencode + +from django.core.cache import caches, BaseCache +from django.http import HttpRequest, HttpResponse, JsonResponse, QueryDict +~~from django.shortcuts import render, redirect +from django.utils.module_loading import import_string + +import ipware.ip + +from axes.conf import settings +from axes.models import AccessBase + +log = getLogger(__name__) + + +def get_cache() -> BaseCache: + + return caches[getattr(settings, "AXES_CACHE", "default")] + + +def get_cache_timeout() -> Optional[int]: + + cool_off = get_cool_off() + if cool_off is None: + return None + return int(cool_off.total_seconds()) + + +def get_cool_off() -> Optional[timedelta]: + + +## ... source file abbreviated to get to redirect examples ... + + + "failure_limit": get_failure_limit(request, credentials), + "username": get_client_username(request, credentials) or "", + } + + cool_off = get_cool_off() + if cool_off: + context.update( + { + "cooloff_time": get_cool_off_iso8601( + cool_off + ), # differing old name is kept for backwards compatibility + "cooloff_timedelta": cool_off, + } + ) + + if request.is_ajax(): + return JsonResponse(context, status=status) + + if settings.AXES_LOCKOUT_TEMPLATE: + return render(request, settings.AXES_LOCKOUT_TEMPLATE, context, status=status) + + if settings.AXES_LOCKOUT_URL: + lockout_url = settings.AXES_LOCKOUT_URL + query_string = urlencode({"username": context["username"]}) + url = "{}?{}".format(lockout_url, query_string) +~~ return redirect(url) + + return HttpResponse(get_lockout_message(), status=status) + + +def is_ip_address_in_whitelist(ip_address: str) -> bool: + if not settings.AXES_IP_WHITELIST: + return False + + return ip_address in settings.AXES_IP_WHITELIST + + +def is_ip_address_in_blacklist(ip_address: str) -> bool: + if not settings.AXES_IP_BLACKLIST: + return False + + return ip_address in settings.AXES_IP_BLACKLIST + + +def is_client_ip_address_whitelisted(request): + + if settings.AXES_NEVER_LOCKOUT_WHITELIST and is_ip_address_in_whitelist( + request.axes_ip_address + ): + return True + + +## ... source file continues with no further redirect examples... + +``` + + +## Example 4 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / views.py**](https://github.com/divio/django-filer/blob/develop/filer/./views.py) + +```python +# views.py +from __future__ import absolute_import, unicode_literals + +from django.http import Http404 +~~from django.shortcuts import get_object_or_404, redirect + +from .models import File + + +def canonical(request, uploaded_at, file_id): + filer_file = get_object_or_404(File, pk=file_id, is_public=True) + if (not filer_file.file or int(uploaded_at) != filer_file.canonical_time): + raise Http404('No %s matches the given query.' % File._meta.object_name) +~~ return redirect(filer_file.url) + + + +## ... source file continues with no further redirect examples... + +``` + + +## Example 5 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / admin.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./admin.py) + +```python +# admin.py +from collections import OrderedDict + +from django import forms +from django.conf import settings +from django.contrib import admin, messages +from django.contrib.admin.widgets import FilteredSelectMultiple +from django.contrib.auth import get_user_model +~~from django.shortcuts import get_object_or_404, redirect, render +from django.urls import reverse, path +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import gettext +from guardian.forms import GroupObjectPermissionsForm, UserObjectPermissionsForm +from django.contrib.auth.models import Group +from guardian.shortcuts import (get_group_perms, get_groups_with_perms, get_perms_for_model, get_user_perms, + get_users_with_perms) + + +class AdminUserObjectPermissionsForm(UserObjectPermissionsForm): + + def get_obj_perms_field_widget(self): + return FilteredSelectMultiple(_("Permissions"), False) + + +class AdminGroupObjectPermissionsForm(GroupObjectPermissionsForm): + + def get_obj_perms_field_widget(self): + return FilteredSelectMultiple(_("Permissions"), False) + + +class GuardedModelAdminMixin: + change_form_template = \ + 'admin/guardian/model/change_form.html' + + +## ... source file abbreviated to get to redirect examples ... + + + view=self.admin_site.admin_view( + self.obj_perms_manage_group_view), + name='%s_%s_permissions_manage_group' % info), + ] + urls = myurls + urls + return urls + + def get_obj_perms_base_context(self, request, obj): + context = self.admin_site.each_context(request) + context.update({ + 'adminform': {'model_admin': self}, + 'media': self.media, + 'object': obj, + 'app_label': self.model._meta.app_label, + 'opts': self.model._meta, + 'original': str(obj), + 'has_change_permission': self.has_change_permission(request, obj), + 'model_perms': get_perms_for_model(obj), + 'title': _("Object permissions"), + }) + return context + + def obj_perms_manage_view(self, request, object_pk): + if not self.has_change_permission(request, None): + post_url = reverse('admin:index', current_app=self.admin_site.name) +~~ return redirect(post_url) + + from django.contrib.admin.utils import unquote + obj = get_object_or_404(self.get_queryset( + request), pk=unquote(object_pk)) + users_perms = OrderedDict( + sorted( + get_users_with_perms(obj, attach_perms=True, + with_group_users=False).items(), + key=lambda user: getattr( + user[0], get_user_model().USERNAME_FIELD) + ) + ) + + groups_perms = OrderedDict( + sorted( + get_groups_with_perms(obj, attach_perms=True).items(), + key=lambda group: group[0].name + ) + ) + + if request.method == 'POST' and 'submit_manage_user' in request.POST: + user_form = self.get_obj_perms_user_select_form( + request)(request.POST) + group_form = self.get_obj_perms_group_select_form( + request)(request.POST) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + if user_form.is_valid(): + user_id = user_form.cleaned_data['user'].pk + url = reverse( + '%s:%s_%s_permissions_manage_user' % info, + args=[obj.pk, user_id] + ) +~~ return redirect(url) + elif request.method == 'POST' and 'submit_manage_group' in request.POST: + user_form = self.get_obj_perms_user_select_form( + request)(request.POST) + group_form = self.get_obj_perms_group_select_form( + request)(request.POST) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + if group_form.is_valid(): + group_id = group_form.cleaned_data['group'].id + url = reverse( + '%s:%s_%s_permissions_manage_group' % info, + args=[obj.pk, group_id] + ) +~~ return redirect(url) + else: + user_form = self.get_obj_perms_user_select_form(request)() + group_form = self.get_obj_perms_group_select_form(request)() + + context = self.get_obj_perms_base_context(request, obj) + context['users_perms'] = users_perms + context['groups_perms'] = groups_perms + context['user_form'] = user_form + context['group_form'] = group_form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_template(), context) + + def get_obj_perms_manage_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage.html' + return self.obj_perms_manage_template + + def obj_perms_manage_user_view(self, request, object_pk, user_id): + if not self.has_change_permission(request, None): + post_url = reverse('admin:index', current_app=self.admin_site.name) +~~ return redirect(post_url) + + user = get_object_or_404(get_user_model(), pk=user_id) + obj = get_object_or_404(self.get_queryset(request), pk=object_pk) + form_class = self.get_obj_perms_manage_user_form(request) + form = form_class(user, obj, request.POST or None) + + if request.method == 'POST' and form.is_valid(): + form.save_obj_perms() + msg = gettext("Permissions saved.") + messages.success(request, msg) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + url = reverse( + '%s:%s_%s_permissions_manage_user' % info, + args=[obj.pk, user.pk] + ) +~~ return redirect(url) + + context = self.get_obj_perms_base_context(request, obj) + context['user_obj'] = user + context['user_perms'] = get_user_perms(user, obj) + context['form'] = form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_user_template(), context) + + def get_obj_perms_manage_user_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage_user.html' + return self.obj_perms_manage_user_template + + def get_obj_perms_user_select_form(self, request): + return UserManage + + def get_obj_perms_group_select_form(self, request): + return GroupManage + + def get_obj_perms_manage_user_form(self, request): + return AdminUserObjectPermissionsForm + + def obj_perms_manage_group_view(self, request, object_pk, group_id): + if not self.has_change_permission(request, None): + post_url = reverse('admin:index', current_app=self.admin_site.name) +~~ return redirect(post_url) + + group = get_object_or_404(Group, id=group_id) + obj = get_object_or_404(self.get_queryset(request), pk=object_pk) + form_class = self.get_obj_perms_manage_group_form(request) + form = form_class(group, obj, request.POST or None) + + if request.method == 'POST' and form.is_valid(): + form.save_obj_perms() + msg = gettext("Permissions saved.") + messages.success(request, msg) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + url = reverse( + '%s:%s_%s_permissions_manage_group' % info, + args=[obj.pk, group.id] + ) +~~ return redirect(url) + + context = self.get_obj_perms_base_context(request, obj) + context['group_obj'] = group + context['group_perms'] = get_group_perms(group, obj) + context['form'] = form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_group_template(), context) + + def get_obj_perms_manage_group_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage_group.html' + return self.obj_perms_manage_group_template + + def get_obj_perms_manage_group_form(self, request): + return AdminGroupObjectPermissionsForm + + +class GuardedModelAdmin(GuardedModelAdminMixin, admin.ModelAdmin): + + +class UserManage(forms.Form): + user = forms.CharField(label=_("User identification"), + + +## ... source file continues with no further redirect examples... + +``` + + +## Example 6 from django-inline-actions +[django-inline-actions](https://github.com/escaped/django-inline-actions) +([PyPI package information](https://pypi.org/project/django-inline-actions/)) +is an extension that adds actions to the [Django](/django.html) +Admin InlineModelAdmin and ModelAdmin changelists. The project is open +sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/escaped/django-inline-actions/blob/master/LICENSE). + +[**django-inline-actions / inline_actions / actions.py**](https://github.com/escaped/django-inline-actions/blob/master/inline_actions/./actions.py) + +```python +# actions.py +from django.contrib import messages +~~from django.shortcuts import redirect +from django.urls import reverse +from django.utils.translation import ugettext_lazy as _ + + +class ViewAction: + inline_actions = ['view_action'] + + def view_action(self, request, obj, parent_obj=None): + url = reverse( + 'admin:{}_{}_change'.format( + obj._meta.app_label, + obj._meta.model_name, + ), + args=(obj.pk,) + ) +~~ return redirect(url) + view_action.short_description = _("View") + + +class DeleteAction: + def get_inline_actions(self, request, obj=None): + actions = super().get_inline_actions(request, obj) + if self.has_delete_permission(request, obj): + actions.append('delete_action') + return actions + + def delete_action(self, request, obj, parent_obj=None): + if self.has_delete_permission(request): + obj.delete() + messages.info(request, "`{}` deleted.".format(obj)) + delete_action.short_description = _("Delete") + + +class DefaultActionsMixin(ViewAction, + DeleteAction): + inline_actions = [] + + + +## ... source file continues with no further redirect examples... + +``` + + +## Example 7 from django-loginas +[django-loginas](https://github.com/skorokithakis/django-loginas) +([PyPI package information](https://pypi.org/project/django-loginas/)) +is [Django](/django.html) code library for admins to log into an application +as another user, typically for debugging purposes. + +django-loginas is open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/skorokithakis/django-loginas/blob/master/LICENSE). + +[**django-loginas / loginas / views.py**](https://github.com/skorokithakis/django-loginas/blob/master/loginas/./views.py) + +```python +# views.py +from django.contrib import messages +from django.contrib.admin.utils import unquote +from django.core.exceptions import ImproperlyConfigured, PermissionDenied +~~from django.shortcuts import redirect +from django.utils.translation import gettext_lazy as _ +from django.views.decorators.csrf import csrf_protect +from django.views.decorators.http import require_POST + +from . import settings as la_settings +from .utils import login_as, restore_original_login + +try: + from importlib import import_module +except ImportError: + from django.utils.importlib import import_module # type: ignore + + +try: + from django.contrib.auth import get_user_model + + User = get_user_model() +except ImportError: + from django.contrib.auth.models import User # type: ignore + + +def _load_module(path): + + i = path.rfind(".") + + +## ... source file abbreviated to get to redirect examples ... + + + can_login_as = getattr(mod, attr) + except AttributeError: + raise ImproperlyConfigured("Module {0} does not define a {1} " "function.".format(module, attr)) + return can_login_as + + +@csrf_protect +@require_POST +def user_login(request, user_id): + user = User.objects.get(pk=unquote(user_id)) + + if isinstance(la_settings.CAN_LOGIN_AS, str): + can_login_as = _load_module(la_settings.CAN_LOGIN_AS) + elif hasattr(la_settings.CAN_LOGIN_AS, "__call__"): + can_login_as = la_settings.CAN_LOGIN_AS + else: + raise ImproperlyConfigured("The CAN_LOGIN_AS setting is neither a valid module nor callable.") + no_permission_error = None + try: + if not can_login_as(request, user): + no_permission_error = _("You do not have permission to do that.") + except PermissionDenied as e: + no_permission_error = str(e) + if no_permission_error is not None: + messages.error(request, no_permission_error, extra_tags=la_settings.MESSAGE_EXTRA_TAGS, fail_silently=True) +~~ return redirect(request.META.get("HTTP_REFERER", "/")) + + try: + login_as(user, request) + except ImproperlyConfigured as e: + messages.error(request, str(e), extra_tags=la_settings.MESSAGE_EXTRA_TAGS, fail_silently=True) +~~ return redirect(request.META.get("HTTP_REFERER", "/")) + +~~ return redirect(la_settings.LOGIN_REDIRECT) + + +def user_logout(request): + restore_original_login(request) + +~~ return redirect(la_settings.LOGOUT_REDIRECT) + + + +## ... source file continues with no further redirect examples... + +``` + + +## Example 8 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / decorators.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./decorators.py) + +```python +# decorators.py +from functools import wraps + +from django.http import HttpResponseForbidden +from django.http import HttpResponseNotFound +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404 +~~from django.shortcuts import redirect +from django.template.loader import render_to_string +from django.urls import reverse +from django.utils.http import urlquote +from wiki.conf import settings +from wiki.core.exceptions import NoRootURL + + +def response_forbidden(request, article, urlpath, read_denied=False): + if request.user.is_anonymous: + qs = request.META.get("QUERY_STRING", "") + if qs: + qs = urlquote("?" + qs) + else: + qs = "" +~~ return redirect(settings.LOGIN_URL + "?next=" + request.path + qs) + else: + return HttpResponseForbidden( + render_to_string( + "wiki/permission_denied.html", + context={ + "article": article, + "urlpath": urlpath, + "read_denied": read_denied, + }, + request=request, + ) + ) + + +def get_article( # noqa: max-complexity=23 + func=None, + can_read=True, + can_write=False, + deleted_contents=False, + not_locked=False, + can_delete=False, + can_moderate=False, + can_create=False, +): + + def wrapper(request, *args, **kwargs): + from . import models + + path = kwargs.pop("path", None) + article_id = kwargs.pop("article_id", None) + + if path is not None: + try: + urlpath = models.URLPath.get_by_path(path, select_related=True) + except NoRootURL: +~~ return redirect("wiki:root_create") + except models.URLPath.DoesNotExist: + try: + pathlist = list(filter(lambda x: x != "", path.split("/"),)) + path = "/".join(pathlist[:-1]) + parent = models.URLPath.get_by_path(path) + return HttpResponseRedirect( + reverse("wiki:create", kwargs={"path": parent.path}) + + "?slug=%s" % pathlist[-1].lower() + ) + except models.URLPath.DoesNotExist: + return HttpResponseNotFound( + render_to_string( + "wiki/error.html", + context={"error_type": "ancestors_missing"}, + request=request, + ) + ) + if urlpath.article: + article = urlpath.article + else: + return_url = reverse("wiki:get", kwargs={"path": urlpath.parent.path}) + urlpath.delete() + return HttpResponseRedirect(return_url) + + elif article_id: + articles = models.Article.objects + + article = get_object_or_404(articles, id=article_id) + try: + urlpath = models.URLPath.objects.get(articles__article=article) + except ( + models.URLPath.DoesNotExist, + models.URLPath.MultipleObjectsReturned, + ): + urlpath = None + + else: + raise TypeError("You should specify either article_id or path") + + if not deleted_contents: + if urlpath: + if urlpath.is_deleted(): # This also checks all ancestors +~~ return redirect("wiki:deleted", path=urlpath.path) + else: + if article.current_revision and article.current_revision.deleted: +~~ return redirect("wiki:deleted", article_id=article.id) + + if article.current_revision.locked and not_locked: + return response_forbidden(request, article, urlpath) + + if can_read and not article.can_read(request.user): + return response_forbidden(request, article, urlpath, read_denied=True) + + if (can_write or can_create) and not article.can_write(request.user): + return response_forbidden(request, article, urlpath) + + if can_create and not ( + request.user.is_authenticated or settings.ANONYMOUS_CREATE + ): + return response_forbidden(request, article, urlpath) + + if can_delete and not article.can_delete(request.user): + return response_forbidden(request, article, urlpath) + + if can_moderate and not article.can_moderate(request.user): + return response_forbidden(request, article, urlpath) + + kwargs["urlpath"] = urlpath + + return func(request, article, *args, **kwargs) + + +## ... source file continues with no further redirect examples... + +``` + + +## Example 9 from register +[register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is +open source under the +[GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). +This web application makes it easier for people to register as organ donors. +You can see the application live at +[https://register.organize.org/](https://register.organize.org/). + +[**register / registration / middleware.py**](https://github.com/ORGAN-IZE/register/blob/master/registration/./middleware.py) + +```python +# middleware.py +import django.middleware.locale +~~import django.shortcuts +from django.utils import translation +from django.utils.deprecation import MiddlewareMixin + + +class RequestLocaleMiddleware(MiddlewareMixin): + def process_view(self, request, view_func, view_args, view_kwargs): + if request.method == 'GET': + language = request.GET.get('lang') + if language: + translation.activate(language) + request.session[translation.LANGUAGE_SESSION_KEY] = translation.get_language() + query = request.GET.copy() + del query['lang'] + path = '?'.join([request.path, query.urlencode()]) +~~ return django.shortcuts.redirect(path) + + + +## ... source file continues with no further redirect examples... + +``` + + +## Example 10 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / views.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/views.py) + +```python +# views.py +from django.http import Http404, HttpResponse +~~from django.shortcuts import get_object_or_404, redirect +from django.urls import reverse + +from wagtail.core import hooks +from wagtail.core.forms import PasswordViewRestrictionForm +from wagtail.core.models import Page, PageViewRestriction, Site + + +def serve(request, path): + site = Site.find_for_request(request) + if not site: + raise Http404 + + path_components = [component for component in path.split('/') if component] + page, args, kwargs = site.root_page.specific.route(request, path_components) + + for fn in hooks.get_hooks('before_serve_page'): + result = fn(page, request, args, kwargs) + if isinstance(result, HttpResponse): + return result + + return page.serve(request, *args, **kwargs) + + +def authenticate_with_password(request, page_view_restriction_id, page_id): + restriction = get_object_or_404(PageViewRestriction, id=page_view_restriction_id) + page = get_object_or_404(Page, id=page_id).specific + + if request.method == 'POST': + form = PasswordViewRestrictionForm(request.POST, instance=restriction) + if form.is_valid(): + restriction.mark_as_passed(request) + +~~ return redirect(form.cleaned_data['return_url']) + else: + form = PasswordViewRestrictionForm(instance=restriction) + + action_url = reverse('wagtailcore_authenticate_with_password', args=[restriction.id, page.id]) + return page.serve_password_required_response(request, form, action_url) + + + +## ... source file continues with no further redirect examples... + +``` + diff --git a/content/pages/examples/django/django-shortcuts-render.markdown b/content/pages/examples/django/django-shortcuts-render.markdown new file mode 100644 index 000000000..7b5d2d193 --- /dev/null +++ b/content/pages/examples/django/django-shortcuts-render.markdown @@ -0,0 +1,1883 @@ +title: django.shortcuts render Example Code +category: page +slug: django-shortcuts-render-examples +sortorder: 500011348 +toc: False +sidebartitle: django.shortcuts render +meta: Python example code for the render callable from the django.shortcuts module of the Django project. + + +render is a callable within the django.shortcuts module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / registration / views.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/registration/views.py) + +```python +# views.py +from django.contrib.auth import get_user_model +from django.contrib.auth.decorators import login_required +~~from django.shortcuts import render, redirect + +from users.models import generate_avatar +from users.forms import PersonalForm, ProfessionalForm, SubscriptionsForm + +User = get_user_model() + + +@login_required +def personal(request): + profile = request.user.profile + if request.method == 'POST': + form = PersonalForm(request.POST, instance=profile) + if form.is_valid(): + form.save() + profile.avatar = generate_avatar(profile) + profile.save() + return redirect('register-professional') + else: + form = PersonalForm(instance=profile) +~~ return render(request, 'registration/personal.html', { + 'form': form + }) + +@login_required +def professional(request): + profile = request.user.profile + if request.method == 'POST': + form = ProfessionalForm(request.POST, instance=profile) + if form.is_valid(): + form.save() + return redirect('register-subscriptions') + else: + form = ProfessionalForm(instance=profile) +~~ return render(request, 'registration/professional.html', { + 'form': form + }) + + +@login_required +def subscriptions(request): + subscriptions = request.user.subscriptions + if request.method == 'POST': + form = SubscriptionsForm(request.POST, instance=subscriptions) + if form.is_valid(): + form.save() + request.user.has_finished_registration = True + request.user.save() + return redirect('home') + else: + form = SubscriptionsForm(instance=subscriptions) +~~ return render(request, 'registration/subscriptions.html', { + 'form': form + }) + + + +## ... source file continues with no further render examples... + +``` + + +## Example 2 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / socialaccount / helpers.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/helpers.py) + +```python +# helpers.py +from django.contrib import messages +from django.forms import ValidationError +from django.http import HttpResponseRedirect +~~from django.shortcuts import render +from django.urls import reverse + +from allauth.account import app_settings as account_settings +from allauth.account.adapter import get_adapter as get_account_adapter +from allauth.account.utils import complete_signup, perform_login, user_username +from allauth.exceptions import ImmediateHttpResponse + +from . import app_settings, signals +from .adapter import get_adapter +from .models import SocialLogin +from .providers.base import AuthError, AuthProcess + + +def _process_signup(request, sociallogin): + auto_signup = get_adapter(request).is_auto_signup_allowed( + request, + sociallogin) + if not auto_signup: + request.session['socialaccount_sociallogin'] = sociallogin.serialize() + url = reverse('socialaccount_signup') + ret = HttpResponseRedirect(url) + else: + if account_settings.USER_MODEL_USERNAME_FIELD: + username = user_username(sociallogin.user) + try: + get_account_adapter(request).clean_username(username) + except ValidationError: + user_username(sociallogin.user, '') + if not get_adapter(request).is_open_for_signup( + request, + sociallogin): +~~ return render( + request, + "account/signup_closed." + + account_settings.TEMPLATE_EXTENSION) + get_adapter(request).save_user(request, sociallogin, form=None) + ret = complete_social_signup(request, sociallogin) + return ret + + +def _login_social_account(request, sociallogin): + return perform_login(request, sociallogin.user, + email_verification=app_settings.EMAIL_VERIFICATION, + redirect_url=sociallogin.get_redirect_url(request), + signal_kwargs={"sociallogin": sociallogin}) + + +def render_authentication_error(request, + provider_id, + error=AuthError.UNKNOWN, + exception=None, + extra_context=None): + try: + if extra_context is None: + extra_context = {} + get_adapter(request).authentication_error( + request, + provider_id, + error=error, + exception=exception, + extra_context=extra_context) + except ImmediateHttpResponse as e: + return e.response + if error == AuthError.CANCELLED: + return HttpResponseRedirect(reverse('socialaccount_login_cancelled')) + context = { + 'auth_error': { + 'provider': provider_id, + 'code': error, + 'exception': exception + } + } + context.update(extra_context) +~~ return render( + request, + "socialaccount/authentication_error." + + account_settings.TEMPLATE_EXTENSION, + context + ) + + +def _add_social_account(request, sociallogin): + if request.user.is_anonymous: + return HttpResponseRedirect(reverse('socialaccount_connections')) + level = messages.INFO + message = 'socialaccount/messages/account_connected.txt' + action = None + if sociallogin.is_existing: + if sociallogin.user != request.user: + level = messages.ERROR + message = 'socialaccount/messages/account_connected_other.txt' + else: + action = 'updated' + message = 'socialaccount/messages/account_connected_updated.txt' + signals.social_account_updated.send( + sender=SocialLogin, + request=request, + sociallogin=sociallogin) + + +## ... source file continues with no further render examples... + +``` + + +## Example 3 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / helpers.py**](https://github.com/jazzband/django-axes/blob/master/axes/./helpers.py) + +```python +# helpers.py +from datetime import timedelta +from hashlib import md5 +from logging import getLogger +from string import Template +from typing import Callable, Optional, Type, Union +from urllib.parse import urlencode + +from django.core.cache import caches, BaseCache +from django.http import HttpRequest, HttpResponse, JsonResponse, QueryDict +~~from django.shortcuts import render, redirect +from django.utils.module_loading import import_string + +import ipware.ip + +from axes.conf import settings +from axes.models import AccessBase + +log = getLogger(__name__) + + +def get_cache() -> BaseCache: + + return caches[getattr(settings, "AXES_CACHE", "default")] + + +def get_cache_timeout() -> Optional[int]: + + cool_off = get_cool_off() + if cool_off is None: + return None + return int(cool_off.total_seconds()) + + +def get_cool_off() -> Optional[timedelta]: + + +## ... source file abbreviated to get to render examples ... + + + raise TypeError( + "settings.AXES_LOCKOUT_CALLABLE needs to be a string, callable, or None." + ) + + status = 403 + context = { + "failure_limit": get_failure_limit(request, credentials), + "username": get_client_username(request, credentials) or "", + } + + cool_off = get_cool_off() + if cool_off: + context.update( + { + "cooloff_time": get_cool_off_iso8601( + cool_off + ), # differing old name is kept for backwards compatibility + "cooloff_timedelta": cool_off, + } + ) + + if request.is_ajax(): + return JsonResponse(context, status=status) + + if settings.AXES_LOCKOUT_TEMPLATE: +~~ return render(request, settings.AXES_LOCKOUT_TEMPLATE, context, status=status) + + if settings.AXES_LOCKOUT_URL: + lockout_url = settings.AXES_LOCKOUT_URL + query_string = urlencode({"username": context["username"]}) + url = "{}?{}".format(lockout_url, query_string) + return redirect(url) + + return HttpResponse(get_lockout_message(), status=status) + + +def is_ip_address_in_whitelist(ip_address: str) -> bool: + if not settings.AXES_IP_WHITELIST: + return False + + return ip_address in settings.AXES_IP_WHITELIST + + +def is_ip_address_in_blacklist(ip_address: str) -> bool: + if not settings.AXES_IP_BLACKLIST: + return False + + return ip_address in settings.AXES_IP_BLACKLIST + + + + +## ... source file continues with no further render examples... + +``` + + +## Example 4 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / page_rendering.py**](https://github.com/divio/django-cms/blob/develop/cms/./page_rendering.py) + +```python +# page_rendering.py +from django.conf import settings +from django.http import Http404 +~~from django.shortcuts import render +from django.template.response import TemplateResponse +from django.urls import Resolver404, resolve, reverse + +from cms import __version__ +from cms.cache.page import set_page_cache +from cms.models import Page +from cms.utils.conf import get_cms_setting +from cms.utils.page import get_page_template_from_request +from cms.utils.page_permissions import user_can_change_page, user_can_view_page + + +def render_page(request, page, current_language, slug): + context = {} + context['lang'] = current_language + context['current_page'] = page + context['has_change_permissions'] = user_can_change_page(request.user, page) + context['has_view_permissions'] = user_can_view_page(request.user, page) + + if not context['has_view_permissions']: + return _handle_no_page(request) + + template = get_page_template_from_request(request) + response = TemplateResponse(request, template, context) + response.add_post_render_callback(set_page_cache) + + xframe_options = page.get_xframe_options() + if xframe_options == Page.X_FRAME_OPTIONS_INHERIT or xframe_options is None: + return response + + response.xframe_options_exempt = True + + if xframe_options == Page.X_FRAME_OPTIONS_ALLOW: + return response + elif xframe_options == Page.X_FRAME_OPTIONS_SAMEORIGIN: + response['X-Frame-Options'] = 'SAMEORIGIN' + elif xframe_options == Page.X_FRAME_OPTIONS_DENY: + response['X-Frame-Options'] = 'DENY' + return response + + +def render_object_structure(request, obj): + context = { + 'object': obj, + 'cms_toolbar': request.toolbar, + } +~~ return render(request, 'cms/toolbar/structure.html', context) + + +def _handle_no_page(request): + try: + resolve('%s$' % request.path) + except Resolver404 as e: + exc = Http404(dict(path=request.path, tried=e.args[0]['tried'])) + raise exc + raise Http404('CMS Page not found: %s' % request.path) + + +def _render_welcome_page(request): + context = { + 'cms_version': __version__, + 'cms_edit_on': get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'), + 'django_debug': settings.DEBUG, + 'next_url': reverse('pages-root'), + } + return TemplateResponse(request, "cms/welcome.html", context) + + + +## ... source file continues with no further render examples... + +``` + + +## Example 5 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / folderadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/folderadmin.py) + +```python +# folderadmin.py +from __future__ import absolute_import, division, unicode_literals + +import itertools +import os +import re +from collections import OrderedDict + +from django import forms +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import messages +from django.contrib.admin import helpers +from django.contrib.admin.utils import capfirst, quote, unquote +from django.core.exceptions import PermissionDenied, ValidationError +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db import models, router +from django.http import HttpResponse, HttpResponseRedirect +~~from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils.encoding import force_text +from django.utils.html import escape +from django.utils.http import urlquote, urlunquote +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy, ungettext + +from .. import settings +from ..models import ( + File, Folder, FolderPermission, FolderRoot, ImagesWithMissingData, + UnsortedImages, tools, +) +from ..settings import FILER_IMAGE_MODEL, FILER_PAGINATE_BY +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import get_delete_permission +from ..utils.filer_easy_thumbnails import FilerActionThumbnailer +from ..utils.loader import load_model +from . import views +from .forms import CopyFilesAndFoldersForm, RenameFilesForm, ResizeImagesForm +from .patched.admin_utils import get_deleted_objects +from .permissions import PrimitivePermissionAwareModelAdmin +from .tools import ( + AdminContext, admin_url_params_encoded, check_files_edit_permissions, + + +## ... source file abbreviated to get to render examples ... + + + 'virtual_items': virtual_items, + 'uploader_connections': settings.FILER_UPLOADER_CONNECTIONS, + 'permissions': permissions, + 'permstest': userperms_for_request(folder, request), + 'current_url': request.path, + 'title': _('Directory listing for %(folder_name)s') % {'folder_name': folder.name}, + 'search_string': ' '.join(search_terms), + 'q': urlquote(q), + 'show_result_count': show_result_count, + 'folder_children': folder_children, + 'folder_files': folder_files, + 'limit_search_to_folder': limit_search_to_folder, + 'is_popup': popup_status(request), + 'filer_admin_context': AdminContext(request), + 'root_path': reverse('admin:index'), + 'action_form': action_form, + 'actions_on_top': self.actions_on_top, + 'actions_on_bottom': self.actions_on_bottom, + 'actions_selection_counter': self.actions_selection_counter, + 'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(paginated_items.object_list)}, + 'selection_note_all': selection_note_all % {'total_count': paginator.count}, + 'media': self.media, + 'enable_permissions': settings.FILER_ENABLE_PERMISSIONS, + 'can_make_folder': request.user.is_superuser or (folder.is_root and settings.FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS) or permissions.get("has_add_children_permission"), + }) +~~ return render(request, self.directory_listing_template, context) + + def filter_folder(self, qs, terms=()): + def construct_search(field_name): + if field_name.startswith('^'): + return "%s__istartswith" % field_name[1:] + elif field_name.startswith('='): + return "%s__iexact" % field_name[1:] + elif field_name.startswith('@'): + return "%s__search" % field_name[1:] + else: + return "%s__icontains" % field_name + + for term in terms: + filters = models.Q() + for filter_ in self.search_fields: + filters |= models.Q(**{construct_search(filter_): term}) + for filter_ in self.get_owner_filter_lookups(): + filters |= models.Q(**{filter_: term}) + qs = qs.filter(filters) + return qs + + def filter_file(self, qs, terms=()): + for term in terms: + filters = (models.Q(name__icontains=term) + + +## ... source file abbreviated to get to render examples ... + + + return None + + if all_perms_needed or all_protected: + title = _("Cannot delete files and/or folders") + else: + title = _("Are you sure?") + + context = self.admin_site.each_context(request) + context.update({ + "title": title, + "instance": current_folder, + "breadcrumbs_action": _("Delete files and/or folders"), + "deletable_objects": all_deletable_objects, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": all_perms_needed, + "protected": all_protected, + "opts": opts, + 'is_popup': popup_status(request), + 'filer_admin_context': AdminContext(request), + "root_path": reverse('admin:index'), + "app_label": app_label, + "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + }) + +~~ return render( + request, + "admin/filer/delete_selected_files_confirmation.html", + context + ) + + delete_files_or_folders.short_description = ugettext_lazy( + "Delete selected files and/or folders") + + def _format_callback(self, obj, user, admin_site, perms_needed): + has_admin = obj.__class__ in admin_site._registry + opts = obj._meta + if has_admin: + admin_url = reverse('%s:%s_%s_change' + % (admin_site.name, + opts.app_label, + opts.object_name.lower()), + None, (quote(obj._get_pk_val()),)) + p = get_delete_permission(opts) + if not user.has_perm(p): + perms_needed.add(opts.verbose_name) + return mark_safe('%s: %s' % + (escape(capfirst(opts.verbose_name)), + admin_url, + escape(obj))) + + +## ... source file abbreviated to get to render examples ... + + + "destination") % ", ".join(conflicting_names)) + elif n: + self._move_files_and_folders_impl(files_queryset, folders_queryset, destination) + self.message_user(request, _("Successfully moved %(count)d files and/or folders to folder '%(destination)s'.") % { + "count": n, + "destination": destination, + }) + return None + + context = self.admin_site.each_context(request) + context.update({ + "title": _("Move files and/or folders"), + "instance": current_folder, + "breadcrumbs_action": _("Move files and/or folders"), + "to_move": to_move, + "destination_folders": folders, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": perms_needed, + "opts": opts, + "root_path": reverse('admin:index'), + "app_label": app_label, + "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + }) + +~~ return render(request, "admin/filer/folder/choose_move_destination.html", context) + + move_files_and_folders.short_description = ugettext_lazy("Move selected files and/or folders") + + def _rename_file(self, file_obj, form_data, counter, global_counter): + original_basename, original_extension = os.path.splitext(file_obj.original_filename) + if file_obj.name: + current_basename, current_extension = os.path.splitext(file_obj.name) + else: + current_basename = "" + current_extension = "" + file_obj.name = form_data['rename_format'] % { + 'original_filename': file_obj.original_filename, + 'original_basename': original_basename, + 'original_extension': original_extension, + 'current_filename': file_obj.name or "", + 'current_basename': current_basename, + 'current_extension': current_extension, + 'current_folder': getattr(file_obj.folder, 'name', ''), + 'counter': counter + 1, # 1-based + 'global_counter': global_counter + 1, # 1-based + } + file_obj.save() + + def _rename_files(self, files, form_data, global_counter): + + +## ... source file abbreviated to get to render examples ... + + + if files_queryset.count() + folders_queryset.count(): + n = self._rename_files_impl(files_queryset, folders_queryset, form.cleaned_data, 0) + self.message_user(request, _("Successfully renamed %(count)d files.") % { + "count": n, + }) + return None + else: + form = RenameFilesForm() + + context = self.admin_site.each_context(request) + context.update({ + "title": _("Rename files"), + "instance": current_folder, + "breadcrumbs_action": _("Rename files"), + "to_rename": to_rename, + "rename_form": form, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": perms_needed, + "opts": opts, + "root_path": reverse('admin:index'), + "app_label": app_label, + "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + }) + +~~ return render(request, "admin/filer/folder/choose_rename_format.html", context) + + rename_files.short_description = ugettext_lazy("Rename files") + + def _generate_new_filename(self, filename, suffix): + basename, extension = os.path.splitext(filename) + return basename + suffix + extension + + def _copy_file(self, file_obj, destination, suffix, overwrite): + if overwrite: + raise NotImplementedError + + + filename = self._generate_new_filename(file_obj.file.name, suffix) + + file_obj.pk = None + file_obj.id = None + file_obj.save() + file_obj.folder = destination + file_obj._file_data_changed_hint = False # no need to update size, sha1, etc. + file_obj.file = file_obj._copy_file(filename) + file_obj.original_filename = self._generate_new_filename(file_obj.original_filename, suffix) + file_obj.save() + + def _copy_files(self, files, destination, suffix, overwrite): + + +## ... source file abbreviated to get to render examples ... + + + selected_destination_folder = int(request.POST.get('destination', 0)) + except ValueError: + if current_folder: + selected_destination_folder = current_folder.pk + else: + selected_destination_folder = 0 + + context = self.admin_site.each_context(request) + context.update({ + "title": _("Copy files and/or folders"), + "instance": current_folder, + "breadcrumbs_action": _("Copy files and/or folders"), + "to_copy": to_copy, + "destination_folders": folders, + "selected_destination_folder": selected_destination_folder, + "copy_form": form, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": perms_needed, + "opts": opts, + "root_path": reverse('admin:index'), + "app_label": app_label, + "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + }) + +~~ return render(request, "admin/filer/folder/choose_copy_destination.html", context) + + copy_files_and_folders.short_description = ugettext_lazy("Copy selected files and/or folders") + + def _check_resize_perms(self, request, files_queryset, folders_queryset): + try: + check_files_read_permissions(request, files_queryset) + check_folder_read_permissions(request, folders_queryset) + check_files_edit_permissions(request, files_queryset) + except PermissionDenied: + return True + return False + + def _list_folders_to_resize(self, request, folders): + for fo in folders: + children = list(self._list_folders_to_resize(request, fo.children.all())) + children.extend([self._format_callback(f, request.user, self.admin_site, set()) for f in sorted(fo.files) if isinstance(f, Image)]) + if children: + yield self._format_callback(fo, request.user, self.admin_site, set()) + yield children + + def _list_all_to_resize(self, request, files_queryset, folders_queryset): + to_resize = list(self._list_folders_to_resize(request, folders_queryset)) + to_resize.extend([self._format_callback(f, request.user, self.admin_site, set()) for f in sorted(files_queryset) if isinstance(f, Image)]) + return to_resize + + +## ... source file abbreviated to get to render examples ... + + + form.cleaned_data['upscale'] = form.cleaned_data['thumbnail_option'].upscale + if files_queryset.count() + folders_queryset.count(): + n = self._resize_images_impl(files_queryset, folders_queryset, form.cleaned_data) + self.message_user(request, _("Successfully resized %(count)d images.") % {"count": n, }) + return None + else: + form = ResizeImagesForm() + + context = self.admin_site.each_context(request) + context.update({ + "title": _("Resize images"), + "instance": current_folder, + "breadcrumbs_action": _("Resize images"), + "to_resize": to_resize, + "resize_form": form, + "cmsplugin_enabled": 'cmsplugin_filer_image' in django_settings.INSTALLED_APPS, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": perms_needed, + "opts": opts, + "root_path": reverse('admin:index'), + "app_label": app_label, + "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, + }) + +~~ return render(request, "admin/filer/folder/choose_images_resize_options.html", context) + + resize_images.short_description = ugettext_lazy("Resize selected images") + + + +## ... source file continues with no further render examples... + +``` + + +## Example 6 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / admin.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./admin.py) + +```python +# admin.py +from collections import OrderedDict + +from django import forms +from django.conf import settings +from django.contrib import admin, messages +from django.contrib.admin.widgets import FilteredSelectMultiple +from django.contrib.auth import get_user_model +~~from django.shortcuts import get_object_or_404, redirect, render +from django.urls import reverse, path +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import gettext +from guardian.forms import GroupObjectPermissionsForm, UserObjectPermissionsForm +from django.contrib.auth.models import Group +from guardian.shortcuts import (get_group_perms, get_groups_with_perms, get_perms_for_model, get_user_perms, + get_users_with_perms) + + +class AdminUserObjectPermissionsForm(UserObjectPermissionsForm): + + def get_obj_perms_field_widget(self): + return FilteredSelectMultiple(_("Permissions"), False) + + +class AdminGroupObjectPermissionsForm(GroupObjectPermissionsForm): + + def get_obj_perms_field_widget(self): + return FilteredSelectMultiple(_("Permissions"), False) + + +class GuardedModelAdminMixin: + change_form_template = \ + 'admin/guardian/model/change_form.html' + + +## ... source file abbreviated to get to render examples ... + + + request)(request.POST) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + if group_form.is_valid(): + group_id = group_form.cleaned_data['group'].id + url = reverse( + '%s:%s_%s_permissions_manage_group' % info, + args=[obj.pk, group_id] + ) + return redirect(url) + else: + user_form = self.get_obj_perms_user_select_form(request)() + group_form = self.get_obj_perms_group_select_form(request)() + + context = self.get_obj_perms_base_context(request, obj) + context['users_perms'] = users_perms + context['groups_perms'] = groups_perms + context['user_form'] = user_form + context['group_form'] = group_form + + request.current_app = self.admin_site.name + +~~ return render(request, self.get_obj_perms_manage_template(), context) + + def get_obj_perms_manage_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage.html' + return self.obj_perms_manage_template + + def obj_perms_manage_user_view(self, request, object_pk, user_id): + if not self.has_change_permission(request, None): + post_url = reverse('admin:index', current_app=self.admin_site.name) + return redirect(post_url) + + user = get_object_or_404(get_user_model(), pk=user_id) + obj = get_object_or_404(self.get_queryset(request), pk=object_pk) + form_class = self.get_obj_perms_manage_user_form(request) + form = form_class(user, obj, request.POST or None) + + if request.method == 'POST' and form.is_valid(): + form.save_obj_perms() + msg = gettext("Permissions saved.") + messages.success(request, msg) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + url = reverse( + '%s:%s_%s_permissions_manage_user' % info, + args=[obj.pk, user.pk] + ) + return redirect(url) + + context = self.get_obj_perms_base_context(request, obj) + context['user_obj'] = user + context['user_perms'] = get_user_perms(user, obj) + context['form'] = form + + request.current_app = self.admin_site.name + +~~ return render(request, self.get_obj_perms_manage_user_template(), context) + + def get_obj_perms_manage_user_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage_user.html' + return self.obj_perms_manage_user_template + + def get_obj_perms_user_select_form(self, request): + return UserManage + + def get_obj_perms_group_select_form(self, request): + return GroupManage + + def get_obj_perms_manage_user_form(self, request): + return AdminUserObjectPermissionsForm + + def obj_perms_manage_group_view(self, request, object_pk, group_id): + if not self.has_change_permission(request, None): + post_url = reverse('admin:index', current_app=self.admin_site.name) + return redirect(post_url) + + group = get_object_or_404(Group, id=group_id) + obj = get_object_or_404(self.get_queryset(request), pk=object_pk) + form_class = self.get_obj_perms_manage_group_form(request) + form = form_class(group, obj, request.POST or None) + + if request.method == 'POST' and form.is_valid(): + form.save_obj_perms() + msg = gettext("Permissions saved.") + messages.success(request, msg) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + url = reverse( + '%s:%s_%s_permissions_manage_group' % info, + args=[obj.pk, group.id] + ) + return redirect(url) + + context = self.get_obj_perms_base_context(request, obj) + context['group_obj'] = group + context['group_perms'] = get_group_perms(group, obj) + context['form'] = form + + request.current_app = self.admin_site.name + +~~ return render(request, self.get_obj_perms_manage_group_template(), context) + + def get_obj_perms_manage_group_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage_group.html' + return self.obj_perms_manage_group_template + + def get_obj_perms_manage_group_form(self, request): + return AdminGroupObjectPermissionsForm + + +class GuardedModelAdmin(GuardedModelAdminMixin, admin.ModelAdmin): + + +class UserManage(forms.Form): + user = forms.CharField(label=_("User identification"), + max_length=200, + error_messages={'does_not_exist': _( + "This user does not exist")}, + help_text=_( + 'Enter a value compatible with User.USERNAME_FIELD') + ) + + def clean_user(self): + identification = self.cleaned_data['user'] + + +## ... source file continues with no further render examples... + +``` + + +## Example 7 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / admin.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./admin.py) + +```python +# admin.py +from django.contrib.admin.options import ModelAdmin, csrf_protect_m +from django.contrib.admin.views.main import SEARCH_VAR, ChangeList +from django.core.exceptions import PermissionDenied +from django.core.paginator import InvalidPage, Paginator +~~from django.shortcuts import render +from django.utils.encoding import force_str +from django.utils.translation import ungettext + +from haystack import connections +from haystack.constants import DEFAULT_ALIAS +from haystack.query import SearchQuerySet +from haystack.utils import get_model_ct_tuple + + +class SearchChangeList(ChangeList): + def __init__(self, **kwargs): + self.haystack_connection = kwargs.pop("haystack_connection", DEFAULT_ALIAS) + super(SearchChangeList, self).__init__(**kwargs) + + def get_results(self, request): + if SEARCH_VAR not in request.GET: + return super(SearchChangeList, self).get_results(request) + + sqs = ( + SearchQuerySet(self.haystack_connection) + .models(self.model) + .auto_query(request.GET[SEARCH_VAR]) + .load_all() + ) + + +## ... source file abbreviated to get to render examples ... + + + "%(total_count)s selected", + "All %(total_count)s selected", + changelist.result_count, + ) + + context = { + "module_name": force_str(self.model._meta.verbose_name_plural), + "selection_note": selection_note % {"count": len(changelist.result_list)}, + "selection_note_all": selection_note_all + % {"total_count": changelist.result_count}, + "title": changelist.title, + "is_popup": changelist.is_popup, + "cl": changelist, + "media": media, + "has_add_permission": self.has_add_permission(request), + "opts": changelist.opts, + "app_label": self.model._meta.app_label, + "action_form": action_form, + "actions_on_top": self.actions_on_top, + "actions_on_bottom": self.actions_on_bottom, + "actions_selection_counter": getattr(self, "actions_selection_counter", 0), + } + context.update(extra_context or {}) + request.current_app = self.admin_site.name + app_name, model_name = get_model_ct_tuple(self.model) +~~ return render( + request, + self.change_list_template + or [ + "admin/%s/%s/change_list.html" % (app_name, model_name), + "admin/%s/change_list.html" % app_name, + "admin/change_list.html", + ], + context, + ) + + +class SearchModelAdmin(SearchModelAdminMixin, ModelAdmin): + pass + + + +## ... source file continues with no further render examples... + +``` + + +## Example 8 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / views / base.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/views/base.py) + +```python +# base.py +import json +import logging +import urllib.parse + +from django.contrib.auth.mixins import LoginRequiredMixin +from django.http import HttpResponse, JsonResponse +~~from django.shortcuts import render +from django.urls import reverse +from django.utils import timezone +from django.utils.decorators import method_decorator +from django.views.decorators.csrf import csrf_exempt +from django.views.decorators.debug import sensitive_post_parameters +from django.views.generic import FormView, View + +from ..exceptions import OAuthToolkitError +from ..forms import AllowForm +from ..http import OAuth2ResponseRedirect +from ..models import get_access_token_model, get_application_model +from ..scopes import get_scopes_backend +from ..settings import oauth2_settings +from ..signals import app_authorized +from .mixins import OAuthLibMixin + + +log = logging.getLogger("oauth2_provider") + + +class BaseAuthorizationView(LoginRequiredMixin, OAuthLibMixin, View): + + def dispatch(self, request, *args, **kwargs): + self.oauth2_data = {} + + +## ... source file abbreviated to get to render examples ... + + + return self.error_response(error, application) + + return self.render_to_response(self.get_context_data(**kwargs)) + + def redirect(self, redirect_to, application, token=None): + + if not redirect_to.startswith("urn:ietf:wg:oauth:2.0:oob"): + return super().redirect(redirect_to, application) + + parsed_redirect = urllib.parse.urlparse(redirect_to) + code = urllib.parse.parse_qs(parsed_redirect.query)["code"][0] + + if redirect_to.startswith("urn:ietf:wg:oauth:2.0:oob:auto"): + + response = { + "access_token": code, + "token_uri": redirect_to, + "client_id": application.client_id, + "client_secret": application.client_secret, + "revoke_uri": reverse("oauth2_provider:revoke-token"), + } + + return JsonResponse(response) + + else: +~~ return render( + request=self.request, + template_name="oauth2_provider/authorized-oob.html", + context={ + "code": code, + }, + ) + + +@method_decorator(csrf_exempt, name="dispatch") +class TokenView(OAuthLibMixin, View): + server_class = oauth2_settings.OAUTH2_SERVER_CLASS + validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS + oauthlib_backend_class = oauth2_settings.OAUTH2_BACKEND_CLASS + + @method_decorator(sensitive_post_parameters("password")) + def post(self, request, *args, **kwargs): + url, headers, body, status = self.create_token_response(request) + if status == 200: + access_token = json.loads(body).get("access_token") + if access_token is not None: + token = get_access_token_model().objects.get( + token=access_token) + app_authorized.send( + sender=self, request=request, + + +## ... source file continues with no further render examples... + +``` + + +## Example 9 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / views.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./views.py) + +```python +# views.py +import re +import six +from collections import Counter + +try: + from django.urls import reverse_lazy +except ImportError: + from django.core.urlresolvers import reverse_lazy + +import django +from django.db import DatabaseError +from django.db.models import Count +from django.forms.models import model_to_dict +from django.http import HttpResponse, JsonResponse, HttpResponseRedirect, Http404 +~~from django.shortcuts import get_object_or_404, render +from django.views.decorators.http import require_POST +from django.utils.decorators import method_decorator +from django.views.generic import ListView +from django.views.generic.base import View +from django.views.generic.edit import CreateView, DeleteView +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.core.exceptions import ImproperlyConfigured +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.auth.views import LoginView + +from explorer import app_settings +from explorer.connections import connections +from explorer.exporters import get_exporter_class +from explorer.forms import QueryForm +from explorer.models import Query, QueryLog, MSG_FAILED_BLACKLIST +from explorer.tasks import execute_query +from explorer.utils import ( + url_get_rows, + url_get_query_id, + url_get_log_id, + url_get_params, + safe_login_prompt, + fmt_sql, + allowed_query_pks, + url_get_show, + url_get_fullscreen +) + +from explorer.schema import schema_info +from explorer import permissions + + +class ExplorerContextMixin(object): + + def gen_ctx(self): + return {'can_view': app_settings.EXPLORER_PERMISSION_VIEW(self.request.user), + 'can_change': app_settings.EXPLORER_PERMISSION_CHANGE(self.request.user)} + + def get_context_data(self, **kwargs): + ctx = super(ExplorerContextMixin, self).get_context_data(**kwargs) + ctx.update(self.gen_ctx()) + return ctx + + def render_template(self, template, ctx): + ctx.update(self.gen_ctx()) +~~ return render(self.request, template, ctx) + + +class PermissionRequiredMixin(object): + + permission_required = None + + def get_permission_required(self): + if self.permission_required is None: + raise ImproperlyConfigured( + '{0} is missing the permission_required attribute. Define {0}.permission_required, or override ' + '{0}.get_permission_required().'.format(self.__class__.__name__) + ) + return self.permission_required + + def has_permission(self, request, *args, **kwargs): + perms = self.get_permission_required() + handler = getattr(permissions, perms) # TODO: fix the case when the perms is + return handler(request, *args, **kwargs) + + def handle_no_permission(self, request): + return SafeLoginView.as_view( + extra_context={'title': 'Log in', REDIRECT_FIELD_NAME: request.get_full_path()})(request) + + def dispatch(self, request, *args, **kwargs): + + +## ... source file abbreviated to get to render examples ... + + + + permission_required = 'view_permission' + + def post(self, request, query_id, *args, **kwargs): + if request.is_ajax(): + email = request.POST.get('email', None) + if email: + execute_query.delay(query_id, email) + return JsonResponse({'message': 'message was sent successfully'}) + return JsonResponse({}, status=403) + + +class SchemaView(PermissionRequiredMixin, View): + permission_required = 'change_permission' + + @method_decorator(xframe_options_sameorigin) + def dispatch(self, *args, **kwargs): + return super(SchemaView, self).dispatch(*args, **kwargs) + + def get(self, request, *args, **kwargs): + connection = kwargs.get('connection') + if connection not in connections: + raise Http404 + schema = schema_info(connection) + if schema: +~~ return render(None, 'explorer/schema.html', + {'schema': schema_info(connection)}) + else: +~~ return render(None, 'explorer/schema_building.html') + + +@require_POST +def format_sql(request): + sql = request.POST.get('sql', '') + formatted = fmt_sql(sql) + return JsonResponse({"formatted": formatted}) + + +class ListQueryView(PermissionRequiredMixin, ExplorerContextMixin, ListView): + + permission_required = 'view_permission_list' + + def recently_viewed(self): + qll = QueryLog.objects.filter(run_by_user=self.request.user, query_id__isnull=False).order_by( + '-run_at').select_related('query') + ret = [] + tracker = [] + for ql in qll: + if len(ret) == app_settings.EXPLORER_RECENT_QUERY_COUNT: + break + + if ql.query_id not in tracker: + ret.append(ql) + + +## ... source file abbreviated to get to render examples ... + + +class PlayQueryView(PermissionRequiredMixin, ExplorerContextMixin, View): + + permission_required = 'change_permission' + + def get(self, request): + if url_get_query_id(request): + query = get_object_or_404(Query, pk=url_get_query_id(request)) + return self.render_with_sql(request, query, run_query=False) + + if url_get_log_id(request): + log = get_object_or_404(QueryLog, pk=url_get_log_id(request)) + query = Query(sql=log.sql, title="Playground", connection=log.connection) + return self.render_with_sql(request, query) + + return self.render() + + def post(self, request): + sql = request.POST.get('sql') + show = url_get_show(request) + query = Query(sql=sql, title="Playground", connection=request.POST.get('connection')) + passes_blacklist, failing_words = query.passes_blacklist() + error = MSG_FAILED_BLACKLIST % ', '.join(failing_words) if not passes_blacklist else None + run_query = not bool(error) if show else False + return self.render_with_sql(request, query, run_query=run_query, error=error) + +~~ def render(self): + return self.render_template('explorer/play.html', {'title': 'Playground', 'form': QueryForm()}) + + def render_with_sql(self, request, query, run_query=True, error=None): + rows = url_get_rows(request) + fullscreen = url_get_fullscreen(request) + template = 'fullscreen' if fullscreen else 'play' + form = QueryForm(request.POST if len(request.POST) else None, instance=query) + return self.render_template('explorer/%s.html' % template, query_viewmodel(request.user, + query, + title="Playground", + run_query=run_query, + error=error, + rows=rows, + form=form)) + + +class QueryView(PermissionRequiredMixin, ExplorerContextMixin, View): + + permission_required = 'view_permission' + + def get(self, request, query_id): + query, form = QueryView.get_instance_and_form(request, query_id) + query.save() # updates the modified date + show = url_get_show(request) + + +## ... source file continues with no further render examples... + +``` + + +## Example 10 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / accounts.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/accounts.py) + +```python +# accounts.py +from django.conf import settings as django_settings +from django.contrib import messages +from django.contrib.auth import get_user_model +from django.contrib.auth import login as auth_login +from django.contrib.auth import logout as auth_logout +from django.contrib.auth.forms import AuthenticationForm +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +~~from django.shortcuts import render +from django.urls import reverse +from django.utils.translation import gettext as _ +from django.views.generic import CreateView +from django.views.generic import FormView +from django.views.generic import UpdateView +from django.views.generic import View +from wiki import forms +from wiki.conf import settings + +User = get_user_model() + + +class Signup(CreateView): + model = User + form_class = forms.UserCreationForm + template_name = "wiki/accounts/signup.html" + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_anonymous and not request.user.is_superuser: + return redirect("wiki:root") + if not settings.ACCOUNT_HANDLING: + return redirect(settings.SIGNUP_URL) + if not request.user.is_superuser and not settings.ACCOUNT_SIGNUP_ALLOWED: + c = {"error_msg": _("Account signup is only allowed for administrators.")} +~~ return render(request, "wiki/error.html", context=c) + + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["honeypot_class"] = context["form"].honeypot_class + context["honeypot_jsfunction"] = context["form"].honeypot_jsfunction + return context + + def get_success_url(self, *args): + messages.success( + self.request, _("You are now signed up... and now you can sign in!") + ) + return reverse("wiki:login") + + +class Logout(View): + def dispatch(self, request, *args, **kwargs): + if not settings.ACCOUNT_HANDLING: + return redirect(settings.LOGOUT_URL) + return super().dispatch(request, *args, **kwargs) + + def get(self, request, *args, **kwargs): + auth_logout(request) + + +## ... source file continues with no further render examples... + +``` + + +## Example 11 from dmd-interpreter +[dmd-interpreter](https://github.com/mitchalexbailey/dmd-interpreter) +([running web app](http://www.dmd.nl/DOVE)) +is a Python tool to aggregate clinically relevant information related +to variants in the DMD gene and display that [data](/data.html) to a user +with a [Django](/django.html) web application. + +[**dmd-interpreter / interpreter / views.py**](https://github.com/mitchalexbailey/dmd-interpreter/blob/master/interpreter/./views.py) + +```python +# views.py +~~from django.shortcuts import get_object_or_404, render +from django.http import HttpResponseRedirect, HttpResponse +from django.template import RequestContext, loader +from django.core.urlresolvers import reverse +from .forms import IndexForm, ACMGForm + +from interpreter_functions import * +import os,sys +import subprocess +import csv +import re +import pprint + +interpreter_dir = os.path.dirname(__file__) + +def index(request): + if request.method == "POST": + user = request.POST.get('user', None) +~~ return render(request, 'index.html') + + +def results(request): + if request.method == 'POST': + mut = request.POST.get('mutation', None) + + ucsc_info = [12, 'NM_004006', 'chrX', '-', 31137344, 33229673, 31140035, 33229429, 79, '31137344,31144758,31152218,31164407,31165391,31187559,31190464,31191655,31196048,31196785,31198486,31200854,31222077,31224698,31227614,31241163,31279071,31341714,31366672,31462597,31496222,31497099,31514904,31525397,31645789,31676106,31697491,31747747,31792076,31838091,31854834,31893307,31947712,31950196,31986455,32235032,32305645,32328198,32360216,32361250,32364059,32366522,32380904,32382698,32383136,32398626,32404426,32407617,32408187,32429868,32456357,32459296,32466572,32472778,32481555,32482702,32486614,32490280,32503035,32509393,32519871,32536124,32563275,32583818,32591646,32591861,32613873,32632419,32662248,32663080,32715986,32717228,32827609,32834584,32841411,32862899,32867844,33038255,33229398,', '31140047,31144790,31152311,31164531,31165635,31187718,31190530,31191721,31196087,31196922,31198598,31201021,31222235,31224784,31227816,31241238,31279133,31341775,31366751,31462744,31496491,31497220,31515061,31525570,31645979,31676261,31697703,31747865,31792309,31838200,31854939,31893490,31947862,31950344,31986631,32235180,32305818,32328393,32360399,32361403,32364197,32366645,32381075,32382827,32383316,32398797,32404582,32407791,32408298,32430030,32456507,32459431,32466755,32472949,32481711,32482816,32486827,32490426,32503216,32509635,32519959,32536248,32563451,32583998,32591754,32591963,32613993,32632570,32662430,32663269,32716115,32717410,32827728,32834757,32841504,32862977,32867937,33038317,33229673,', 0, 'DMD', 'cmpl', 'cmpl', '0,1,1,0,2,2,2,2,2,0,2,0,1,2,1,1,2,1,0,0,1,0,2,0,2,0,1,0,1,0,0,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,2,0,0,0,1,2,0,0,0,0,1,0,'] + + + + f = open(os.path.join(interpreter_dir, "rescue_esesites.txt")) + ese_sites = [] + for line in f: + temp = '' + for char in line: + if char != "\n": + temp += char + temp = ''.join(temp) + ese_sites += [temp] + f.close() + + f = open(os.path.join(interpreter_dir, "esssites.txt")) + ess_sites = [] + for line in f: + + +## ... source file abbreviated to get to render examples ... + + + provean = 'Not missense' + metasvm = 'Not missense' + nsfp_score = '' + nsfp_message = '' + cv = '' + consequence = '' + consequence_statement = '' + ese_message = '' + esefinder = '' + rescueese = '' + ess_message = '' + splice_message = '' + splice_message2 = '' + motif_message = '' + ds = '' + splice_result = [] + long_aa_change = [] + readthrough_elig = "Not eligible" + + ex_input = exoninput(mut) + mutype, search = type_inp(mut, ex_input) + num_list, intron_list = parse(mut, mutype, exon_positions, ex_input) + + + if mutype == "Invalid mutation" and len(num_list) == 0: +~~ return render(request, 'index.html',{'success':False}) + else: + pass + + + for num in num_list: + if int(num) > 3685*3 and not ex_input: #AA length *3 + past_max = True + elif int(num) > len_ref: + past_max = True + else: + pass + + + intron_only = intron_count(intron_list, num_list) + + + if (mutype == "Deletion" or mutype == "Duplication") and "c." not in mut and len(num_list) > 0 and not ex_input and "Nucleotide" not in mut: + if max(num_list) < 80 and not ex_input: + with open(os.path.join(interpreter_dir, 'templates/triage.html'), 'w') as g: + num_list = re.findall("\d+", mut) + g.write("""

You entered: '""") + g.write(mut) + g.write("""'


Did you mean...

'""") + temp = '' + temp += mutype + if len(num_list) == 1: + temp += " of exon " + temp += str(num_list[0]) + if len(num_list) > 1: + temp += " of exons " + temp += str(min(num_list)) + temp += "-" + temp += str(max(num_list)) + g.write(temp) + g.write("""'?


{% csrf_token %}{% csrf_token %}
""") + g.closed +~~ return render(request, 'index.html', {'triage':True}) + + + + if past_max or mutype == "Invalid mutation": + with open(os.path.join(interpreter_dir, 'templates/triage.html'), 'w') as g: + g.write("""

You entered: '""") + g.write(mut) + g.write("""'

Did you mean...
""") + + if past_max: + g.write(("""

A smaller number?


You entered: %s""" % str(max(num_list))) + """
Which is larger than the length of the DMD, Dp427m coding sequence (11055 nt)

Please enter your revised mutation below, or return to the previous page to try the "Exon deletion selector" feature.

{% csrf_token %}

""") + + if mutype == "Invalid mutation" and not past_max and len(num_list)>0:# and not ex_input: + tridel = "Deletion of Nucleotide(s) " + tridelex = "Deletion of Exon(s) " + tridup = "Duplication of Nucleotide(s) " + tridupex = "Duplication of Exon(s) " + triins = "Insertion at Nucleotide position(s) " + tridelins = "Deletion/Insertion at Nucleotide position(s) " + tripoint = "Point mutation at Nucleotide position(s) " + if len(num_list) == 1: + tridel += str(num_list[0]) + tridup += str(num_list[0]) + tridelex += str(num_list[0]) + + +## ... source file abbreviated to get to render examples ... + + + + g.write("
") + + g.write("
") + + g.write("
") + + g.write("
""") + + g.closed +~~ return render(request, 'index.html', {'triage':True}) + + if mutype != "Invalid mutation" and len(num_list) == 0 and not intron_only: + with open(os.path.join(interpreter_dir, 'templates/triage.html'), 'w') as g: + g.write("""

You entered: '""") + g.write(mut) + g.write("'



This mutation type (") + g.write(mutype) + g.write(""") requires a position to be interpreted.



Please complete the mutation in the box below, or return to the previous page to try the "Exon deletion selector" feature.

{% csrf_token %}
*Note that the symbol '>' denotes point mutation*

""") + g.closed +~~ return render(request, 'index.html', {'triage':True}) + + if not past_max and mutype != "Invalid mutation": # and len(num_list) != 0: + if intron_only: + missense = False + nonsense = False + silent = True + frame_shift = False + length_mutation, pm_change, pm_pre = get_length(mut, mutype, num_list, mut, ex_input, reference_cdna) + positions_in_genomic1, positions_in_genomic2, positions_in_genomic3 = cdna2gen(num_list, exon_positions, genomic_positions1, genomic_positions2, genomic_positions3, intron_list) + ghgvs, ghgvs19 = HGVS(positions_in_genomic2, positions_in_genomic3, mutype, search, length_mutation, ex_input, [[],[]], pm_change, pm_pre, True) + + + if mutype == "Point mutation" and len(pm_pre) == 0: + if mutype == "Point mutation" or mutype == "Deletion/Insertion": + if len(num_list) == 1: + pm_pre = genomic_dna[min(positions_in_genomic1)] + if len(num_list)>1: + pm_pre = genomic_dna[min(positions_in_genomic1):max(positions_in_genomic1)] + else: + if len(num_list) == 1: + pm_change = genomic_dna[min(positions_in_genomic1)] + if len(num_list)>1 and length_mutation < 4: + pm_change = genomic_dna[min(positions_in_genomic1):max(positions_in_genomic1)] + cDNA, mut_genomic_dna = alter_cDNA(reference_cdna, num_list, positions_in_genomic1, length_mutation, mutype, pm_change, genomic_dna, intron_only) + + +## ... source file abbreviated to get to render examples ... + + + if mutype == "Deletion" or mutype == "Duplication": + if len(num_list) == 1: + pm_change = genomic_dna[min(positions_in_genomic1)] + if len(num_list)>1 and length_mutation < 4: + pm_change = genomic_dna[min(positions_in_genomic1)-1:max(positions_in_genomic1)] + cDNA, mut_genomic_dna = alter_cDNA(reference_cdna, num_list, positions_in_genomic1, length_mutation, mutype, pm_change, genomic_dna, intron_only) + if ("Insertion" in mutype or mutype == "Point mutation") and len(pm_change) == 0: + with open(os.path.join(interpreter_dir, 'templates/triage.html'), 'w') as g: + g.write("""

You entered: '""") + g.write(mut) + g.write("""'

This mutation type requires that you input the inserted nucleotides (i.e. an A, T, G, C or combination thereof).



Please add the inserted bases in the box below, or return to the previous page to try the "Exon deletion selector" feature.

{% csrf_token %}

""") + g.closed +~~ return render(request, 'index.html', {'triage':True}) + frame_shift = frame(length_mutation, mutype, num_list) + exon_numbers = [] + exon_ints = [] + if (mutype == "Deletion" or mutype == "Duplication"): + exon_numbers, part = exons(num_list, exon_positions, ex_input, mut, part) + if len(exon_numbers) != 0: + for item in exon_numbers: + exon_ints += [int(item)] + temp = str(exon_numbers[0]), "-", str(exon_numbers[len(exon_numbers)-1]) + temp = ''.join(temp) + standard_hgvs, catcher = HGVS(num_list, num_list, mutype, search, length_mutation, ex_input, intron_list, pm_change, pm_pre) + mv_results = myVariantSearch(standard_hgvs) + CV = ClinVar(mv_results, standard_hgvs) + aa_ref = translate(reference_cdna[244:]) + nsfp_results, path_pred = gen_point(positions_in_genomic1, complement(pm_change), intron_only, length_mutation, NSFP) + + if mutype == "Deletion" and len(num_list) != 0: + cDNA, mut_genomic_dna = alter_cDNA(reference_cdna, num_list, positions_in_genomic1, length_mutation, mutype, pm_change, genomic_dna, intron_only) + aa_seq = translate(cDNA[244:]) + if frame_shift == False: + aa_length = (length_mutation)/3 + i = 0 + filler = '' + while i < aa_length: + + +## ... source file abbreviated to get to render examples ... + + + + + if len(posskip)>0 and frame_shift: + if part == True: + posskip = [] + if part and ex_input: + print part + posskip = [] + posskip += ["This variant includes a partial exon deletion."] + elif not frame_shift: + posskip = [] + posskip += ["There is no frameshift predicted."] + elif length_mutation < 32: + posskip = [] + posskip += ["This variant type (missense; nonsense; small insertion, deletion, indel; or splice-affecting) has not been clinically tested in DMD with exon skip therapy."] + elif len(posskip) == 0 and length_mutation >= 32: + posskip += ["There are no theoretical exon skips predicted to apply to this mutation."] + + if nonsense and not frame_shift: + readthrough_elig = "Eligible" + else: + pass + + + else: +~~ return render(request, 'index.html',{'success':False}) + + + if mutype != "Deletion" and mutype != "Deletion/Insertion" and mutype != "Duplication" and not intron_only: + temp_cdna = "",cDNA[0:min(num_list)+243],"",cDNA[min(num_list)+243:min(num_list)+243+length_mutation],"",cDNA[max(num_list)+243+length_mutation:len(cDNA)],"" + if mutype == "Point mutation (insertion)": + temp_cdna = "",cDNA[0:max(num_list)+244],"",cDNA[max(num_list)+244:max(num_list)+244+length_mutation],"",cDNA[max(num_list)+244+length_mutation:len(cDNA)],"" + if mutype == "Duplication" and not intron_only: + temp_cdna = "",cDNA[0:min(num_list)+244],"",cDNA[min(num_list)+244:min(num_list)+244+(length_mutation)],"",cDNA[min(num_list)+244+(length_mutation):min(num_list)+244+(length_mutation*2)],"",cDNA[min(num_list)+244+(length_mutation*2):len(cDNA)],"" + if mutype == "Insertion" and not intron_only: + temp_cdna = "",cDNA[0:min(num_list)+243],"",cDNA[min(num_list)+244:min(num_list)+244+length_mutation],"",cDNA[max(num_list)+244+length_mutation:len(cDNA)],"" + if mutype == "Deletion" and not intron_only: + fill = '' + i = 0 + while i",fill,"",cDNA[min(num_list)+244:len(cDNA)],"" + if intron_only: + temp_refcdna = "",reference_cdna,"" + temp_cdna = temp_refcdna + refcdna_for_print = ''.join(temp_refcdna) + if mutype == "Deletion/Insertion" and not intron_only: + i = 0 + fill = '' + + +## ... source file abbreviated to get to render examples ... + + + standard_hgvs_search = ''.join(standard_hgvs_search) + leiden_link ="https://databases.lovd.nl/shared/variants/DMD/unique?search_var_status=%3D%22Marked%22%7C%3D%22Public%22#object_id=VariantOnTranscriptUnique%2CVariantOnGenome&id=DMD&order=VariantOnTranscript%2FDNA%2CASC&skip[chromosome]=chromosome&skip[allele_]=allele_&skip[transcriptid]=transcriptid&search_transcriptid=00000024&skip[owner_countryid]=owner_countryid&FRMatchType_CustomVL_VOTunique_VOG_DMD=1&FRMatchType_CustomVL_VOTunique_VOG_DMD=2&FRMatchType_CustomVL_VOTunique_VOG_DMD=3&FRReplaceAll_CustomVL_VOTunique_VOG_DMD=1&=Preview&=Cancel&=Submit&search_VariantOnTranscript/DNA="+standard_hgvs_search + iframe = "" + elif length_mutation > 30 and mutype != "Deletion/Insertion": + leiden_link = "https://databases.lovd.nl/shared/variants/DMD/unique?search_var_status=%3D%22Marked%22%7C%3D%22Public%22#object_id=VariantOnTranscriptUnique%2CVariantOnGenome&id=DMD&order=VariantOnTranscript%2FDNA%2CASC&skip[chromosome]=chromosome&skip[allele_]=allele_&skip[transcriptid]=transcriptid&search_transcriptid=00000024&skip[owner_countryid]=owner_countryid&FRMatchType_CustomVL_VOTunique_VOG_DMD=1&FRMatchType_CustomVL_VOTunique_VOG_DMD=2&FRMatchType_CustomVL_VOTunique_VOG_DMD=3&FRReplaceAll_CustomVL_VOTunique_VOG_DMD=1&=Preview&=Cancel&=Submit&search_VariantOnTranscript/DNA="+search_nums+"%20"+search + iframe = "" + elif length_mutation < 30 and mutype != "Point mutation": + leiden_link = "https://databases.lovd.nl/shared/variants/DMD/unique?search_var_status=%3D%22Marked%22%7C%3D%22Public%22#object_id=VariantOnTranscriptUnique%2CVariantOnGenome&id=DMD&order=VariantOnTranscript%2FDNA%2CASC&skip[chromosome]=chromosome&skip[allele_]=allele_&skip[transcriptid]=transcriptid&search_transcriptid=00000024&skip[owner_countryid]=owner_countryid&FRMatchType_CustomVL_VOTunique_VOG_DMD=1&FRMatchType_CustomVL_VOTunique_VOG_DMD=2&FRMatchType_CustomVL_VOTunique_VOG_DMD=3&FRReplaceAll_CustomVL_VOTunique_VOG_DMD=1&=Preview&=Cancel&=Submit&search_VariantOnTranscript/DNA="+standard_hgvs_search + iframe = "" + else: + leiden_link = "https://databases.lovd.nl/shared/variants/DMD/unique?search_var_status=%3D%22Marked%22%7C%3D%22Public" + iframe = "" + + if nsfp_score == '': + nsfp_score = 'N/A' + else: + pass + + try: + mv_results = mv_results[0] + mv_results_formatted = pprint.pformat(mv_results, indent=4) + mv_disable = False + except: + mv_results_formatted = "No myVariantInfo results available" + mv_disable = True +~~ return render(request, 'main.html', + {'user_inp':mut, + 'mutype':mutype, + 'hgvs':standard_hgvs, + 'ghgvs':ghgvs, + 'ghgvs19':ghgvs19, + 'length_mutation':length_mutation, + 'exons': exon_numbers, + 'domains':ds, + 'therapy':therapy, + 'insilico_message':insilico_message, + 'splice_message':splice_message, + 'ese_message':ese_message, + 'consequence':consequence, + 'consequence_message':consequence_statement, + 'cv':cv, + 'leiden_link':leiden_link, + 'leiden_frame':iframe, + 'cdna_for_print':cdna_for_print, #full mutated sequence + 'cdna_print_preview':cdna_print_preview, #partial mutated + 'refcdna_for_print':refcdna_for_print, #full wt cdna + 'refcdna_print_preview':refcdna_print_preview, #wt preview + 'readthrough_elig':readthrough_elig, + 'posskip':posskip, #list of skips (empty if there are none) + 'sift':sift, + + +## ... source file continues with no further render examples... + +``` + diff --git a/content/pages/examples/django/django-shortcuts-resolve-url.markdown b/content/pages/examples/django/django-shortcuts-resolve-url.markdown new file mode 100644 index 000000000..b090f13f9 --- /dev/null +++ b/content/pages/examples/django/django-shortcuts-resolve-url.markdown @@ -0,0 +1,135 @@ +title: django.shortcuts resolve_url Example Code +category: page +slug: django-shortcuts-resolve-url-examples +sortorder: 500011349 +toc: False +sidebartitle: django.shortcuts resolve_url +meta: Python example code for the resolve_url callable from the django.shortcuts module of the Django project. + + +resolve_url is a callable within the django.shortcuts module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / adapter.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/adapter.py) + +```python +# adapter.py +from __future__ import unicode_literals + +import hashlib +import json +import time +import warnings + +from django import forms +from django.conf import settings +from django.contrib import messages +from django.contrib.auth import ( + authenticate, + get_backends, + login as django_login, + logout as django_logout, +) +from django.contrib.auth.models import AbstractUser +from django.contrib.auth.password_validation import validate_password +from django.contrib.sites.shortcuts import get_current_site +from django.core.cache import cache +from django.core.mail import EmailMessage, EmailMultiAlternatives +from django.http import HttpResponse, HttpResponseRedirect +~~from django.shortcuts import resolve_url +from django.template import TemplateDoesNotExist +from django.template.loader import render_to_string +from django.urls import reverse +from django.utils import timezone +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +from ..utils import ( + build_absolute_uri, + email_address_exists, + generate_unique_username, + get_user_model, + import_attribute, +) +from . import app_settings + + +class DefaultAccountAdapter(object): + + error_messages = { + 'username_blacklisted': + _('Username can not be used. Please use other username.'), + 'username_taken': + AbstractUser._meta.get_field('username').error_messages['unique'], + + +## ... source file abbreviated to get to resolve_url examples ... + + + from_email, + [email]) + if 'html' in bodies: + msg.attach_alternative(bodies['html'], 'text/html') + else: + msg = EmailMessage(subject, + bodies['html'], + from_email, + [email]) + msg.content_subtype = 'html' # Main content is now text/html + return msg + + def send_mail(self, template_prefix, email, context): + msg = self.render_mail(template_prefix, email, context) + msg.send() + + def get_login_redirect_url(self, request): + assert request.user.is_authenticated + url = getattr(settings, "LOGIN_REDIRECT_URLNAME", None) + if url: + warnings.warn("LOGIN_REDIRECT_URLNAME is deprecated, simply" + " use LOGIN_REDIRECT_URL with a URL name", + DeprecationWarning) + else: + url = settings.LOGIN_REDIRECT_URL +~~ return resolve_url(url) + + def get_logout_redirect_url(self, request): +~~ return resolve_url(app_settings.LOGOUT_REDIRECT_URL) + + def get_email_confirmation_redirect_url(self, request): + if request.user.is_authenticated: + if app_settings.EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL: + return \ + app_settings.EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL + else: + return self.get_login_redirect_url(request) + else: + return app_settings.EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL + + def is_open_for_signup(self, request): + return True + + def new_user(self, request): + user = get_user_model()() + return user + + def populate_username(self, request, user): + from .utils import user_username, user_email, user_field + first_name = user_field(user, 'first_name') + last_name = user_field(user, 'last_name') + email = user_email(user) + username = user_username(user) + + +## ... source file continues with no further resolve_url examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-context.markdown b/content/pages/examples/django/django-template-base-context.markdown new file mode 100644 index 000000000..98338234d --- /dev/null +++ b/content/pages/examples/django/django-template-base-context.markdown @@ -0,0 +1,67 @@ +title: django.template.base Context Example Code +category: page +slug: django-template-base-context-examples +sortorder: 500011363 +toc: False +sidebartitle: django.template.base Context +meta: Python example code for the Context class from the django.template.base module of the Django project. + + +Context is a class within the django.template.base module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / templatetags / pipeline.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/templatetags/pipeline.py) + +```python +# pipeline.py +import logging +import subprocess + +from django.contrib.staticfiles.storage import staticfiles_storage + +from django import template +~~from django.template.base import Context, VariableDoesNotExist +from django.template.loader import render_to_string +from django.utils.safestring import mark_safe + +from ..collector import default_collector +from ..conf import settings +from ..exceptions import CompilerError +from ..packager import Packager, PackageNotFound +from ..utils import guess_type + +logger = logging.getLogger(__name__) + +register = template.Library() + + +class PipelineMixin(object): + request = None + _request_var = None + + @property + def request_var(self): + if not self._request_var: + self._request_var = template.Variable('request') + return self._request_var + + + +## ... source file continues with no further Context examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-filterexpression.markdown b/content/pages/examples/django/django-template-base-filterexpression.markdown new file mode 100644 index 000000000..6a5d325a2 --- /dev/null +++ b/content/pages/examples/django/django-template-base-filterexpression.markdown @@ -0,0 +1,111 @@ +title: django.template.base FilterExpression Example Code +category: page +slug: django-template-base-filterexpression-examples +sortorder: 500011370 +toc: False +sidebartitle: django.template.base FilterExpression +meta: Example code for understanding how to use the FilterExpression class from the django.template.base module of the Django project. + + +`FilterExpression` is a class within the `django.template.base` module of the Django project. + +Context, +Node, +NodeList, +Parser, +Template, +TemplateSyntaxError, +TextNode, +Token, +TokenType, +VariableDoesNotExist, +VariableNode, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / templatetags / sitetree.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/templatetags/sitetree.py) + +```python +# sitetree.py +from django import template +~~from django.template.base import FilterExpression +from django.template.loader import get_template + +from ..sitetreeapp import get_sitetree + +register = template.Library() + + +@register.tag +def sitetree_tree(parser, token): + tokens = token.split_contents() + use_template = detect_clause(parser, 'template', tokens) + tokens_num = len(tokens) + + if tokens_num in (3, 5): + tree_alias = parser.compile_filter(tokens[2]) + return sitetree_treeNode(tree_alias, use_template) + else: + raise template.TemplateSyntaxError( + '%r tag requires two arguments. E.g. {%% sitetree_tree from "mytree" %%}.' % tokens[0]) + + +@register.tag +def sitetree_children(parser, token): + tokens = token.split_contents() + + +## ... source file abbreviated to get to FilterExpression examples ... + + + + def get_value(self, context): + return get_sitetree().get_current_page_attr('description', self.item, context) + + +class sitetree_page_hintNode(SimpleNode): + + def get_value(self, context): + return get_sitetree().get_current_page_attr('hint', self.item, context) + + +def detect_clause(parser, clause_name, tokens): + if clause_name in tokens: + t_index = tokens.index(clause_name) + clause_value = parser.compile_filter(tokens[t_index + 1]) + del tokens[t_index:t_index + 2] + else: + clause_value = None + return clause_value + + +def render(context, tree_items, use_template): + context.push() + context['sitetree_items'] = tree_items + +~~ if isinstance(use_template, FilterExpression): + use_template = use_template.resolve(context) + + content = get_template(use_template).render(context.flatten()) + context.pop() + + return content + + + +## ... source file continues with no further FilterExpression examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-node.markdown b/content/pages/examples/django/django-template-base-node.markdown new file mode 100644 index 000000000..d12b75a6f --- /dev/null +++ b/content/pages/examples/django/django-template-base-node.markdown @@ -0,0 +1,99 @@ +title: django.template.base Node Example Code +category: page +slug: django-template-base-node-examples +sortorder: 500011371 +toc: False +sidebartitle: django.template.base Node +meta: Example code for understanding how to use the Node class from the django.template.base module of the Django project. + + +`Node` is a class within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +NodeList, +Parser, +Template, +TemplateSyntaxError, +TextNode, +Token, +TokenType, +VariableDoesNotExist, +VariableNode, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / templatetags / djng_tags.py**](https://github.com/jrief/django-angular/blob/master/djng/templatetags/djng_tags.py) + +```python +# djng_tags.py +import json + +from django.template import Library +~~from django.template.base import Node, NodeList, TextNode, VariableNode +from django.utils.html import format_html +from django.utils.safestring import mark_safe +from django.utils.translation import get_language_from_request + +from djng.core.urlresolvers import get_all_remote_methods, get_current_remote_methods + + +register = Library() + + +@register.simple_tag(name='djng_all_rmi') +def djng_all_rmi(): + return mark_safe(json.dumps(get_all_remote_methods())) + + +@register.simple_tag(name='djng_current_rmi', takes_context=True) +def djng_current_rmi(context): + return mark_safe(json.dumps(get_current_remote_methods(context.get('view')))) + + +@register.simple_tag(name='load_djng_urls', takes_context=True) +def djng_urls(context, *namespaces): + raise DeprecationWarning( + "load_djng_urls templatetag is deprecated and has been removed from this version of django-angular." + "Please refer to documentation for updated way to manage django urls in angular.") + + +~~class AngularJsNode(Node): + def __init__(self, django_nodelist, angular_nodelist, variable): + self.django_nodelist = django_nodelist + self.angular_nodelist = angular_nodelist + self.variable = variable + + def render(self, context): + if self.variable.resolve(context): + return self.angular_nodelist.render(context) + return self.django_nodelist.render(context) + + +@register.tag +def angularjs(parser, token): + bits = token.contents.split() + if len(bits) < 2: + bits.append('1') + values = [parser.compile_filter(bit) for bit in bits[1:]] + django_nodelist = parser.parse(('endangularjs',)) + angular_nodelist = NodeList() + for node in django_nodelist: + if isinstance(node, VariableNode): + tokens = node.filter_expression.token.split('.') + token = tokens[0] + for part in tokens[1:]: + + +## ... source file continues with no further Node examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-nodelist.markdown b/content/pages/examples/django/django-template-base-nodelist.markdown new file mode 100644 index 000000000..82615eb0b --- /dev/null +++ b/content/pages/examples/django/django-template-base-nodelist.markdown @@ -0,0 +1,116 @@ +title: django.template.base NodeList Example Code +category: page +slug: django-template-base-nodelist-examples +sortorder: 500011372 +toc: False +sidebartitle: django.template.base NodeList +meta: Example code for understanding how to use the NodeList class from the django.template.base module of the Django project. + + +`NodeList` is a class within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +Node, +Parser, +Template, +TemplateSyntaxError, +TextNode, +Token, +TokenType, +VariableDoesNotExist, +VariableNode, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / templatetags / djng_tags.py**](https://github.com/jrief/django-angular/blob/master/djng/templatetags/djng_tags.py) + +```python +# djng_tags.py +import json + +from django.template import Library +~~from django.template.base import Node, NodeList, TextNode, VariableNode +from django.utils.html import format_html +from django.utils.safestring import mark_safe +from django.utils.translation import get_language_from_request + +from djng.core.urlresolvers import get_all_remote_methods, get_current_remote_methods + + +register = Library() + + +@register.simple_tag(name='djng_all_rmi') +def djng_all_rmi(): + return mark_safe(json.dumps(get_all_remote_methods())) + + +@register.simple_tag(name='djng_current_rmi', takes_context=True) +def djng_current_rmi(context): + return mark_safe(json.dumps(get_current_remote_methods(context.get('view')))) + + +@register.simple_tag(name='load_djng_urls', takes_context=True) +def djng_urls(context, *namespaces): + raise DeprecationWarning( + "load_djng_urls templatetag is deprecated and has been removed from this version of django-angular." + "Please refer to documentation for updated way to manage django urls in angular.") + + +class AngularJsNode(Node): + def __init__(self, django_nodelist, angular_nodelist, variable): + self.django_nodelist = django_nodelist + self.angular_nodelist = angular_nodelist + self.variable = variable + + def render(self, context): + if self.variable.resolve(context): + return self.angular_nodelist.render(context) + return self.django_nodelist.render(context) + + +@register.tag +def angularjs(parser, token): + bits = token.contents.split() + if len(bits) < 2: + bits.append('1') + values = [parser.compile_filter(bit) for bit in bits[1:]] + django_nodelist = parser.parse(('endangularjs',)) +~~ angular_nodelist = NodeList() + for node in django_nodelist: + if isinstance(node, VariableNode): + tokens = node.filter_expression.token.split('.') + token = tokens[0] + for part in tokens[1:]: + if part.isdigit(): + token += '[%s]' % part + else: + token += '.%s' % part + node = TextNode('{{ %s }}' % token) + angular_nodelist.append(node) + parser.delete_first_token() + return AngularJsNode(django_nodelist, angular_nodelist, values[0]) + + +@register.simple_tag(name='djng_locale_script', takes_context=True) +def djng_locale_script(context, default_language='en'): + language = get_language_from_request(context['request']) + if not language: + language = default_language + return format_html('angular-locale_{}.js', language.lower()) + + + +## ... source file continues with no further NodeList examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-parser.markdown b/content/pages/examples/django/django-template-base-parser.markdown new file mode 100644 index 000000000..d935c982b --- /dev/null +++ b/content/pages/examples/django/django-template-base-parser.markdown @@ -0,0 +1,127 @@ +title: django.template.base Parser Example Code +category: page +slug: django-template-base-parser-examples +sortorder: 500011373 +toc: False +sidebartitle: django.template.base Parser +meta: Example code for understanding how to use the Parser class from the django.template.base module of the Django project. + + +`Parser` is a class within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +Node, +NodeList, +Template, +TemplateSyntaxError, +TextNode, +Token, +TokenType, +VariableDoesNotExist, +VariableNode, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / fields.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./fields.py) + +```python +# fields.py +from typing import Optional + +from django import template +~~from django.template.base import Parser, Token +from django.forms import ChoiceField +from django.utils.safestring import mark_safe + +from .compat import TOKEN_BLOCK +from .templatetags.sitetree import sitetree_tree +from .utils import get_tree_model, get_tree_item_model +from .settings import ITEMS_FIELD_ROOT_ID + +if False: # pragma: nocover + from .models import TreeItemBase, TreeBase # noqa + + +MODEL_TREE_CLASS = get_tree_model() +MODEL_TREE_ITEM_CLASS = get_tree_item_model() + + +class TreeItemChoiceField(ChoiceField): + template: str = 'admin/sitetree/tree/tree_combo.html' + root_title: str = '---------' + + def __init__( + self, + tree: 'TreeBase' = None, + required: bool = True, + + +## ... source file abbreviated to get to Parser examples ... + + + super().__init__( + required=required, widget=widget, label=label, initial=initial, + help_text=help_text, *args, **kwargs) + + self.tree = None + self.choices_init(tree) + + def choices_init(self, tree: Optional['TreeBase']): + if not tree: + return + + if isinstance(tree, MODEL_TREE_CLASS): + tree = tree.alias + + self.tree = tree + self.choices = self._build_choices() + + def _build_choices(self): + tree_token = f'sitetree_tree from "{self.tree}" template "{self.template}"' + + context_kwargs = {'current_app': 'admin'} + context = template.Context(context_kwargs) + context.update({'request': object()}) + + choices_str = sitetree_tree( +~~ Parser([]), Token(token_type=TOKEN_BLOCK, contents=tree_token) + ).render(context) + + tree_choices = [(ITEMS_FIELD_ROOT_ID, self.root_title)] + + for line in choices_str.splitlines(): + if line.strip(): + splitted = line.split(':::') + tree_choices.append((splitted[0], mark_safe(splitted[1]))) + + return tree_choices + + def clean(self, value): + if not value: + return None + + try: + return MODEL_TREE_ITEM_CLASS.objects.get(pk=value) + + except MODEL_TREE_ITEM_CLASS.DoesNotExist: + return None + + + +## ... source file continues with no further Parser examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-template.markdown b/content/pages/examples/django/django-template-base-template.markdown new file mode 100644 index 000000000..23d44a910 --- /dev/null +++ b/content/pages/examples/django/django-template-base-template.markdown @@ -0,0 +1,142 @@ +title: django.template.base Template Example Code +category: page +slug: django-template-base-template-examples +sortorder: 500011374 +toc: False +sidebartitle: django.template.base Template +meta: Example code for understanding how to use the Template class from the django.template.base module of the Django project. + + +`Template` is a class within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +Node, +NodeList, +Parser, +TemplateSyntaxError, +TextNode, +Token, +TokenType, +VariableDoesNotExist, +VariableNode, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / tests / test_static_placeholder.py**](https://github.com/divio/django-cms/blob/develop/cms/tests/test_static_placeholder.py) + +```python +# test_static_placeholder.py + +from django.contrib.admin.sites import site +from django.template import Context +~~from django.template.base import Template + +from cms.api import add_plugin +from cms.models import StaticPlaceholder, Placeholder, UserSettings +from cms.tests.test_plugins import PluginsTestBaseCase +from cms.utils.urlutils import admin_reverse + + +class StaticPlaceholderTestCase(PluginsTestBaseCase): + @property + def admin_class(self): + return site._registry[StaticPlaceholder] + + def fill_placeholder(self, placeholder=None): + if placeholder is None: + placeholder = Placeholder(slot=u"some_slot") + placeholder.save() # a good idea, if not strictly necessary + + + plugin_1 = add_plugin(placeholder, u"TextPlugin", u"en", + body=u"01", + ) + plugin_1.save() + + + plugin_2 = add_plugin(placeholder, u"TextPlugin", u"en", + body=u"02", + ) + plugin_1 = self.reload(plugin_1) + plugin_2.parent = plugin_1 + plugin_2.save() + return placeholder + + def get_admin(self): + usr = self._create_user("admin", True, True) + return usr + + def test_template_creation(self): + self.assertObjectDoesNotExist(StaticPlaceholder.objects.all(), code='foobar') + self.assertObjectDoesNotExist(Placeholder.objects.all(), slot='foobar') +~~ t = Template('{% load cms_tags %}{% static_placeholder "foobar" %}') + t.render(self.get_context('/')) + self.assertObjectExist(StaticPlaceholder.objects.all(), code='foobar', + creation_method=StaticPlaceholder.CREATION_BY_TEMPLATE) + self.assertEqual(Placeholder.objects.filter(slot='foobar').count(), 2) + + def test_empty(self): + self.assertObjectDoesNotExist(StaticPlaceholder.objects.all(), code='foobar') + self.assertObjectDoesNotExist(Placeholder.objects.all(), slot='foobar') +~~ t = Template('{% load cms_tags %}{% static_placeholder "foobar" or %}No Content{% endstatic_placeholder %}') + rendered = t.render(self.get_context('/')) + self.assertIn("No Content", rendered) + +~~ t = Template('{% load cms_tags %}{% static_placeholder "" %}') + rendered = t.render(self.get_context('/')) + self.assertEqual("", rendered) + +~~ t = Template('{% load cms_tags %}{% static_placeholder code or %}No Content{% endstatic_placeholder %}') + rendered = t.render(Context({'code': StaticPlaceholder.objects.all()[0]})) + self.assertIn("No Content", rendered) + + for p in Placeholder.objects.all(): + add_plugin(p, 'TextPlugin', 'en', body='test') +~~ t = Template('{% load cms_tags %}{% static_placeholder "foobar" or %}No Content{% endstatic_placeholder %}') + rendered = t.render(self.get_context('/')) + self.assertNotIn("No Content", rendered) + self.assertEqual(StaticPlaceholder.objects.filter(site_id__isnull=True, code='foobar').count(), 1) + + def test_local(self): + self.assertObjectDoesNotExist(StaticPlaceholder.objects.all(), code='foobar') + self.assertObjectDoesNotExist(Placeholder.objects.all(), slot='foobar') +~~ t = Template('{% load cms_tags %}{% static_placeholder "foobar" site or %}No Content{% endstatic_placeholder %}') + rendered = t.render(self.get_context('/')) + self.assertIn("No Content", rendered) + for p in Placeholder.objects.all(): + add_plugin(p, 'TextPlugin', 'en', body='test') + rendered = t.render(self.get_context('/')) + self.assertNotIn("No Content", rendered) + self.assertEqual(StaticPlaceholder.objects.filter(site_id__isnull=False, code='foobar').count(), 1) + + def test_publish_stack(self): + static_placeholder = StaticPlaceholder.objects.create(name='foo', code='bar', site_id=1) + self.fill_placeholder(static_placeholder.draft) + static_placeholder.dirty = True + static_placeholder.save() + self.assertEqual(static_placeholder.draft.cmsplugin_set.all().count(), 2) + self.assertEqual(static_placeholder.public.cmsplugin_set.all().count(), 0) + with self.login_user_context(self.get_superuser()): + response = self.client.post('%s?statics=%s' % (admin_reverse("cms_page_publish_page", args=[1, 'en']), static_placeholder.pk)) + self.assertEqual(response.status_code, 302) + + def test_permissions(self): + static_placeholder = StaticPlaceholder.objects.create(name='foo', code='bar', site_id=1) + request = self.get_request() + + request.user = self._create_user('user_a', is_staff=True, is_superuser=False, permissions=['change_staticplaceholder']) + + +## ... source file continues with no further Template examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-templatesyntaxerror.markdown b/content/pages/examples/django/django-template-base-templatesyntaxerror.markdown new file mode 100644 index 000000000..9050c318a --- /dev/null +++ b/content/pages/examples/django/django-template-base-templatesyntaxerror.markdown @@ -0,0 +1,254 @@ +title: django.template.base TemplateSyntaxError Example Code +category: page +slug: django-template-base-templatesyntaxerror-examples +sortorder: 500011375 +toc: False +sidebartitle: django.template.base TemplateSyntaxError +meta: Example code for understanding how to use the TemplateSyntaxError class from the django.template.base module of the Django project. + + +`TemplateSyntaxError` is a class within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +Node, +NodeList, +Parser, +Template, +TextNode, +Token, +TokenType, +VariableDoesNotExist, +VariableNode, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / tests / test_templatetags.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/tests/test_templatetags.py) + +```python +# test_templatetags.py +import pytest +~~from django.template.base import TemplateSyntaxError +from django.utils.translation import activate, deactivate_all + +from sitetree.exceptions import SiteTreeError +from sitetree.settings import ALIAS_THIS_ANCESTOR_CHILDREN, ALIAS_THIS_CHILDREN, ALIAS_THIS_PARENT_SIBLINGS, \ + ALIAS_THIS_SIBLINGS, ALIAS_TRUNK + + +def test_items_hook(template_render_tag, template_context, common_tree): + + from sitetree.toolbox import register_items_hook + + with pytest.raises(SiteTreeError): + register_items_hook(lambda: []) + + def my_processor(tree_items, tree_sender): + for item in tree_items: + item.hint = f'hooked_hint_{item.title}' + return tree_items + + register_items_hook(my_processor) + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', template_context()) + + assert 'hooked_hint_Darwin' in result + assert 'hooked_hint_Australia' in result + + +## ... source file abbreviated to get to TemplateSyntaxError examples ... + + +def test_urlpattern_resolve(monkeypatch, template_render_tag, template_context, common_tree): + + monkeypatch.setattr('sitetree.sitetreeapp.UNRESOLVED_ITEM_MARKER', 'UNKNOWN') + + context = template_context() + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', context) + + assert '"/contacts/australia/australia_var/"' in result + assert 'href="UNKNOWN" >China' in result + + context = template_context({'australia_var': 33}) + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', context) + + assert 'href="/https/github.com/contacts/australia/33/"' in result + + context = template_context({'australia_var': 'пробапера'}) # non-ascii + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', context) + + assert '"/contacts/australia/%D0%BF%D1%80%D0%BE%D0%B1%D0%B0%D0%BF%D0%B5%D1%80%D0%B0/"' in result + + +def test_sitetree_tree(template_render_tag, template_context, common_tree): + + context = template_context() + +~~ with pytest.raises(TemplateSyntaxError): + template_render_tag('sitetree', 'sitetree_tree "mytree"', context) + + assert template_render_tag('sitetree', 'sitetree_tree from "notree"', context) == '\n' + + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', context) + + assert '"/articles/cats/ugly/"' in result + assert '"/contacts/russia/postal/"' not in result # insitetree False + assert '"/users/ordinary/"' in result + assert '"/users/hidden/"' not in result + + +def test_sitetree_children(template_render_tag, template_context, common_tree): + + context = template_context({ + 'parent_item': common_tree['/users/'] + }) + +~~ with pytest.raises(TemplateSyntaxError): + template_render_tag('sitetree', 'sitetree_children', context) + + result = template_render_tag( + 'sitetree', 'sitetree_children of parent_item for sitetree template "sitetree/tree.html"', context) + + assert '"/users/moderators/"' in result + assert '"/users/"' not in result + assert '"/users/hidden/"' not in result + + +def test_sitetree_breadcrumbs(template_render_tag, template_context, common_tree): + + result = template_render_tag('sitetree', 'sitetree_breadcrumbs from "notree"', template_context()) # non-existing tree + + assert result.strip() == '
    \n\t\n
' + +~~ with pytest.raises(TemplateSyntaxError): + template_render_tag('sitetree', 'sitetree_breadcrumbs') + + result = template_render_tag('sitetree', 'sitetree_breadcrumbs from "mytree"', template_context()) + + assert result.strip() == '
    \n\t\n
' + + context = template_context(request='/contacts/russia/web/private/') + result = template_render_tag('sitetree', 'sitetree_breadcrumbs from "mytree"', context) + + assert '"/contacts/russia/web/"' in result + assert '"/contacts/russia/"' in result + assert '"/contacts/"' not in result # inbreadcrumbs False + assert '"/home/"' in result + + +def check_page_attr_tag(realm, value, settings, monkeypatch, template_render_tag, template_context): + +~~ with pytest.raises(TemplateSyntaxError): # Invalid tag arguments. + template_render_tag('sitetree', f'sitetree_page_{realm}') + + context = template_context(request='/contacts/russia/') + result = template_render_tag('sitetree', f'sitetree_page_{realm} from "mytree"', context) + + assert result == value + + result = template_render_tag('sitetree', f'sitetree_page_{realm} from "mytree" as somevar', context) + + assert result == '' + assert context.get('somevar') == value + + settings.DEBUG = True + + with pytest.raises(SiteTreeError) as e: + template_render_tag('sitetree', f'sitetree_page_{realm} from "mytree"') + + assert 'django.core.context_processors.request' in f'{e.value}' + + context = template_context(request='/unknown_url/') + + with pytest.raises(SiteTreeError) as e: + template_render_tag('sitetree', f'sitetree_page_{realm} from "mytree"', context) + + assert 'Unable to resolve current sitetree item' in f'{e.value}' + + monkeypatch.setattr('sitetree.sitetreeapp.RAISE_ITEMS_ERRORS_ON_DEBUG', False) + result = template_render_tag('sitetree', f'sitetree_page_{realm} from "mytree"', context) + + assert result == '' + + +def test_sitetree_page_title(settings, monkeypatch, template_render_tag, template_context, common_tree): + check_page_attr_tag('title', 'Russia', settings, monkeypatch, template_render_tag, template_context) + + +def test_sitetree_page_hint(settings, monkeypatch, template_render_tag, template_context, common_tree): + check_page_attr_tag('hint', 'The place', settings, monkeypatch, template_render_tag, template_context) + + +def test_sitetree_page_description(settings, monkeypatch, template_render_tag, template_context, common_tree): + check_page_attr_tag( + 'description', 'Russian Federation', settings, monkeypatch, template_render_tag, template_context) + + +def test_sitetree_url(template_render_tag, template_context, common_tree): + +~~ with pytest.raises(TemplateSyntaxError): + template_render_tag('sitetree', 'sitetree_url') + + target_url = '/contacts/russia/' + + tree_item = common_tree[target_url] + context = template_context({'item_var': tree_item}) + + result = template_render_tag('sitetree', 'sitetree_url for item_var', context) + + assert result == target_url + + result = template_render_tag('sitetree', 'sitetree_url for item_var as somevar', context) + assert result == '' + assert context.get('somevar') == target_url + + +def test_sitetree_menu(template_render_tag, template_context, common_tree): + + result = template_render_tag( + 'sitetree', f'sitetree_menu from "notree" include "{ALIAS_TRUNK}"', template_context()) # non-existing tree + + assert result.strip() == '
    \n\t\n
' + +~~ with pytest.raises(TemplateSyntaxError): + template_render_tag('sitetree', 'sitetree_menu') + + item_ruweb = common_tree['/contacts/russia/web/'] + + context = template_context(request='/') + result = template_render_tag('sitetree', f'sitetree_menu from "mytree" include "{item_ruweb.alias}"', context) + + assert '"/contacts/russia/web/"' not in result + assert '"/contacts/russia/web/public/"' in result + assert '"/contacts/russia/web/private/"' in result + + result = template_render_tag('sitetree', f'sitetree_menu from "mytree" include "{item_ruweb.id}"', context) + + assert '"/contacts/russia/web/"' not in result + assert '"/contacts/russia/web/public/"' in result + assert '"/contacts/russia/web/private/"' in result + + context = template_context(request='/contacts/russia/web/') + result = template_render_tag('sitetree', f'sitetree_menu from "mytree" include "{ALIAS_TRUNK}"', context) + + assert '"/users/moderators/"' in result + assert '"/articles/cats/ugly/"' in result + assert '"/home/"' in result + assert '"/users/ordinary/"' in result + + +## ... source file continues with no further TemplateSyntaxError examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-textnode.markdown b/content/pages/examples/django/django-template-base-textnode.markdown new file mode 100644 index 000000000..ba9d0fd65 --- /dev/null +++ b/content/pages/examples/django/django-template-base-textnode.markdown @@ -0,0 +1,114 @@ +title: django.template.base TextNode Example Code +category: page +slug: django-template-base-textnode-examples +sortorder: 500011376 +toc: False +sidebartitle: django.template.base TextNode +meta: Example code for understanding how to use the TextNode class from the django.template.base module of the Django project. + + +`TextNode` is a class within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +Node, +NodeList, +Parser, +Template, +TemplateSyntaxError, +Token, +TokenType, +VariableDoesNotExist, +VariableNode, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / templatetags / djng_tags.py**](https://github.com/jrief/django-angular/blob/master/djng/templatetags/djng_tags.py) + +```python +# djng_tags.py +import json + +from django.template import Library +~~from django.template.base import Node, NodeList, TextNode, VariableNode +from django.utils.html import format_html +from django.utils.safestring import mark_safe +from django.utils.translation import get_language_from_request + +from djng.core.urlresolvers import get_all_remote_methods, get_current_remote_methods + + +register = Library() + + +@register.simple_tag(name='djng_all_rmi') +def djng_all_rmi(): + return mark_safe(json.dumps(get_all_remote_methods())) + + +@register.simple_tag(name='djng_current_rmi', takes_context=True) +def djng_current_rmi(context): + return mark_safe(json.dumps(get_current_remote_methods(context.get('view')))) + + +@register.simple_tag(name='load_djng_urls', takes_context=True) +def djng_urls(context, *namespaces): + raise DeprecationWarning( + "load_djng_urls templatetag is deprecated and has been removed from this version of django-angular." + + +## ... source file abbreviated to get to TextNode examples ... + + + self.variable = variable + + def render(self, context): + if self.variable.resolve(context): + return self.angular_nodelist.render(context) + return self.django_nodelist.render(context) + + +@register.tag +def angularjs(parser, token): + bits = token.contents.split() + if len(bits) < 2: + bits.append('1') + values = [parser.compile_filter(bit) for bit in bits[1:]] + django_nodelist = parser.parse(('endangularjs',)) + angular_nodelist = NodeList() + for node in django_nodelist: + if isinstance(node, VariableNode): + tokens = node.filter_expression.token.split('.') + token = tokens[0] + for part in tokens[1:]: + if part.isdigit(): + token += '[%s]' % part + else: + token += '.%s' % part +~~ node = TextNode('{{ %s }}' % token) + angular_nodelist.append(node) + parser.delete_first_token() + return AngularJsNode(django_nodelist, angular_nodelist, values[0]) + + +@register.simple_tag(name='djng_locale_script', takes_context=True) +def djng_locale_script(context, default_language='en'): + language = get_language_from_request(context['request']) + if not language: + language = default_language + return format_html('angular-locale_{}.js', language.lower()) + + + +## ... source file continues with no further TextNode examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-token-kwargs.markdown b/content/pages/examples/django/django-template-base-token-kwargs.markdown new file mode 100644 index 000000000..0daeda14c --- /dev/null +++ b/content/pages/examples/django/django-template-base-token-kwargs.markdown @@ -0,0 +1,135 @@ +title: django.template.base token_kwargs Example Code +category: page +slug: django-template-base-token-kwargs-examples +sortorder: 500011381 +toc: False +sidebartitle: django.template.base token_kwargs +meta: Python example code that shows how to use the token_kwargs callable from the django.template.base module of the Django project. + + +`token_kwargs` is a callable within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +Node, +NodeList, +Parser, +Template, +TemplateSyntaxError, +TextNode, +Token, +TokenType, +VariableDoesNotExist, +and VariableNode +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / templatetags / floppyforms.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/templatetags/floppyforms.py) + +```python +# floppyforms.py +from collections import defaultdict +from contextlib import contextmanager + +import django +from django.conf import settings +from django.template import (Library, Node, Variable, + TemplateSyntaxError, VariableDoesNotExist) +~~from django.template.base import token_kwargs +from django.utils.functional import empty + +from ..compat import get_template + + +from django.forms.utils import ErrorList + + +register = Library() + + +def is_formset(var): + significant_attributes = ('forms', 'management_form') + return all(hasattr(var, attr) for attr in significant_attributes) + + +def is_form(var): + significant_attributes = ('is_bound', 'data', 'fields') + return all(hasattr(var, attr) for attr in significant_attributes) + + +def is_bound_field(var): + significant_attributes = ('as_widget', 'as_hidden', 'is_hidden') + return all(hasattr(var, attr) for attr in significant_attributes) + + +## ... source file abbreviated to get to token_kwargs examples ... + + + + @classmethod + def parse_using(cls, tagname, parser, bits, options): + if bits: + if bits[0] == 'using': + bits.pop(0) + if len(bits): + if bits[0] in ('with', 'only'): + raise TemplateSyntaxError( + '%s: you must provide one template after ' + '"using" and before "with" or "only".' % + tagname) + options['using'] = Variable(bits.pop(0)) + else: + raise TemplateSyntaxError('%s: expected a template name ' + 'after "using".' % tagname) + elif not cls.optional_using_parameter: + raise TemplateSyntaxError('Unknown argument for %s tag: %r.' % + (tagname, bits[0])) + + @classmethod + def parse_with(cls, tagname, parser, bits, options): + if bits: + if bits[0] == 'with': + bits.pop(0) +~~ arguments = token_kwargs(bits, parser, support_legacy=False) + if not arguments: + raise TemplateSyntaxError('"with" in %s tag needs at ' + 'least one keyword argument.' % + tagname) + options['with'] = arguments + elif bits[0] not in ('only',) and not cls.optional_with_parameter: + raise TemplateSyntaxError('Unknown argument for %s tag: %r.' % + (tagname, bits[0])) + + if bits: + if cls.accept_only_parameter and bits[0] == 'only': + bits.pop(0) + options['only'] = True + + @classmethod + def parse_for(cls, tagname, parser, bits, options): + if bits: + if bits[0] == 'for': + bits.pop(0) + if len(bits): + options['for'] = Variable(bits.pop(0)) + else: + raise TemplateSyntaxError('%s: expected an argument ' + 'after "for".' % tagname) + + +## ... source file continues with no further token_kwargs examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-token.markdown b/content/pages/examples/django/django-template-base-token.markdown new file mode 100644 index 000000000..5610cf6fe --- /dev/null +++ b/content/pages/examples/django/django-template-base-token.markdown @@ -0,0 +1,127 @@ +title: django.template.base Token Example Code +category: page +slug: django-template-base-token-examples +sortorder: 500011377 +toc: False +sidebartitle: django.template.base Token +meta: Example code for understanding how to use the Token class from the django.template.base module of the Django project. + + +`Token` is a class within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +Node, +NodeList, +Parser, +Template, +TemplateSyntaxError, +TextNode, +TokenType, +VariableDoesNotExist, +VariableNode, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / fields.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./fields.py) + +```python +# fields.py +from typing import Optional + +from django import template +~~from django.template.base import Parser, Token +from django.forms import ChoiceField +from django.utils.safestring import mark_safe + +from .compat import TOKEN_BLOCK +from .templatetags.sitetree import sitetree_tree +from .utils import get_tree_model, get_tree_item_model +from .settings import ITEMS_FIELD_ROOT_ID + +if False: # pragma: nocover + from .models import TreeItemBase, TreeBase # noqa + + +MODEL_TREE_CLASS = get_tree_model() +MODEL_TREE_ITEM_CLASS = get_tree_item_model() + + +class TreeItemChoiceField(ChoiceField): + template: str = 'admin/sitetree/tree/tree_combo.html' + root_title: str = '---------' + + def __init__( + self, + tree: 'TreeBase' = None, + required: bool = True, + + +## ... source file abbreviated to get to Token examples ... + + + super().__init__( + required=required, widget=widget, label=label, initial=initial, + help_text=help_text, *args, **kwargs) + + self.tree = None + self.choices_init(tree) + + def choices_init(self, tree: Optional['TreeBase']): + if not tree: + return + + if isinstance(tree, MODEL_TREE_CLASS): + tree = tree.alias + + self.tree = tree + self.choices = self._build_choices() + + def _build_choices(self): + tree_token = f'sitetree_tree from "{self.tree}" template "{self.template}"' + + context_kwargs = {'current_app': 'admin'} + context = template.Context(context_kwargs) + context.update({'request': object()}) + + choices_str = sitetree_tree( +~~ Parser([]), Token(token_type=TOKEN_BLOCK, contents=tree_token) + ).render(context) + + tree_choices = [(ITEMS_FIELD_ROOT_ID, self.root_title)] + + for line in choices_str.splitlines(): + if line.strip(): + splitted = line.split(':::') + tree_choices.append((splitted[0], mark_safe(splitted[1]))) + + return tree_choices + + def clean(self, value): + if not value: + return None + + try: + return MODEL_TREE_ITEM_CLASS.objects.get(pk=value) + + except MODEL_TREE_ITEM_CLASS.DoesNotExist: + return None + + + +## ... source file continues with no further Token examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-tokentype.markdown b/content/pages/examples/django/django-template-base-tokentype.markdown new file mode 100644 index 000000000..6064b392d --- /dev/null +++ b/content/pages/examples/django/django-template-base-tokentype.markdown @@ -0,0 +1,76 @@ +title: django.template.base TokenType Example Code +category: page +slug: django-template-base-tokentype-examples +sortorder: 500011378 +toc: False +sidebartitle: django.template.base TokenType +meta: Example code for understanding how to use the TokenType class from the django.template.base module of the Django project. + + +`TokenType` is a class within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +Node, +NodeList, +Parser, +Template, +TemplateSyntaxError, +TextNode, +Token, +VariableDoesNotExist, +VariableNode, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / compat.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./compat.py) + +```python +# compat.py +from typing import Callable + +try: +~~ from django.template.base import TokenType +~~ TOKEN_BLOCK = TokenType.BLOCK +~~ TOKEN_TEXT = TokenType.TEXT +~~ TOKEN_VAR = TokenType.VAR +except ImportError: + from django.template.base import TOKEN_BLOCK, TOKEN_TEXT, TOKEN_VAR + + +class CommandOption: + + def __init__(self, *args, **kwargs): + self.args = args + self.kwargs = kwargs + + +def options_getter(command_options): + def get_options(option_func: Callable = None): + from optparse import make_option + + func = option_func or make_option + options = tuple([func(*option.args, **option.kwargs) for option in command_options]) + + return [] if option_func is None else options + + return get_options + + + +## ... source file continues with no further TokenType examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-variabledoesnotexist.markdown b/content/pages/examples/django/django-template-base-variabledoesnotexist.markdown new file mode 100644 index 000000000..a1894a291 --- /dev/null +++ b/content/pages/examples/django/django-template-base-variabledoesnotexist.markdown @@ -0,0 +1,124 @@ +title: django.template.base VariableDoesNotExist Example Code +category: page +slug: django-template-base-variabledoesnotexist-examples +sortorder: 500011379 +toc: False +sidebartitle: django.template.base VariableDoesNotExist +meta: Example code for understanding how to use the VariableDoesNotExist class from the django.template.base module of the Django project. + + +`VariableDoesNotExist` is a class within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +Node, +NodeList, +Parser, +Template, +TemplateSyntaxError, +TextNode, +Token, +TokenType, +VariableNode, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / templatetags / pipeline.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/templatetags/pipeline.py) + +```python +# pipeline.py +import logging +import subprocess + +from django.contrib.staticfiles.storage import staticfiles_storage + +from django import template +~~from django.template.base import VariableDoesNotExist +from django.template.loader import render_to_string +from django.utils.safestring import mark_safe + +from ..collector import default_collector +from ..conf import settings +from ..exceptions import CompilerError +from ..packager import Packager, PackageNotFound +from ..utils import guess_type + +logger = logging.getLogger(__name__) + +register = template.Library() + + +class PipelineMixin(object): + request = None + _request_var = None + + @property + def request_var(self): + if not self._request_var: + self._request_var = template.Variable('request') + return self._request_var + + def package_for(self, package_name, package_type): + package = { + 'js': getattr(settings, 'JAVASCRIPT', {}).get(package_name, {}), + 'css': getattr(settings, 'STYLESHEETS', {}).get(package_name, {}), + }[package_type] + + if package: + package = {package_name: package} + + packager = { + 'js': Packager(css_packages={}, js_packages=package), + 'css': Packager(css_packages=package, js_packages={}), + }[package_type] + + return packager.package_for(package_type, package_name) + + def render(self, context): + try: + self.request = self.request_var.resolve(context) +~~ except VariableDoesNotExist: + pass + + def render_compressed(self, package, package_name, package_type): + if settings.PIPELINE_ENABLED: + return self.render_compressed_output(package, package_name, + package_type) + else: + return self.render_compressed_sources(package, package_name, + package_type) + + def render_compressed_output(self, package, package_name, package_type): + method = getattr(self, f'render_{package_type}') + + return method(package, package.output_filename) + + def render_compressed_sources(self, package, package_name, package_type): + if settings.PIPELINE_COLLECTOR_ENABLED: + default_collector.collect(self.request) + + packager = Packager() + method = getattr(self, f'render_individual_{package_type}') + + try: + paths = packager.compile(package.paths) + + +## ... source file continues with no further VariableDoesNotExist examples... + +``` + diff --git a/content/pages/examples/django/django-template-base-variablenode.markdown b/content/pages/examples/django/django-template-base-variablenode.markdown new file mode 100644 index 000000000..a2d26decd --- /dev/null +++ b/content/pages/examples/django/django-template-base-variablenode.markdown @@ -0,0 +1,168 @@ +title: django.template.base VariableNode Example Code +category: page +slug: django-template-base-variablenode-examples +sortorder: 500011380 +toc: False +sidebartitle: django.template.base VariableNode +meta: Example code for understanding how to use the VariableNode class from the django.template.base module of the Django project. + + +`VariableNode` is a class within the `django.template.base` module of the Django project. + +Context, +FilterExpression, +Node, +NodeList, +Parser, +Template, +TemplateSyntaxError, +TextNode, +Token, +TokenType, +VariableDoesNotExist, +and token_kwargs +are several other callables with code examples from the same `django.template.base` package. + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / templatetags / djng_tags.py**](https://github.com/jrief/django-angular/blob/master/djng/templatetags/djng_tags.py) + +```python +# djng_tags.py +import json + +from django.template import Library +~~from django.template.base import Node, NodeList, TextNode, VariableNode +from django.utils.html import format_html +from django.utils.safestring import mark_safe +from django.utils.translation import get_language_from_request + +from djng.core.urlresolvers import get_all_remote_methods, get_current_remote_methods + + +register = Library() + + +@register.simple_tag(name='djng_all_rmi') +def djng_all_rmi(): + return mark_safe(json.dumps(get_all_remote_methods())) + + +@register.simple_tag(name='djng_current_rmi', takes_context=True) +def djng_current_rmi(context): + return mark_safe(json.dumps(get_current_remote_methods(context.get('view')))) + + +@register.simple_tag(name='load_djng_urls', takes_context=True) +def djng_urls(context, *namespaces): + raise DeprecationWarning( + "load_djng_urls templatetag is deprecated and has been removed from this version of django-angular." + "Please refer to documentation for updated way to manage django urls in angular.") + + +class AngularJsNode(Node): + def __init__(self, django_nodelist, angular_nodelist, variable): + self.django_nodelist = django_nodelist + self.angular_nodelist = angular_nodelist + self.variable = variable + + def render(self, context): + if self.variable.resolve(context): + return self.angular_nodelist.render(context) + return self.django_nodelist.render(context) + + +@register.tag +def angularjs(parser, token): + bits = token.contents.split() + if len(bits) < 2: + bits.append('1') + values = [parser.compile_filter(bit) for bit in bits[1:]] + django_nodelist = parser.parse(('endangularjs',)) + angular_nodelist = NodeList() + for node in django_nodelist: +~~ if isinstance(node, VariableNode): + tokens = node.filter_expression.token.split('.') + token = tokens[0] + for part in tokens[1:]: + if part.isdigit(): + token += '[%s]' % part + else: + token += '.%s' % part + node = TextNode('{{ %s }}' % token) + angular_nodelist.append(node) + parser.delete_first_token() + return AngularJsNode(django_nodelist, angular_nodelist, values[0]) + + +@register.simple_tag(name='djng_locale_script', takes_context=True) +def djng_locale_script(context, default_language='en'): + language = get_language_from_request(context['request']) + if not language: + language = default_language + return format_html('angular-locale_{}.js', language.lower()) + + + +## ... source file continues with no further VariableNode examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / utils / placeholder.py**](https://github.com/divio/django-cms/blob/develop/cms/utils/placeholder.py) + +```python +# placeholder.py +import operator +import warnings +from collections import OrderedDict + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db.models.query_utils import Q +from django.template import TemplateSyntaxError, NodeList, Variable, Context, Template, engines +~~from django.template.base import VariableNode +from django.template.loader import get_template +from django.template.loader_tags import BlockNode, ExtendsNode, IncludeNode + +from sekizai.helpers import get_varname + +from cms.exceptions import DuplicatePlaceholderWarning +from cms.utils.conf import get_cms_setting + + +def _get_nodelist(tpl): + if hasattr(tpl, 'template'): + return tpl.template.nodelist + else: + return tpl.nodelist + + +def get_context(): + if engines is not None: + context = Context() + context.template = Template('') + return context + else: + return {} + + + +## ... source file continues with no further VariableNode examples... + +``` + diff --git a/content/pages/examples/django/django-template-context-context.markdown b/content/pages/examples/django/django-template-context-context.markdown new file mode 100644 index 000000000..5b3926fb2 --- /dev/null +++ b/content/pages/examples/django/django-template-context-context.markdown @@ -0,0 +1,186 @@ +title: django.template.context Context Example Code +category: page +slug: django-template-context-context-examples +sortorder: 500011382 +toc: False +sidebartitle: django.template.context Context +meta: Example code for understanding how to use the Context class from the django.template.context module of the Django project. + + +`Context` is a class within the `django.template.context` module of the Django project. + + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / test_utils / testcases.py**](https://github.com/divio/django-cms/blob/develop/cms/test_utils/testcases.py) + +```python +# testcases.py +import json +import sys +import warnings + +from urllib.parse import unquote, urljoin + +from django.conf import settings +from django.contrib.auth import get_user_model +from django.contrib.auth.models import AnonymousUser, Permission +from django.contrib.sites.models import Site +from django.core.cache import cache +from django.core.exceptions import ObjectDoesNotExist +from django.forms.models import model_to_dict +from django.template import engines +~~from django.template.context import Context +from django.test import testcases +from django.test.client import RequestFactory +from django.urls import reverse +from django.utils.http import urlencode +from django.utils.timezone import now +from django.utils.translation import activate +from menus.menu_pool import menu_pool + +from cms.api import create_page +from cms.constants import ( + PUBLISHER_STATE_DEFAULT, + PUBLISHER_STATE_DIRTY, + PUBLISHER_STATE_PENDING, +) +from cms.plugin_rendering import ContentRenderer, StructureRenderer +from cms.models import Page +from cms.models.permissionmodels import ( + GlobalPagePermission, + PagePermission, + PageUser, +) +from cms.test_utils.util.context_managers import UserLoginContext +from cms.utils.conf import get_cms_setting +from cms.utils.permissions import set_current_user + + +## ... source file abbreviated to get to Context examples ... + + + + def create_homepage(self, *args, **kwargs): + homepage = create_page(*args, **kwargs) + homepage.set_as_homepage() + return homepage.reload() + + def move_page(self, page, target_page, position="first-child"): + page.move_page(target_page.node, position) + return self.reload_page(page) + + def reload_page(self, page): + return self.reload(page) + + def reload(self, obj): + return obj.__class__.objects.get(pk=obj.pk) + + def get_pages_root(self): + return unquote(reverse("pages-root")) + + def get_context(self, path=None, page=None): + if not path: + path = self.get_pages_root() + context = {} + request = self.get_request(path, page=page) + context['request'] = request +~~ return Context(context) + + def get_content_renderer(self, request=None): + request = request or self.get_request() + return ContentRenderer(request) + + def get_structure_renderer(self, request=None): + request = request or self.get_request() + return StructureRenderer(request) + + def get_request(self, path=None, language=None, post_data=None, enforce_csrf_checks=False, page=None, domain=None): + factory = RequestFactory() + + if not path: + path = self.get_pages_root() + + if not language: + if settings.USE_I18N: + language = settings.LANGUAGES[0][0] + else: + language = settings.LANGUAGE_CODE + + if post_data: + request = factory.post(path, post_data) + else: + + +## ... source file continues with no further Context examples... + +``` + + +## Example 2 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / sitetreeapp.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./sitetreeapp.py) + +```python +# sitetreeapp.py +import warnings +from collections import defaultdict +from copy import deepcopy +from inspect import getfullargspec +from sys import exc_info +from threading import local +from typing import Callable, List, Optional, Dict, Union, Sequence, Any, Tuple + +from django.conf import settings +from django.core.cache import caches +from django.db.models import signals, QuerySet +from django.template.base import ( + FilterExpression, Lexer, Parser, Variable, VariableDoesNotExist, VARIABLE_TAG_START) +~~from django.template.context import Context +from django.template.loader import get_template +from django.urls import reverse, NoReverseMatch +from django.utils import module_loading +from django.utils.encoding import iri_to_uri +from django.utils.translation import get_language + +from .compat import TOKEN_TEXT, TOKEN_VAR +from .exceptions import SiteTreeError +from .settings import ( + ALIAS_TRUNK, ALIAS_THIS_CHILDREN, ALIAS_THIS_SIBLINGS, ALIAS_THIS_PARENT_SIBLINGS, ALIAS_THIS_ANCESTOR_CHILDREN, + UNRESOLVED_ITEM_MARKER, RAISE_ITEMS_ERRORS_ON_DEBUG, CACHE_TIMEOUT, CACHE_NAME, DYNAMIC_ONLY, ADMIN_APP_NAME, + SITETREE_CLS) +from .utils import get_tree_model, get_tree_item_model, import_app_sitetree_module, generate_id_for + +if False: # pragma: nocover + from django.contrib.auth.models import User # noqa + from .models import TreeItemBase, TreeBase + +TypeDynamicTrees = Dict[str, Union[Dict[str, List['TreeBase']], List['TreeBase']]] + +MODEL_TREE_CLASS = get_tree_model() +MODEL_TREE_ITEM_CLASS = get_tree_item_model() + + + + +## ... source file continues with no further Context examples... + +``` + diff --git a/content/pages/examples/django/django-template-context.markdown b/content/pages/examples/django/django-template-context.markdown new file mode 100644 index 000000000..9bfe9e562 --- /dev/null +++ b/content/pages/examples/django/django-template-context.markdown @@ -0,0 +1,1069 @@ +title: django.template Context Example Code +category: page +slug: django-template-context-examples +sortorder: 500011357 +toc: False +sidebartitle: django.template Context +meta: Example code for understanding how to use the Context class from the django.template module of the Django project. + + +`Context` is a class within the `django.template` module of the Django project. + +Engine, +Library, +Node, +NodeList, +Origin, +RequestContext, +Template, +TemplateDoesNotExist, +TemplateSyntaxError, +Variable, +context, +engine, +library, +and loader +are several other callables with code examples from the same `django.template` package. + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / chair_mail / models.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/chair_mail/models.py) + +```python +# models.py +from django.conf import settings +from django.core.mail import send_mail +from django.db import models +from django.db.models import ForeignKey, OneToOneField, TextField, CharField, \ + SET_NULL, CASCADE, BooleanField, UniqueConstraint +from django.db.models.signals import post_save +from django.dispatch import receiver +~~from django.template import Template, Context +from django.utils import timezone +from markdown import markdown +from html2text import html2text + +from chair_mail.context import get_conference_context, get_user_context, \ + get_submission_context, get_frame_context +from conferences.models import Conference +from submissions.models import Submission +from users.models import User + +MSG_TYPE_USER = 'user' +MSG_TYPE_SUBMISSION = 'submission' + +MESSAGE_TYPE_CHOICES = ( + (MSG_TYPE_USER, 'Message to users'), + (MSG_TYPE_SUBMISSION, 'Message to submissions'), +) + + +class EmailFrame(models.Model): + text_html = models.TextField() + text_plain = models.TextField() + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now_add=True) + created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) + conference = models.ForeignKey(Conference, on_delete=models.CASCADE) + + @staticmethod + def render(frame_template, conference, subject, body): + context_data = get_frame_context(conference, subject, body) +~~ context = Context(context_data, autoescape=False) + return Template(frame_template).render(context) + + def render_html(self, subject, body): + return EmailFrame.render( + self.text_html, self.conference, subject, body + ) + + def render_plain(self, subject, body): + text_plain = self.text_plain + if not text_plain: + text_plain = html2text(self.text_html) + return EmailFrame.render( + text_plain, self.conference, subject, body + ) + + +class EmailSettings(models.Model): + frame = models.ForeignKey(EmailFrame, on_delete=models.SET_NULL, null=True) + conference = models.OneToOneField( + Conference, null=True, blank=True, on_delete=models.CASCADE, + related_name='email_settings', + ) + + + + +## ... source file abbreviated to get to Context examples ... + + + + group_message = models.OneToOneField( + GroupMessage, on_delete=models.CASCADE, parent_link=True) + + @property + def message_type(self): + return MSG_TYPE_USER + + @staticmethod + def create(subject, body, conference, objects_to): + msg = UserMessage.objects.create( + subject=subject, body=body, conference=conference) + for user in objects_to: + msg.recipients.add(user) + msg.save() + return msg + + def send(self, sender): + self.sent = False + self.sent_by = sender + self.save() + + frame = self.conference.email_settings.frame + conference_context = get_conference_context(self.conference) + for user in self.recipients.all(): +~~ context = Context({ + **conference_context, + **get_user_context(user, self.conference) + }, autoescape=False) + email = EmailMessage.create( + group_message=self.group_message, + user_to=user, + context=context, + frame=frame + ) + email.send(sender) + + self.sent_at = timezone.now() + self.sent = True + self.save() + return self + + +class SubmissionMessage(GroupMessage): + recipients = models.ManyToManyField( + Submission, related_name='group_emails') + + group_message = models.OneToOneField( + GroupMessage, on_delete=models.CASCADE, parent_link=True) + + @property + def message_type(self): + return MSG_TYPE_SUBMISSION + + @staticmethod + def create(subject, body, conference, objects_to): + msg = SubmissionMessage.objects.create( + subject=subject, body=body, conference=conference) + for submission in objects_to: + msg.recipients.add(submission) + msg.save() + return msg + + def send(self, sender): + self.sent = False + self.sent_by = sender + self.save() + + frame = self.conference.email_settings.frame + conference_context = get_conference_context(self.conference) + for submission in self.recipients.all(): + submission_context = get_submission_context(submission) + for author in submission.authors.all(): + user = author.user +~~ context = Context({ + **conference_context, + **submission_context, + **get_user_context(user, self.conference) + }, autoescape=False) + email = EmailMessage.create( + group_message=self.group_message, + user_to=user, + context=context, + frame=frame + ) + email.send(sender) + + self.sent_at = timezone.now() + self.sent = True + self.save() + return self + + +def get_group_message_model(msg_type): + return { + MSG_TYPE_USER: UserMessage, + MSG_TYPE_SUBMISSION: SubmissionMessage, + }[msg_type] + + + +## ... source file continues with no further Context examples... + +``` + + +## Example 2 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / tests.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/tests.py) + +```python +# tests.py +from __future__ import absolute_import + +import json +import uuid +from datetime import timedelta + +from django import forms +from django.conf import settings +from django.contrib.auth.models import AbstractUser, AnonymousUser +from django.contrib.sites.models import Site +from django.core import mail, validators +from django.core.exceptions import ValidationError +from django.db import models +from django.http import HttpResponseRedirect +~~from django.template import Context, Template +from django.test.client import Client, RequestFactory +from django.test.utils import override_settings +from django.urls import reverse +from django.utils.timezone import now + +from allauth.account.forms import BaseSignupForm, ResetPasswordForm, SignupForm +from allauth.account.models import ( + EmailAddress, + EmailConfirmation, + EmailConfirmationHMAC, +) +from allauth.tests import Mock, TestCase, patch +from allauth.utils import get_user_model, get_username_max_length + +from . import app_settings +from .adapter import get_adapter +from .auth_backends import AuthenticationBackend +from .signals import user_logged_in, user_logged_out +from .utils import ( + filter_users_by_username, + url_str_to_user_pk, + user_pk_to_url_str, + user_username, +) + + +## ... source file continues with no further Context examples... + +``` + + +## Example 3 from django-appmail +[Django-Appmail](https://github.com/yunojuno/django-appmail) +([PyPI package information](https://pypi.org/project/django-appmail/)) +is a [Django](/django.html) app for handling transactional email templates. +While the project began development as a way to work with the Mandrill +transactional [API](/application-programming-interfaces.html), it is +not exclusive to that API. The project simply provides a way to store +and render email content. The library does not send or receive emails. + +Django-Appmail is open sourced under the +[MIT license](https://github.com/yunojuno/django-appmail/blob/master/LICENSE). + +[**django-appmail / appmail / models.py**](https://github.com/yunojuno/django-appmail/blob/master/appmail/./models.py) + +```python +# models.py +from __future__ import annotations + +from typing import Any, Callable, Dict, List, Optional + +from django.conf import settings +from django.contrib.auth import get_user_model +from django.core.exceptions import ValidationError +from django.core.mail import EmailMultiAlternatives +from django.core.serializers.json import DjangoJSONEncoder +from django.db import models, transaction +from django.http import HttpRequest +~~from django.template import Context, Template, TemplateDoesNotExist, TemplateSyntaxError +from django.utils.timezone import now as tz_now +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy as _lazy + +from . import helpers +from .compat import JSONField +from .settings import ( + ADD_EXTRA_HEADERS, + CONTEXT_PROCESSORS, + LOG_SENT_EMAILS, + VALIDATE_ON_SAVE, +) + +User = get_user_model() + + +class EmailTemplateQuerySet(models.query.QuerySet): + def active(self) -> EmailTemplateQuerySet: + return self.filter(is_active=True) + + def current( + self, name: str, language: str = settings.LANGUAGE_CODE + ) -> EmailTemplateQuerySet: + return ( + + +## ... source file abbreviated to get to Context examples ... + + + + def save(self, *args: Any, **kwargs: Any) -> EmailTemplate: + if self.pk is None: + self.test_context = helpers.get_context( + self.subject + self.body_text + self.body_html + ) + validate = kwargs.pop("validate", VALIDATE_ON_SAVE) + if validate: + self.clean() + super(EmailTemplate, self).save(*args, **kwargs) + return self + + def clean(self) -> None: + validation_errors = {} + validation_errors.update(self._validate_body(EmailTemplate.CONTENT_TYPE_PLAIN)) + validation_errors.update(self._validate_body(EmailTemplate.CONTENT_TYPE_HTML)) + validation_errors.update(self._validate_subject()) + if validation_errors: + raise ValidationError(validation_errors) + + def render_subject( + self, + context: dict, + processors: List[Callable[[HttpRequest], dict]] = CONTEXT_PROCESSORS, + ) -> str: +~~ ctx = Context(helpers.patch_context(context, processors), autoescape=False) + return Template(self.subject).render(ctx) + + def _validate_subject(self) -> Dict[str, str]: + try: + self.render_subject({}) + except TemplateDoesNotExist as ex: + return {"subject": _lazy("Template does not exist: {}".format(ex))} + except TemplateSyntaxError as ex: + return {"subject": str(ex)} + else: + return {} + + def render_body( + self, + context: dict, + content_type: str = CONTENT_TYPE_PLAIN, + processors: List[Callable[[HttpRequest], dict]] = CONTEXT_PROCESSORS, + ) -> str: + if content_type not in EmailTemplate.CONTENT_TYPES: + raise ValueError(_(f"Invalid content type. Value supplied: {content_type}")) + if content_type == EmailTemplate.CONTENT_TYPE_PLAIN: +~~ ctx = Context(helpers.patch_context(context, processors), autoescape=False) + return Template(self.body_text).render(ctx) + if content_type == EmailTemplate.CONTENT_TYPE_HTML: +~~ ctx = Context(helpers.patch_context(context, processors)) + return Template(self.body_html).render(ctx) + raise ValueError(f"Invalid content_type '{content_type}'.") + + def _validate_body(self, content_type: str) -> Dict[str, str]: + if content_type == EmailTemplate.CONTENT_TYPE_PLAIN: + field_name = "body_text" + elif content_type == EmailTemplate.CONTENT_TYPE_HTML: + field_name = "body_html" + else: + raise ValueError("Invalid template content_type.") + try: + self.render_body({}, content_type=content_type) + except TemplateDoesNotExist as ex: + return {field_name: _("Template does not exist: {}".format(ex))} + except TemplateSyntaxError as ex: + return {field_name: str(ex)} + else: + return {} + + def clone(self) -> EmailTemplate: + self.pk = None + self.version += 1 + return self.save() + + + +## ... source file continues with no further Context examples... + +``` + + +## Example 4 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_rendering.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_rendering.py) + +```python +# plugin_rendering.py +from collections import OrderedDict + +from functools import partial + +from classytags.utils import flatten_context + +from django.contrib.sites.models import Site +~~from django.template import Context +from django.utils.functional import cached_property +from django.utils.module_loading import import_string +from django.utils.safestring import mark_safe + +from cms.cache.placeholder import get_placeholder_cache, set_placeholder_cache +from cms.toolbar.utils import ( + get_placeholder_toolbar_js, + get_plugin_toolbar_js, + get_toolbar_from_request, +) +from cms.utils import get_language_from_request +from cms.utils.conf import get_cms_setting +from cms.utils.permissions import has_plugin_permission +from cms.utils.placeholder import get_toolbar_plugin_struct, restore_sekizai_context +from cms.utils.plugins import get_plugin_restrictions + + +def _unpack_plugins(parent_plugin): + found_plugins = [] + + for plugin in parent_plugin.child_plugin_instances or []: + found_plugins.append(plugin) + + if plugin.child_plugin_instances: + + +## ... source file abbreviated to get to Context examples ... + + + placeholder_cache = self._rendered_plugins_by_placeholder.setdefault(instance.placeholder_id, {}) + placeholder_cache.setdefault('plugins', []).append(instance) + return self.get_plugin_toolbar_js(instance, page=page) + + def render_plugins(self, placeholder, language, page=None): + template = page.get_template() if page else None + plugins = self.get_plugins_to_render(placeholder, language, template) + + for plugin in plugins: + plugin._placeholder_cache = placeholder + yield self.render_plugin(plugin, page=page) + + +class LegacyRenderer(ContentRenderer): + + load_structure = True + placeholder_edit_template = ( + ) + + def get_editable_placeholder_context(self, placeholder, page=None): + context = super().get_editable_placeholder_context(placeholder, page) + context['plugin_menu_js'] = self.get_placeholder_plugin_menu(placeholder, page=page) + return context + + +~~class PluginContext(Context): + + def __init__(self, dict_, instance, placeholder, processors=None, current_app=None): + dict_ = flatten_context(dict_) + super().__init__(dict_) + + if not processors: + processors = [] + + for path in get_cms_setting('PLUGIN_CONTEXT_PROCESSORS'): + processor = import_string(path) + self.update(processor(instance, placeholder, self)) + for processor in processors: + self.update(processor(instance, placeholder, self)) + + + +## ... source file continues with no further Context examples... + +``` + + +## Example 5 from django-easy-timezones +[django-easy-timezones](https://github.com/Miserlou/django-easy-timezones) +([project website](https://www.gun.io/blog/django-easy-timezones)) +is a Django +[middleware](https://docs.djangoproject.com/en/2.2/topics/http/middleware/) +[code library](https://pypi.org/project/django-easy-timezones/) +to simplify handling time data in your applications using +users' geolocation data. + +[**django-easy-timezones / easy_timezones / views.py**](https://github.com/Miserlou/django-easy-timezones/blob/master/easy_timezones/./views.py) + +```python +# views.py +from django.conf import settings +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import render_to_response +~~from django.template import RequestContext, Template, Context + +from datetime import datetime + +def with_tz(request): + + dt = datetime.now() + t = Template('{% load tz %}{% localtime on %}{% get_current_timezone as TIME_ZONE %}{{ TIME_ZONE }}{% endlocaltime %}') + c = RequestContext(request) + response = t.render(c) + return HttpResponse(response) + +def without_tz(request): + + t = Template('{% load tz %}{% get_current_timezone as TIME_ZONE %}{{ TIME_ZONE }}') + c = RequestContext(request) + response = t.render(c) + return HttpResponse(response) + + + +## ... source file continues with no further Context examples... + +``` + + +## Example 6 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / management / modelviz.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/management/modelviz.py) + +```python +# modelviz.py + +import datetime +import os +import re + +from django.apps import apps +from django.db.models.fields.related import ( + ForeignKey, ManyToManyField, OneToOneField, RelatedField, +) +from django.contrib.contenttypes.fields import GenericRelation +~~from django.template import Context, Template, loader +from django.utils.encoding import force_str +from django.utils.safestring import mark_safe +from django.utils.translation import activate as activate_language + + +__version__ = "1.1" +__license__ = "Python" +__author__ = "Bas van Oostveen ", +__contributors__ = [ + "Antonio Cavedoni " + "Stefano J. Attardi ", + "Carlo C8E Miron", + "Andre Campos ", + "Justin Findlay ", + "Alexander Houben ", + "Joern Hees ", + "Kevin Cherepski ", + "Jose Tomas Tocino ", + "Adam Dobrawy ", + "Mikkel Munch Mortensen ", + "Andrzej Bistram ", + "Daniel Lipsitt ", +] + + +## ... source file abbreviated to get to Context examples ... + + + if '.' in field.remote_field.model: + app_label, model_name = field.remote_field.model.split('.', 1) + else: + app_label = field.model._meta.app_label + model_name = field.remote_field.model + target_model = apps.get_model(app_label, model_name) + else: + target_model = field.remote_field.model + + _rel = self.get_relation_context(target_model, field, label, extras) + + if _rel not in model['relations'] and self.use_model(_rel['target']): + return _rel + + def get_abstract_models(self, appmodels): + abstract_models = [] + for appmodel in appmodels: + abstract_models += [ + abstract_model for abstract_model in appmodel.__bases__ + if hasattr(abstract_model, '_meta') and abstract_model._meta.abstract + ] + abstract_models = list(set(abstract_models)) # remove duplicates + return abstract_models + + def get_app_context(self, app): +~~ return Context({ + 'name': '"%s"' % app.name, + 'app_name': "%s" % app.name, + 'cluster_app_name': "cluster_%s" % app.name.replace(".", "_"), + 'models': [] + }) + + def get_appmodel_attributes(self, appmodel): + if self.relations_as_fields: + attributes = [field for field in appmodel._meta.local_fields] + else: + attributes = [field for field in appmodel._meta.local_fields if not + isinstance(field, RelatedField)] + return attributes + + def get_appmodel_abstracts(self, appmodel): + return [ + abstract_model.__name__ for abstract_model in appmodel.__bases__ + if hasattr(abstract_model, '_meta') and abstract_model._meta.abstract + ] + + def get_appmodel_context(self, appmodel, appmodel_abstracts): + context = { + 'model': appmodel, + 'app_name': appmodel.__module__.replace(".", "_"), + + +## ... source file abbreviated to get to Context examples ... + + + for model_pattern in self.exclude_models: + model_pattern = '^%s$' % model_pattern.replace('*', '.*') + if re.search(model_pattern, model_name): + return False + return not self.include_models + + def skip_field(self, field): + if self.exclude_columns: + if self.verbose_names and field.verbose_name: + if field.verbose_name in self.exclude_columns: + return True + if field.name in self.exclude_columns: + return True + return False + + +def generate_dot(graph_data, template='django_extensions/graph_models/digraph.dot'): + if isinstance(template, str): + template = loader.get_template(template) + + if not isinstance(template, Template) and not (hasattr(template, 'template') and isinstance(template.template, Template)): + raise Exception("Default Django template loader isn't used. " + "This can lead to the incorrect template rendering. " + "Please, check the settings.") + +~~ c = Context(graph_data).flatten() + dot = template.render(c) + + return dot + + +def generate_graph_data(*args, **kwargs): + generator = ModelGraph(*args, **kwargs) + generator.generate_graph_data() + return generator.get_graph_data() + + +def use_model(model, include_models, exclude_models): + generator = ModelGraph([], include_models=include_models, exclude_models=exclude_models) + return generator.use_model(model) + + + +## ... source file continues with no further Context examples... + +``` + + +## Example 7 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / compat.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./compat.py) + +```python +# compat.py +from contextlib import contextmanager + +import django +~~from django.template import Context +from django.utils.datastructures import MultiValueDict + +MULTIVALUE_DICT_TYPES = (MultiValueDict,) + + +REQUIRED_CONTEXT_ATTRIBTUES = ( + '_form_config', + '_form_render', +) + + +class DictContext(dict): + pass + + +if django.VERSION < (1, 8): + def get_template(context, template_name): + from django.template.loader import get_template + return get_template(template_name) + + def get_context(context): +~~ if not isinstance(context, Context): +~~ context = Context(context) + return context + +else: + def get_template(context, template_name): + return context.template.engine.get_template(template_name) + + def get_context(context): + return context + + +def flatten_context(context): +~~ if isinstance(context, Context): + flat = {} + for d in context.dicts: + flat.update(d) + return flat + else: + return context + + +def flatten_contexts(*contexts): + new_context = DictContext() + for context in contexts: + if context is not None: + new_context.update(flatten_context(context)) + for attr in REQUIRED_CONTEXT_ATTRIBTUES: + if hasattr(context, attr): + setattr(new_context, attr, getattr(context, attr)) + return new_context + + +@contextmanager +def render_context(context_instance, context): + if context_instance is not None: + with context_instance.push(context): + yield context_instance + + +## ... source file continues with no further Context examples... + +``` + + +## Example 8 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / utils.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./utils.py) + +```python +# utils.py +import datetime +import json +~~from django.template import Context +from django.utils import translation +from jet import settings +from jet.models import PinnedApplication + +try: + from django.apps.registry import apps +except ImportError: + try: + from django.apps import apps # Fix Django 1.7 import issue + except ImportError: + pass +from django.core.serializers.json import DjangoJSONEncoder +from django.http import HttpResponse +try: + from django.core.urlresolvers import reverse, resolve, NoReverseMatch +except ImportError: # Django 1.11 + from django.urls import reverse, resolve, NoReverseMatch + +from django.contrib.admin import AdminSite +from django.utils.encoding import smart_text +from django.utils.text import capfirst +from django.contrib import messages +from django.utils.encoding import force_text +from django.utils.functional import Promise + + +## ... source file abbreviated to get to Context examples ... + + + item['items'] = item['models'] + return item + app_list = list(map(map_item, original_app_list.values())) + + current_found = False + + for app in app_list: + if not current_found: + for model in app['items']: + if not current_found and model.get('url') and context['request'].path.startswith(model['url']): + model['current'] = True + current_found = True + else: + model['current'] = False + + if not current_found and app.get('url') and context['request'].path.startswith(app['url']): + app['current'] = True + current_found = True + else: + app['current'] = False + + return app_list + + +def context_to_dict(context): +~~ if isinstance(context, Context): + flat = {} + for d in context.dicts: + flat.update(d) + context = flat + + return context + + +def user_is_authenticated(user): + if not hasattr(user.is_authenticated, '__call__'): + return user.is_authenticated + else: + return user.is_authenticated() + + + +## ... source file continues with no further Context examples... + +``` + + +## Example 9 from django-markdown-view +[django-markdown-view](https://github.com/rgs258/django-markdown-view) +([PyPI package information](https://pypi.org/project/django-markdown-view/)) +is a Django extension for serving [Markdown](/markdown.html) files as +[Django templates](/django-templates.html). The project is open +sourced under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/rgs258/django-markdown-view/blob/master/LICENSE). + +[**django-markdown-view / markdown_view / views.py**](https://github.com/rgs258/django-markdown-view/blob/master/markdown_view/./views.py) + +```python +# views.py +import logging + +import markdown +from django.conf import settings +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin +~~from django.template import Engine, Template, Context +from django.utils.safestring import mark_safe +from django.views.generic import TemplateView + +from markdown_view.constants import ( + DEFAULT_MARKDOWN_VIEW_LOADERS, + DEFAULT_MARKDOWN_VIEW_EXTENSIONS, DEFAULT_MARKDOWN_VIEW_TEMPLATE, + DEFAULT_MARKDOWN_VIEW_USE_REQUEST_CONTEXT, DEFAULT_MARKDOWN_VIEW_EXTRA_CONTEXT, + DEFAULT_MARKDOWN_VIEW_TEMPLATE_USE_HIGHLIGHT_JS, DEFAULT_MARKDOWN_VIEW_TEMPLATE_USE_TOC, +) + +logger = logging.getLogger(__name__) + + +class MarkdownView(TemplateView): + file_name = None + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + if self.file_name: + engine = Engine(loaders=getattr( + settings, "MARKDOWN_VIEW_LOADERS", DEFAULT_MARKDOWN_VIEW_LOADERS) + ) + template = engine.get_template(self.file_name) + md = markdown.Markdown(extensions=getattr( + settings, + "MARKDOWN_VIEW_EXTENSIONS", + DEFAULT_MARKDOWN_VIEW_EXTENSIONS + )) + template = Template( + "{{% load static %}}{}".format(md.convert(template.source)) + ) + render_context_base = {} + if getattr( + settings, + "MARKDOWN_VIEW_USE_REQUEST_CONTEXT", + DEFAULT_MARKDOWN_VIEW_USE_REQUEST_CONTEXT + ): + render_context_base = context +~~ render_context = Context({ + **render_context_base, + **(getattr( + settings, + "MARKDOWN_VIEW_EXTRA_CONTEXT", + DEFAULT_MARKDOWN_VIEW_EXTRA_CONTEXT + )) + }) + context.update({ + "markdown_content": mark_safe(template.render(render_context)), + "use_highlight_js": getattr( + settings, + "MARKDOWN_VIEW_TEMPLATE_USE_HIGHLIGHT_JS", + DEFAULT_MARKDOWN_VIEW_TEMPLATE_USE_HIGHLIGHT_JS + ), + "use_toc": False, + }) + + if getattr( + settings, + "MARKDOWN_VIEW_TEMPLATE_USE_TOC", + DEFAULT_MARKDOWN_VIEW_TEMPLATE_USE_TOC + ): + context.update({ + "markdown_toc": mark_safe(md.toc), + + +## ... source file continues with no further Context examples... + +``` + + +## Example 10 from django-smithy +[django-smithy](https://github.com/jamiecounsell/django-smithy) is +a [Django](/django.html) code library that allows users to send +HTTP requests from the Django admin user interface. The code for +the project is open source under the +[MIT license](https://github.com/jamiecounsell/django-smithy/blob/master/LICENSE). + +[**django-smithy / smithy / helpers.py**](https://github.com/jamiecounsell/django-smithy/blob/master/smithy/./helpers.py) + +```python +# helpers.py +~~from django.template import Template, Context +from requests_toolbelt.utils import dump + +def render_with_context(template, context): + template = Template(template) +~~ context = Context(context) + return template.render(context) + +def parse_dump_result(fun, obj): + prefixes = dump.PrefixSettings('', '') + try: + result = bytearray() + fun(obj, prefixes, result) + return result.decode('utf-8') + except Exception: + return "Could not parse request as a string" + + + +## ... source file continues with no further Context examples... + +``` + + +## Example 11 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / columns / templatecolumn.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/columns/templatecolumn.py) + +```python +# templatecolumn.py +~~from django.template import Context, Template +from django.template.loader import get_template +from django.utils.html import strip_tags + +from .base import Column, library + + +@library.register +class TemplateColumn(Column): + + empty_values = () + + def __init__(self, template_code=None, template_name=None, extra_context=None, **extra): + super().__init__(**extra) + self.template_code = template_code + self.template_name = template_name + self.extra_context = extra_context or {} + + if not self.template_code and not self.template_name: + raise ValueError("A template must be provided") + + def render(self, record, table, value, bound_column, **kwargs): +~~ context = getattr(table, "context", Context()) + additional_context = { + "default": bound_column.default, + "column": bound_column, + "record": record, + "value": value, + "row_counter": kwargs["bound_row"].row_counter, + } + additional_context.update(self.extra_context) + with context.update(additional_context): + if self.template_code: + return Template(self.template_code).render(context) + else: + return get_template(self.template_name).render(context.flatten()) + + def value(self, **kwargs): + html = super().value(**kwargs) + return strip_tags(html) if isinstance(html, str) else html + + + +## ... source file continues with no further Context examples... + +``` + diff --git a/content/pages/examples/django/django-template-defaultfilters-escape.markdown b/content/pages/examples/django/django-template-defaultfilters-escape.markdown new file mode 100644 index 000000000..b4a4d96b3 --- /dev/null +++ b/content/pages/examples/django/django-template-defaultfilters-escape.markdown @@ -0,0 +1,142 @@ +title: django.template.defaultfilters escape Example Code +category: page +slug: django-template-defaultfilters-escape-examples +sortorder: 500011383 +toc: False +sidebartitle: django.template.defaultfilters escape +meta: Python example code that shows how to use the escape callable from the django.template.defaultfilters module of the Django project. + + +`escape` is a callable within the `django.template.defaultfilters` module of the Django project. + +filesizeformat, +safe, +slugify, +striptags, +title, +and truncatechars +are several other callables with code examples from the same `django.template.defaultfilters` package. + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / admin / pageadmin.py**](https://github.com/divio/django-cms/blob/develop/cms/admin/pageadmin.py) + +```python +# pageadmin.py +import uuid + + +import django +from django.contrib.admin.helpers import AdminForm +from django.conf import settings +from django.urls import re_path +from django.contrib import admin, messages +from django.contrib.admin.models import LogEntry, CHANGE +from django.contrib.admin.options import IS_POPUP_VAR +from django.contrib.admin.utils import get_deleted_objects +from django.contrib.contenttypes.models import ContentType +from django.contrib.sites.models import Site +from django.core.exceptions import (ObjectDoesNotExist, + PermissionDenied, ValidationError) +from django.db import router, transaction +from django.db.models import Q, Prefetch +from django.http import ( + HttpResponseRedirect, + HttpResponse, + Http404, + HttpResponseBadRequest, + HttpResponseForbidden, +) +from django.shortcuts import render, get_object_or_404 +~~from django.template.defaultfilters import escape +from django.template.loader import get_template +from django.template.response import SimpleTemplateResponse, TemplateResponse +from django.utils.encoding import force_text +from django.utils.translation import gettext, gettext_lazy as _, get_language +from django.utils.decorators import method_decorator +from django.views.decorators.http import require_POST +from django.http import QueryDict + +from cms import operations +from cms.admin.forms import ( + AddPageForm, + AddPageTypeForm, + AdvancedSettingsForm, + ChangePageForm, + ChangeListForm, + CopyPageForm, + CopyPermissionForm, + DuplicatePageForm, + MovePageForm, + PagePermissionForm, + PublicationDatesForm, +) +from cms.admin.permissionadmin import PERMISSION_ADMIN_INLINES +from cms.admin.placeholderadmin import PlaceholderAdminMixin + + +## ... source file abbreviated to get to escape examples ... + + + site = self.get_site(request) + language = get_site_language_from_request(request, site_id=site.pk) + languages = self._get_site_languages(request, obj) + context.update({ + 'language': language, + 'language_tabs': languages, + 'show_language_tabs': len(list(languages)) > 1 and not context.get('publishing_dates', False), + }) + return context + + def get_preserved_filters(self, request): + preserved_filters_encoded = super().get_preserved_filters(request) + preserved_filters = QueryDict(preserved_filters_encoded).copy() + lang = request.GET.get('language') + + if lang: + preserved_filters.update({ + 'language': lang + }) + + return preserved_filters.urlencode() + + def _get_404_exception(self, object_id): + exception = Http404(_('%(name)s object with primary key %(key)r does not exist.') % { + 'name': force_text(self.opts.verbose_name), +~~ 'key': escape(object_id), + }) + return exception + + def _has_add_permission_from_request(self, request): + site = self.get_site(request) + parent_node_id = request.GET.get('parent_node', None) + + if parent_node_id: + try: + parent_item = self.get_queryset(request).get(node=parent_node_id) + except self.model.DoesNotExist: + return False + else: + parent_item = None + + if parent_item: + has_perm = page_permissions.user_can_add_subpage( + request.user, + target=parent_item, + site=site, + ) + else: + has_perm = page_permissions.user_can_add_page(request.user, site=site) + return has_perm + + +## ... source file continues with no further escape examples... + +``` + diff --git a/content/pages/examples/django/django-template-defaultfilters-filesizeformat.markdown b/content/pages/examples/django/django-template-defaultfilters-filesizeformat.markdown new file mode 100644 index 000000000..6847f62c8 --- /dev/null +++ b/content/pages/examples/django/django-template-defaultfilters-filesizeformat.markdown @@ -0,0 +1,137 @@ +title: django.template.defaultfilters filesizeformat Example Code +category: page +slug: django-template-defaultfilters-filesizeformat-examples +sortorder: 500011384 +toc: False +sidebartitle: django.template.defaultfilters filesizeformat +meta: Python example code that shows how to use the filesizeformat callable from the django.template.defaultfilters module of the Django project. + + +`filesizeformat` is a callable within the `django.template.defaultfilters` module of the Django project. + +escape, +safe, +slugify, +striptags, +title, +and truncatechars +are several other callables with code examples from the same `django.template.defaultfilters` package. + +## Example 1 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / images / fields.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/images/fields.py) + +```python +# fields.py +import os + +import willow + +from django.conf import settings +from django.core.exceptions import ValidationError +from django.forms.fields import ImageField +~~from django.template.defaultfilters import filesizeformat +from django.utils.translation import gettext_lazy as _ + + +ALLOWED_EXTENSIONS = ['gif', 'jpg', 'jpeg', 'png', 'webp'] +SUPPORTED_FORMATS_TEXT = _("GIF, JPEG, PNG, WEBP") + + +class WagtailImageField(ImageField): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.max_upload_size = getattr(settings, 'WAGTAILIMAGES_MAX_UPLOAD_SIZE', 10 * 1024 * 1024) + self.max_image_pixels = getattr(settings, 'WAGTAILIMAGES_MAX_IMAGE_PIXELS', 128 * 1000000) +~~ max_upload_size_text = filesizeformat(self.max_upload_size) + + if self.max_upload_size is not None: + self.help_text = _( + "Supported formats: %(supported_formats)s. Maximum filesize: %(max_upload_size)s." + ) % { + 'supported_formats': SUPPORTED_FORMATS_TEXT, + 'max_upload_size': max_upload_size_text, + } + else: + self.help_text = _( + "Supported formats: %(supported_formats)s." + ) % { + 'supported_formats': SUPPORTED_FORMATS_TEXT, + } + + self.error_messages['invalid_image_extension'] = _( + "Not a supported image format. Supported formats: %s." + ) % SUPPORTED_FORMATS_TEXT + + self.error_messages['invalid_image_known_format'] = _( + "Not a valid %s image." + ) + + self.error_messages['file_too_large'] = _( + + +## ... source file abbreviated to get to filesizeformat examples ... + + + def check_image_file_format(self, f): + extension = os.path.splitext(f.name)[1].lower()[1:] + + if extension not in ALLOWED_EXTENSIONS: + raise ValidationError(self.error_messages['invalid_image_extension'], code='invalid_image_extension') + + image_format = extension.upper() + if image_format == 'JPG': + image_format = 'JPEG' + + internal_image_format = f.image.format.upper() + if internal_image_format == 'MPO': + internal_image_format = 'JPEG' + + if internal_image_format != image_format: + raise ValidationError(self.error_messages['invalid_image_known_format'] % ( + image_format, + ), code='invalid_image_known_format') + + def check_image_file_size(self, f): + if self.max_upload_size is None: + return + + if f.size > self.max_upload_size: + raise ValidationError(self.error_messages['file_too_large'] % ( +~~ filesizeformat(f.size), + ), code='file_too_large') + + def check_image_pixel_size(self, f): + if self.max_image_pixels is None: + return + + image = willow.Image.open(f) + width, height = image.get_size() + frames = image.get_frame_count() + num_pixels = width * height * frames + + if num_pixels > self.max_image_pixels: + raise ValidationError(self.error_messages['file_too_many_pixels'] % ( + num_pixels + ), code='file_too_many_pixels') + + def to_python(self, data): + f = super().to_python(data) + + if f is not None: + self.check_image_file_size(f) + self.check_image_file_format(f) + self.check_image_pixel_size(f) + + + +## ... source file continues with no further filesizeformat examples... + +``` + diff --git a/content/pages/examples/django/django-template-defaultfilters-safe.markdown b/content/pages/examples/django/django-template-defaultfilters-safe.markdown new file mode 100644 index 000000000..b4b6211df --- /dev/null +++ b/content/pages/examples/django/django-template-defaultfilters-safe.markdown @@ -0,0 +1,102 @@ +title: django.template.defaultfilters safe Example Code +category: page +slug: django-template-defaultfilters-safe-examples +sortorder: 500011385 +toc: False +sidebartitle: django.template.defaultfilters safe +meta: Python example code that shows how to use the safe callable from the django.template.defaultfilters module of the Django project. + + +`safe` is a callable within the `django.template.defaultfilters` module of the Django project. + +escape, +filesizeformat, +slugify, +striptags, +title, +and truncatechars +are several other callables with code examples from the same `django.template.defaultfilters` package. + +## Example 1 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / gis / widgets.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/gis/widgets.py) + +```python +# widgets.py +from django.conf import settings +~~from django.template.defaultfilters import safe +from django.utils import translation + +import floppyforms as forms + +from urllib.parse import urlencode + +try: + from django.contrib.gis import gdal, geos +except ImportError: + + +__all__ = ('GeometryWidget', 'GeometryCollectionWidget', + 'PointWidget', 'MultiPointWidget', + 'LineStringWidget', 'MultiLineStringWidget', + 'PolygonWidget', 'MultiPolygonWidget', + 'BaseGeometryWidget', 'BaseMetacartaWidget', + 'BaseOsmWidget', 'BaseGMapWidget') + + +class BaseGeometryWidget(forms.Textarea): + display_wkt = False + map_width = 600 + map_height = 400 + map_srid = 4326 + + +## ... source file abbreviated to get to safe examples ... + + + map_srid = 3857 + template_name = 'floppyforms/gis/osm.html' + + class Media: + js = ( + 'floppyforms/openlayers/OpenLayers.js', + 'https://www.openstreetmap.org/openlayers/OpenStreetMap.js', + 'floppyforms/js/MapWidget.js', + ) + + +class BaseGMapWidget(BaseGeometryWidget): + map_srid = 3857 + template_name = 'floppyforms/gis/google.html' + google_maps_api_key = None + + @property + def media(self): + qs_dict = {'v': '3'} + if self.google_maps_api_key is not None: + qs_dict['key'] = self.google_maps_api_key + + js = ( + 'floppyforms/openlayers/OpenLayers.js', + 'floppyforms/js/MapWidget.js', +~~ safe('https://maps.google.com/maps/api/js?' + urlencode(qs_dict)) + ) + return forms.Media(js=js) + + + +## ... source file continues with no further safe examples... + +``` + diff --git a/content/pages/examples/django/django-template-defaultfilters-slugify.markdown b/content/pages/examples/django/django-template-defaultfilters-slugify.markdown new file mode 100644 index 000000000..ab2ba8cc6 --- /dev/null +++ b/content/pages/examples/django/django-template-defaultfilters-slugify.markdown @@ -0,0 +1,276 @@ +title: django.template.defaultfilters slugify Example Code +category: page +slug: django-template-defaultfilters-slugify-examples +sortorder: 500011386 +toc: False +sidebartitle: django.template.defaultfilters slugify +meta: Python example code that shows how to use the slugify callable from the django.template.defaultfilters module of the Django project. + + +`slugify` is a callable within the `django.template.defaultfilters` module of the Django project. + +escape, +filesizeformat, +safe, +striptags, +title, +and truncatechars +are several other callables with code examples from the same `django.template.defaultfilters` package. + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_pool.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_pool.py) + +```python +# plugin_pool.py +from operator import attrgetter + +from django.core.exceptions import ImproperlyConfigured +from django.urls import re_path, include +~~from django.template.defaultfilters import slugify +from django.utils.encoding import force_text +from django.utils.functional import cached_property +from django.utils.module_loading import autodiscover_modules +from django.utils.translation import get_language, deactivate_all, activate +from django.template import TemplateDoesNotExist, TemplateSyntaxError + +from cms.exceptions import PluginAlreadyRegistered, PluginNotRegistered +from cms.plugin_base import CMSPluginBase +from cms.utils.conf import get_cms_setting +from cms.utils.helpers import normalize_name + + +class PluginPool: + + def __init__(self): + self.plugins = {} + self.discovered = False + + def _clear_cached(self): + if 'registered_plugins' in self.__dict__: + del self.__dict__['registered_plugins'] + + if 'plugins_with_extra_menu' in self.__dict__: + del self.__dict__['plugins_with_extra_menu'] + + +## ... source file abbreviated to get to slugify examples ... + + + if placeholder: + plugins = (plugin for plugin in plugins + if not plugin.requires_parent_plugin(placeholder, page)) + return sorted(plugins, key=attrgetter('module')) + + def get_text_enabled_plugins(self, placeholder, page): + plugins = set(self.get_all_plugins(placeholder, page)) + plugins.update(self.get_all_plugins(placeholder, page, 'text_only_plugins')) + return sorted((p for p in plugins if p.text_enabled), + key=attrgetter('module', 'name')) + + def get_plugin(self, name): + self.discover_plugins() + return self.plugins[name] + + def get_patterns(self): + self.discover_plugins() + + lang = get_language() + deactivate_all() + + try: + url_patterns = [] + for plugin in self.registered_plugins: + p = plugin() +~~ slug = slugify(force_text(normalize_name(p.__class__.__name__))) + url_patterns += [ + re_path(r'^plugin/%s/' % (slug,), include(p.plugin_urls)), + ] + finally: + activate(lang) + + return url_patterns + + def get_system_plugins(self): + self.discover_plugins() + return [plugin.__name__ for plugin in self.plugins.values() if plugin.system] + + @cached_property + def registered_plugins(self): + return self.get_all_plugins() + + @cached_property + def plugins_with_extra_menu(self): + plugin_classes = [cls for cls in self.registered_plugins + if cls._has_extra_plugin_menu_items] + return plugin_classes + + @cached_property + def plugins_with_extra_placeholder_menu(self): + + +## ... source file continues with no further slugify examples... + +``` + + +## Example 2 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / utils / files.py**](https://github.com/divio/django-filer/blob/develop/filer/utils/files.py) + +```python +# files.py +from __future__ import absolute_import, unicode_literals + +import mimetypes +import os + +from django.http.multipartparser import ( + ChunkIter, SkipFile, StopFutureHandlers, StopUpload, exhaust, +) +~~from django.template.defaultfilters import slugify as slugify_django +from django.utils.encoding import force_text +from django.utils.text import get_valid_filename as get_valid_filename_django + +from unidecode import unidecode + + +class UploadException(Exception): + pass + + +def handle_upload(request): + if not request.method == "POST": + raise UploadException("AJAX request not valid: must be POST") + if request.is_ajax(): + is_raw = True + filename = request.GET.get('qqfile', False) or request.GET.get('filename', False) or '' + + try: + content_length = int(request.META['CONTENT_LENGTH']) + except (IndexError, TypeError, ValueError): + content_length = None + + if content_length < 0: + raise UploadException("Invalid content length: %r" % content_length) + + +## ... source file abbreviated to get to slugify examples ... + + + for i, handler in enumerate(upload_handlers): + file_obj = handler.file_complete(counters[i]) + if file_obj: + upload = file_obj + break + else: + if len(request.FILES) == 1: + upload, filename, is_raw, mime_type = handle_request_files_upload(request) + else: + raise UploadException("AJAX request not valid: Bad Upload") + return upload, filename, is_raw, mime_type + + +def handle_request_files_upload(request): + is_raw = False + upload = list(request.FILES.values())[0] + filename = upload.name + _, iext = os.path.splitext(filename) + mime_type = upload.content_type.lower() + if iext not in mimetypes.guess_all_extensions(mime_type): + msg = "MIME-Type '{mimetype}' does not correspond to file extension of {filename}." + raise UploadException(msg.format(mimetype=mime_type, filename=filename)) + return upload, filename, is_raw, mime_type + + +~~def slugify(string): + return slugify_django(unidecode(force_text(string))) + + +def get_valid_filename(s): + s = get_valid_filename_django(s) + filename, ext = os.path.splitext(s) +~~ filename = slugify(filename) +~~ ext = slugify(ext) + if ext: + return "%s.%s" % (filename, ext) + else: + return "%s" % (filename,) + + + +## ... source file continues with no further slugify examples... + +``` + + +## Example 3 from gadget-board +[gadget-board](https://github.com/mik4el/gadget-board) is a +[Django](/django.html), +[Django REST Framework (DRF)](/django-rest-framework-drf.html) and +[Angular](/angular.html) web application that is open source under the +[Apache2 license](https://github.com/mik4el/gadget-board/blob/master/LICENSE). + +[**gadget-board / web / gadgets / models.py**](https://github.com/mik4el/gadget-board/blob/master/web/gadgets/models.py) + +```python +# models.py +from django.db import models +from django.contrib.postgres.fields import JSONField +~~from django.template.defaultfilters import slugify +from authentication.models import Account + + +class Gadget(models.Model): + name = models.CharField(max_length=40, unique=True) + slug = models.SlugField(null=True, blank=True) + description = models.TextField() + users_can_upload = models.ManyToManyField(Account) + image_name = models.CharField(max_length=140, blank=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + @property + def image_url(self): + if self.image_name != "": + return "backend/static/media/{}".format(self.image_name) + else: + return "backend/static/dashboard_icon_big.png" + + def __str__(self): + return self.name + + def save(self, *args, **kwargs): + if not self.id: +~~ self.slug = slugify(self.name) + + super(Gadget, self).save(*args, **kwargs) + + +class GadgetData(models.Model): + gadget = models.ForeignKey(Gadget, db_index=True, on_delete=models.DO_NOTHING) # Add index on filtered fields + data = JSONField() + added_by = models.ForeignKey(Account, on_delete=models.DO_NOTHING) + timestamp = models.DateTimeField(null=True, blank=True, db_index=True) # Add index on filtered fields + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return '{} {} {}'.format(self.gadget, self.timestamp, self.added_by) + + + +## ... source file continues with no further slugify examples... + +``` + diff --git a/content/pages/examples/django/django-template-defaultfilters-striptags.markdown b/content/pages/examples/django/django-template-defaultfilters-striptags.markdown new file mode 100644 index 000000000..5d837a866 --- /dev/null +++ b/content/pages/examples/django/django-template-defaultfilters-striptags.markdown @@ -0,0 +1,159 @@ +title: django.template.defaultfilters striptags Example Code +category: page +slug: django-template-defaultfilters-striptags-examples +sortorder: 500011387 +toc: False +sidebartitle: django.template.defaultfilters striptags +meta: Python example code that shows how to use the striptags callable from the django.template.defaultfilters module of the Django project. + + +`striptags` is a callable within the `django.template.defaultfilters` module of the Django project. + +escape, +filesizeformat, +safe, +slugify, +title, +and truncatechars +are several other callables with code examples from the same `django.template.defaultfilters` package. + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / templatetags / wiki_tags.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/templatetags/wiki_tags.py) + +```python +# wiki_tags.py +import re +from urllib.parse import quote as urlquote + +from django import template +from django.apps import apps +from django.conf import settings as django_settings +from django.contrib.contenttypes.models import ContentType +from django.db.models import Model +from django.forms import BaseForm +~~from django.template.defaultfilters import striptags +from django.utils.safestring import mark_safe +from wiki import models +from wiki.conf import settings +from wiki.core.plugins import registry as plugin_registry + +register = template.Library() + + +_cache = {} + + +@register.simple_tag(takes_context=True) +def article_for_object(context, obj): + if not isinstance(obj, Model): + raise TypeError( + "A Wiki article can only be associated to a Django Model " + "instance, not %s" % type(obj) + ) + + content_type = ContentType.objects.get_for_model(obj) + + if True or obj not in _cache: + try: + article = models.ArticleForObject.objects.get( + + +## ... source file abbreviated to get to striptags examples ... + + +@register.inclusion_tag("wiki/includes/form.html", takes_context=True) +def wiki_form(context, form_obj): + if not isinstance(form_obj, BaseForm): + raise TypeError( + "Error including form, it's not a form, it's a %s" % type(form_obj) + ) + context.update({"form": form_obj}) + return context + + +@register.inclusion_tag("wiki/includes/messages.html", takes_context=True) +def wiki_messages(context): + + messages = context.get("messages", []) + for message in messages: + message.css_class = settings.MESSAGE_TAG_CSS_CLASS[message.level] + context.update({"messages": messages}) + return context + + +@register.filter +def get_content_snippet(content, keyword, max_words=30): + + def clean_text(content): + +~~ content = striptags(content) + words = content.split() + + return words + + max_words = int(max_words) + + match_position = content.lower().find(keyword.lower()) + + if match_position != -1: + try: + match_start = content.rindex(" ", 0, match_position) + 1 + except ValueError: + match_start = 0 + try: + match_end = content.index(" ", match_position + len(keyword)) + except ValueError: + match_end = len(content) + all_before = clean_text(content[:match_start]) + match = content[match_start:match_end] + all_after = clean_text(content[match_end:]) + before_words = all_before[-max_words // 2 :] + after_words = all_after[: max_words - len(before_words)] + before = " ".join(before_words) + after = " ".join(after_words) +~~ html = ("%s %s %s" % (before, striptags(match), after)).strip() + kw_p = re.compile(r"(\S*%s\S*)" % keyword, re.IGNORECASE) + html = kw_p.sub(r"\1", html) + + return mark_safe(html) + + return " ".join(clean_text(content)[:max_words]) + + +@register.filter +def can_read(obj, user): + return obj.can_read(user) + + +@register.filter +def can_write(obj, user): + return obj.can_write(user) + + +@register.filter +def can_delete(obj, user): + return obj.can_delete(user) + + +@register.filter + + +## ... source file continues with no further striptags examples... + +``` + diff --git a/content/pages/examples/django/django-template-defaultfilters-title.markdown b/content/pages/examples/django/django-template-defaultfilters-title.markdown new file mode 100644 index 000000000..97ac646e7 --- /dev/null +++ b/content/pages/examples/django/django-template-defaultfilters-title.markdown @@ -0,0 +1,124 @@ +title: django.template.defaultfilters title Example Code +category: page +slug: django-template-defaultfilters-title-examples +sortorder: 500011388 +toc: False +sidebartitle: django.template.defaultfilters title +meta: Python example code that shows how to use the title callable from the django.template.defaultfilters module of the Django project. + + +`title` is a callable within the `django.template.defaultfilters` module of the Django project. + +escape, +filesizeformat, +safe, +slugify, +striptags, +and truncatechars +are several other callables with code examples from the same `django.template.defaultfilters` package. + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / models / placeholdermodel.py**](https://github.com/divio/django-cms/blob/develop/cms/models/placeholdermodel.py) + +```python +# placeholdermodel.py + +import warnings + +from datetime import datetime, timedelta + +from django.contrib import admin +from django.db import models +~~from django.template.defaultfilters import title +from django.utils.encoding import force_text +from django.utils.translation import gettext_lazy as _ + +from cms.cache.placeholder import clear_placeholder_cache +from cms.exceptions import LanguageError +from cms.utils import get_site_id +from cms.utils.i18n import get_language_object +from cms.utils.urlutils import admin_reverse +from cms.constants import ( + EXPIRE_NOW, + MAX_EXPIRATION_TTL, + PUBLISHER_STATE_DIRTY, +) +from cms.utils import get_language_from_request +from cms.utils import permissions +from cms.utils.conf import get_cms_setting + + +class Placeholder(models.Model): + slot = models.CharField(_("slot"), max_length=255, db_index=True, editable=False) + default_width = models.PositiveSmallIntegerField(_("width"), null=True, editable=False) + cache_placeholder = True + is_static = False + is_editable = True + + +## ... source file abbreviated to get to title examples ... + + + slot=self.slot, + location=hex(id(self)), + ) + return display + + def clear(self, language=None): + if language: + qs = self.cmsplugin_set.filter(language=language) + else: + qs = self.cmsplugin_set.all() + qs = qs.order_by('-depth').select_related() + for plugin in qs: + inst, cls = plugin.get_plugin_instance() + if inst and getattr(inst, 'cmsplugin_ptr', False): + inst.cmsplugin_ptr._no_reorder = True + inst._no_reorder = True + inst.delete(no_mp=True) + else: + plugin._no_reorder = True + plugin.delete(no_mp=True) + + def get_label(self): + from cms.utils.placeholder import get_placeholder_conf + + template = self.page.get_template() if self.page else None +~~ name = get_placeholder_conf("name", self.slot, template=template, default=title(self.slot)) + name = _(name) + return name + + def get_extra_context(self, template=None): + from cms.utils.placeholder import get_placeholder_conf + return get_placeholder_conf("extra_context", self.slot, template, {}) + + def get_add_url(self): + return self._get_url('add_plugin') + + def get_edit_url(self, plugin_pk): + return self._get_url('edit_plugin', plugin_pk) + + def get_move_url(self): + return self._get_url('move_plugin') + + def get_delete_url(self, plugin_pk): + return self._get_url('delete_plugin', plugin_pk) + + def get_changelist_url(self): + return self._get_url('changelist') + + def get_clear_url(self): + return self._get_url('clear_placeholder', self.pk) + + +## ... source file continues with no further title examples... + +``` + diff --git a/content/pages/examples/django/django-template-defaultfilters-truncatechars.markdown b/content/pages/examples/django/django-template-defaultfilters-truncatechars.markdown new file mode 100644 index 000000000..96cc9ffa6 --- /dev/null +++ b/content/pages/examples/django/django-template-defaultfilters-truncatechars.markdown @@ -0,0 +1,223 @@ +title: django.template.defaultfilters truncatechars Example Code +category: page +slug: django-template-defaultfilters-truncatechars-examples +sortorder: 500011389 +toc: False +sidebartitle: django.template.defaultfilters truncatechars +meta: Python example code that shows how to use the truncatechars callable from the django.template.defaultfilters module of the Django project. + + +`truncatechars` is a callable within the `django.template.defaultfilters` module of the Django project. + +escape, +filesizeformat, +safe, +slugify, +striptags, +and title +are several other callables with code examples from the same `django.template.defaultfilters` package. + +## Example 1 from django-appmail +[Django-Appmail](https://github.com/yunojuno/django-appmail) +([PyPI package information](https://pypi.org/project/django-appmail/)) +is a [Django](/django.html) app for handling transactional email templates. +While the project began development as a way to work with the Mandrill +transactional [API](/application-programming-interfaces.html), it is +not exclusive to that API. The project simply provides a way to store +and render email content. The library does not send or receive emails. + +Django-Appmail is open sourced under the +[MIT license](https://github.com/yunojuno/django-appmail/blob/master/LICENSE). + +[**django-appmail / appmail / admin.py**](https://github.com/yunojuno/django-appmail/blob/master/appmail/./admin.py) + +```python +# admin.py +from __future__ import annotations + +import json +from typing import Optional, Tuple + +from django.contrib import admin, messages +from django.core.exceptions import ValidationError +from django.db.models.query import QuerySet +from django.http import HttpRequest, HttpResponseRedirect +~~from django.template.defaultfilters import truncatechars +from django.urls import reverse +from django.utils.html import format_html +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _lazy + +from .compat import JSONField +from .forms import JSONWidget +from .models import EmailTemplate, LoggedMessage + + +class ValidTemplateListFilter(admin.SimpleListFilter): + + title = _lazy("Is valid") + parameter_name = "valid" + + def lookups( + self, request: HttpRequest, model_admin: admin.ModelAdmin + ) -> Tuple[Tuple[str, str], Tuple[str, str]]: + return (("1", _lazy("True")), ("0", _lazy("False"))) + + def queryset(self, request: HttpRequest, queryset: QuerySet) -> QuerySet: + valid_ids = [] + invalid_ids = [] + for obj in queryset: + + +## ... source file abbreviated to get to truncatechars examples ... + + + + exclude = ("html", "context") + + formfield_overrides = {JSONField: {"widget": JSONWidget}} + + list_display = ("to", "template_name", "_subject", "timestamp") + + list_filter = ("timestamp", "template__name", "template__language") + + raw_id_fields = ("user", "template") + + readonly_fields = ( + "to", + "user", + "template", + "template_context", + "subject", + "body", + "render_html", + "timestamp", + ) + + search_fields = ("to", "subject") + + def _subject(self, obj: LoggedMessage) -> str: +~~ return truncatechars(obj.subject, 50) + + def template_name(self, obj: LoggedMessage) -> str: + return obj.template.name + + def template_context(self, obj: LoggedMessage) -> str: + return self.pretty_print(obj.context) + + def render_html(self, obj: LoggedMessage) -> str: + if obj.id is None: + url = "" + else: + url = reverse( + "appmail:render_message_body_html", kwargs={"email_id": obj.id} + ) + return self.iframe(url) + + render_html.short_description = "HTML (rendered)" # type: ignore + render_html.allow_tags = True # type: ignore + + + +## ... source file continues with no further truncatechars examples... + +``` + + +## Example 2 from elasticsearch-django +[elasticsearch-django](https://github.com/yunojuno/elasticsearch-django) +([PyPI package information](https://pypi.org/project/elasticsearch-django/)) +is a [Django](/django.html) app for managing +[ElasticSearch](https://github.com/elastic/elasticsearch) indexes +populated by [Django ORM](/django-orm.html) models. The project is +available as open source under the +[MIT license](https://github.com/yunojuno/elasticsearch-django/blob/master/LICENSE). + +[**elasticsearch-django / elasticsearch_django / admin.py**](https://github.com/yunojuno/elasticsearch-django/blob/master/elasticsearch_django/./admin.py) + +```python +# admin.py +import logging + +import simplejson as json # simplejson supports Decimal serialization +from django.contrib import admin +~~from django.template.defaultfilters import truncatechars, truncatewords +from django.utils.safestring import mark_safe + +from .models import SearchQuery + +logger = logging.getLogger(__name__) + + +def pprint(data: dict) -> str: + pretty = json.dumps(data, sort_keys=True, indent=4, separators=(",", ": ")) + html = pretty.replace(" ", " ").replace("\n", "
") + return mark_safe("%s" % html) + + +class SearchQueryAdmin(admin.ModelAdmin): + + list_display = ( + "id", + "user", + "search_terms_display", + "total_hits_display", + "returned_", + "min_", + "max_", + "reference", + "executed_at", + ) + list_filter = ("index", "query_type") + search_fields = ("search_terms", "user__first_name", "user__last_name", "reference") + exclude = ("hits", "aggregations", "query", "page", "total_hits_") + readonly_fields = ( + "user", + "index", + "search_terms", + "query_type", + "total_hits", + "total_hits_relation", + "returned_", + "min_", + "max_", + "duration", + "query_", + "hits_", + "aggregations_", + "executed_at", + ) + + def search_terms_display(self, instance: SearchQuery) -> str: + raw = instance.search_terms +~~ return truncatechars(truncatewords(raw, 5), 50) + + def query_(self, instance: SearchQuery) -> str: + return pprint(instance.query) + + def max_(self, instance: SearchQuery) -> str: + return "-" if instance.page_size == 0 else str(instance.max_score) + + max_.short_description = "Max score" # type: ignore + + def min_(self, instance: SearchQuery) -> str: + return "-" if instance.page_size == 0 else str(instance.min_score) + + min_.short_description = "Min score" # type: ignore + + def total_hits_display(self, instance: SearchQuery) -> str: + if instance.total_hits_relation == SearchQuery.TotalHitsRelation.ESTIMATE: + return f"{instance.total_hits}*" + return f"{instance.total_hits}" + + def returned_(self, instance: SearchQuery) -> str: + if instance.page_size == 0: + return "-" + return "%i - %i" % (instance.page_from, instance.page_to) + + + +## ... source file continues with no further truncatechars examples... + +``` + diff --git a/content/pages/examples/django/django-template-loader-get-template.markdown b/content/pages/examples/django/django-template-loader-get-template.markdown new file mode 100644 index 000000000..1665b4ca0 --- /dev/null +++ b/content/pages/examples/django/django-template-loader-get-template.markdown @@ -0,0 +1,469 @@ +title: django.template.loader get_template Example Code +category: page +slug: django-template-loader-get-template-examples +sortorder: 500011392 +toc: False +sidebartitle: django.template.loader get_template +meta: Python example code that shows how to use the get_template callable from the django.template.loader module of the Django project. + + +`get_template` is a callable within the `django.template.loader` module of the Django project. + +render_to_string +and +select_template +are a couple of other callables within the `django.template.loader` package that also have code examples. + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / chair_mail / views.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/chair_mail/views.py) + +```python +# views.py +from django.contrib import messages +from django.http import JsonResponse, HttpResponse +from django.shortcuts import render, get_object_or_404, redirect +~~from django.template.loader import get_template +from django.urls import reverse +from django.utils import timezone +from django.views.decorators.http import require_GET, require_POST + +from conferences.utilities import validate_chair_access +from chair_mail.context import USER_VARS, CONFERENCE_VARS, SUBMISSION_VARS, \ + FRAME_VARS +from chair_mail.forms import EmailFrameUpdateForm, EmailFrameTestForm, \ + MessageForm, get_preview_form_class, EditNotificationForm, \ + UpdateNotificationStateForm +from chair_mail.mailing_lists import ALL_LISTS +from chair_mail.models import EmailSettings, EmailFrame, EmailMessage, \ + GroupMessage, MSG_TYPE_USER, MSG_TYPE_SUBMISSION, get_group_message_model, \ + get_message_leaf_model, SystemNotification, DEFAULT_NOTIFICATIONS_DATA +from chair_mail.utility import get_email_frame, get_email_frame_or_404, \ + reverse_preview_url, reverse_list_objects_url, get_object_name, \ + get_object_url +from conferences.models import Conference + + +def _get_grouped_vars(msg_type): + if msg_type == MSG_TYPE_USER: + return ( + ('Conference variables', CONFERENCE_VARS), + + +## ... source file abbreviated to get to get_template examples ... + + + ('Submission variables', SUBMISSION_VARS), + ) + raise ValueError(f'unrecognized message type "{msg_type}"') + + +@require_GET +def overview(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + frame = get_email_frame(conference) + return render(request, 'chair_mail/tab_pages/overview.html', context={ + 'conference': conference, + 'frame': frame, + 'active_tab': 'overview', + }) + + +@require_POST +def create_frame(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + if not hasattr(conference, 'email_settings'): + EmailSettings.objects.create(conference=conference) + email_settings = conference.email_settings + frame = email_settings.frame +~~ template_html = get_template( + 'chair_mail/email/default_frame_html.html').template +~~ template_plain = get_template( + 'chair_mail/email/default_frame_plain.txt').template + if frame: + frame.text_html = template_html.source + frame.text_plain = template_plain.source + frame.created_at = timezone.now() + frame.updated_at = timezone.now() + frame.created_by = request.user + frame.save() + messages.success(request, 'Reset existing frame') + else: + frame = EmailFrame.objects.create( + conference=conference, + created_by=request.user, + text_plain=template_plain.source, + text_html=template_html.source, + ) + email_settings.frame = frame + email_settings.save() + messages.success(request, 'Created new template') + + default_next = reverse('chair_mail:overview', kwargs={'conf_pk': conf_pk}) + next_url = request.GET.get('next', default_next) + return redirect(next_url) + + + +## ... source file continues with no further get_template examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / templates.py**](https://github.com/divio/django-cms/blob/develop/cms/./templates.py) + +```python +# templates.py +~~from django.template.loader import get_template +from django.utils.functional import cached_property + + +class TemplatesCache: + + def __init__(self): + self._cached_templates = {} + + def get_cached_template(self, template): + if hasattr(template, 'render'): + return template + + if not template in self._cached_templates: +~~ self._cached_templates[template] = get_template(template) + return self._cached_templates[template] + + @cached_property + def drag_item_template(self): +~~ return get_template('cms/toolbar/dragitem.html') + + @cached_property + def placeholder_plugin_menu_template(self): +~~ return get_template('cms/toolbar/dragitem_menu.html') + + @cached_property + def dragbar_template(self): +~~ return get_template('cms/toolbar/dragbar.html') + + + +## ... source file continues with no further get_template examples... + +``` + + +## Example 3 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / compat.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./compat.py) + +```python +# compat.py +from contextlib import contextmanager + +import django +from django.template import Context +from django.utils.datastructures import MultiValueDict + +MULTIVALUE_DICT_TYPES = (MultiValueDict,) + + +REQUIRED_CONTEXT_ATTRIBTUES = ( + '_form_config', + '_form_render', +) + + +class DictContext(dict): + pass + + +if django.VERSION < (1, 8): +~~ def get_template(context, template_name): +~~ from django.template.loader import get_template +~~ return get_template(template_name) + + def get_context(context): + if not isinstance(context, Context): + context = Context(context) + return context + +else: +~~ def get_template(context, template_name): + return context.template.engine.get_template(template_name) + + def get_context(context): + return context + + +def flatten_context(context): + if isinstance(context, Context): + flat = {} + for d in context.dicts: + flat.update(d) + return flat + else: + return context + + +def flatten_contexts(*contexts): + new_context = DictContext() + for context in contexts: + if context is not None: + new_context.update(flatten_context(context)) + for attr in REQUIRED_CONTEXT_ATTRIBTUES: + if hasattr(context, attr): + setattr(new_context, attr, getattr(context, attr)) + + +## ... source file continues with no further get_template examples... + +``` + + +## Example 4 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / sitetreeapp.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./sitetreeapp.py) + +```python +# sitetreeapp.py +import warnings +from collections import defaultdict +from copy import deepcopy +from inspect import getfullargspec +from sys import exc_info +from threading import local +from typing import Callable, List, Optional, Dict, Union, Sequence, Any, Tuple + +from django.conf import settings +from django.core.cache import caches +from django.db.models import signals, QuerySet +from django.template.base import ( + FilterExpression, Lexer, Parser, Variable, VariableDoesNotExist, VARIABLE_TAG_START) +from django.template.context import Context +~~from django.template.loader import get_template +from django.urls import reverse, NoReverseMatch +from django.utils import module_loading +from django.utils.encoding import iri_to_uri +from django.utils.translation import get_language + +from .compat import TOKEN_TEXT, TOKEN_VAR +from .exceptions import SiteTreeError +from .settings import ( + ALIAS_TRUNK, ALIAS_THIS_CHILDREN, ALIAS_THIS_SIBLINGS, ALIAS_THIS_PARENT_SIBLINGS, ALIAS_THIS_ANCESTOR_CHILDREN, + UNRESOLVED_ITEM_MARKER, RAISE_ITEMS_ERRORS_ON_DEBUG, CACHE_TIMEOUT, CACHE_NAME, DYNAMIC_ONLY, ADMIN_APP_NAME, + SITETREE_CLS) +from .utils import get_tree_model, get_tree_item_model, import_app_sitetree_module, generate_id_for + +if False: # pragma: nocover + from django.contrib.auth.models import User # noqa + from .models import TreeItemBase, TreeBase + +TypeDynamicTrees = Dict[str, Union[Dict[str, List['TreeBase']], List['TreeBase']]] + +MODEL_TREE_CLASS = get_tree_model() +MODEL_TREE_ITEM_CLASS = get_tree_item_model() + + +_ITEMS_PROCESSOR: Optional[Callable] = None + + +## ... source file abbreviated to get to get_template examples ... + + + return [] + + tree_items = self.filter_items(self.get_children(tree_alias, None), 'sitetree') + tree_items = self.apply_hook(tree_items, 'sitetree') + self.update_has_children(tree_alias, tree_items, 'sitetree') + + return tree_items + + def children( + self, + parent_item: 'TreeItemBase', + navigation_type: str, + use_template: str, + context: Context + ) -> str: + parent_item = self.resolve_var(parent_item, context) + tree_alias, tree_items = self.get_sitetree(parent_item.tree.alias) + + self.tree_climber(tree_alias, self.get_tree_current_item(tree_alias)) + + tree_items = self.get_children(tree_alias, parent_item) + tree_items = self.filter_items(tree_items, navigation_type) + tree_items = self.apply_hook(tree_items, f'{navigation_type}.children') + self.update_has_children(tree_alias, tree_items, navigation_type) + +~~ my_template = get_template(use_template) + + context.push() + context['sitetree_items'] = tree_items + rendered = my_template.render(context.flatten()) + context.pop() + + return rendered + + def get_children(self, tree_alias: str, item: Optional['TreeItemBase']) -> List['TreeItemBase']: + if not self._current_app_is_admin: + tree_alias = self.resolve_tree_i18n_alias(tree_alias) + + return self.cache.get_entry('parents', tree_alias)[item] + + def update_has_children(self, tree_alias: str, tree_items: List['TreeItemBase'], navigation_type: str): + get_children = self.get_children + filter_items = self.filter_items + apply_hook = self.apply_hook + + for tree_item in tree_items: + children = get_children(tree_alias, tree_item) + children = filter_items(children, navigation_type) + children = apply_hook(children, f'{navigation_type}.has_children') + tree_item.has_children = len(children) > 0 + + +## ... source file continues with no further get_template examples... + +``` + + +## Example 5 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / tables.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/./tables.py) + +```python +# tables.py +import copy +from collections import OrderedDict +from itertools import count + +from django.conf import settings +from django.core.paginator import Paginator +from django.db import models +~~from django.template.loader import get_template +from django.utils.encoding import force_str + +from . import columns +from .config import RequestConfig +from .data import TableData +from .rows import BoundRows +from .utils import Accessor, AttributeDict, OrderBy, OrderByTuple, Sequence + + +class DeclarativeColumnsMetaclass(type): + + def __new__(mcs, name, bases, attrs): + attrs["_meta"] = opts = TableOptions(attrs.get("Meta", None), name) + + cols, remainder = [], {} + for attr_name, attr in attrs.items(): + if isinstance(attr, columns.Column): + attr._explicit = True + cols.append((attr_name, attr)) + else: + remainder[attr_name] = attr + attrs = remainder + + cols.sort(key=lambda x: x[1].creation_counter) + + +## ... source file abbreviated to get to get_template examples ... + + + order_by = self._meta.order_by + if order_by is None: + self._order_by = None + order_by = self.data.ordering + if order_by is not None: + self.order_by = order_by + else: + self.order_by = order_by + self.template_name = template_name + if request: + RequestConfig(request).configure(self) + + self._counter = count() + + def get_top_pinned_data(self): + return None + + def get_bottom_pinned_data(self): + return None + + def before_render(self, request): + return + + def as_html(self, request): + self._counter = count() +~~ template = get_template(self.template_name) + + context = {"table": self, "request": request} + + self.before_render(request) + return template.render(context) + + def as_values(self, exclude_columns=None): + if exclude_columns is None: + exclude_columns = () + + columns = [ + column + for column in self.columns.iterall() + if not (column.column.exclude_from_export or column.name in exclude_columns) + ] + + yield [force_str(column.header, strings_only=True) for column in columns] + + for row in self.rows: + yield [ + force_str(row.get_cell_value(column.name), strings_only=True) for column in columns + ] + + def has_footer(self): + + +## ... source file continues with no further get_template examples... + +``` + diff --git a/content/pages/examples/django/django-template-loader-render-to-string.markdown b/content/pages/examples/django/django-template-loader-render-to-string.markdown new file mode 100644 index 000000000..ac9390c29 --- /dev/null +++ b/content/pages/examples/django/django-template-loader-render-to-string.markdown @@ -0,0 +1,1293 @@ +title: django.template.loader render_to_string Example Code +category: page +slug: django-template-loader-render-to-string-examples +sortorder: 500011393 +toc: False +sidebartitle: django.template.loader render_to_string +meta: Python example code that shows how to use the render_to_string callable from the django.template.loader module of the Django project. + + +`render_to_string` is a callable within the `django.template.loader` module of the Django project. + +get_template +and +select_template +are a couple of other callables within the `django.template.loader` package that also have code examples. + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / auth_app / views.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/auth_app/views.py) + +```python +# views.py +import json +from urllib.request import Request, urlopen +from urllib.parse import urlencode + +from django.conf import settings +from django.contrib.auth import views as auth_views +from django.contrib.auth import get_user_model, login +from django.shortcuts import redirect, render +~~from django.template.loader import render_to_string +from django.core.mail import send_mail + +from .forms import SignUpForm + +User = get_user_model() + + +def signup(request): + if request.method == 'POST': + form = SignUpForm(request.POST) + if form.is_valid(): + recaptcha_response = request.POST.get('g-recaptcha-response') + url = 'https://www.google.com/recaptcha/api/siteverify' + values = { + 'secret': settings.RECAPTCHA_SECRET_KEY, + 'response': recaptcha_response + } + data = urlencode(values).encode() + req = Request(url, data=data) + + response = urlopen(req) + result = json.loads(response.read().decode()) + if result['success']: + user = form.save() + user.is_active = True + user.save() + login(request, user) + + context = { + 'email': user.email, + 'protocol': 'https' if request.is_secure() else "http", + 'domain': request.get_host(), + } +~~ html = render_to_string('auth_app/email/welcome.html', context) +~~ text = render_to_string('auth_app/email/welcome.txt', context) + send_mail( + 'Welcome to DCCN Conference Registration System!', + message=text, + html_message=html, + recipient_list=[user.email], + from_email=settings.DEFAULT_FROM_EMAIL, + fail_silently=False, + ) + return redirect('register') + else: + form = SignUpForm() + return render(request, 'auth_app/signup.html', { + 'site_key': settings.RECAPTCHA_SITE_KEY, + 'form': form, + }) + + +class PasswordResetDoneView(auth_views.PasswordResetDoneView): + template_name = 'auth_app/password_reset_done.html' + + + +## ... source file continues with no further render_to_string examples... + +``` + + +## Example 2 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / adapter.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/adapter.py) + +```python +# adapter.py +from __future__ import unicode_literals + +import hashlib +import json +import time +import warnings + +from django import forms +from django.conf import settings +from django.contrib import messages +from django.contrib.auth import ( + authenticate, + get_backends, + login as django_login, + logout as django_logout, +) +from django.contrib.auth.models import AbstractUser +from django.contrib.auth.password_validation import validate_password +from django.contrib.sites.shortcuts import get_current_site +from django.core.cache import cache +from django.core.mail import EmailMessage, EmailMultiAlternatives +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import resolve_url +from django.template import TemplateDoesNotExist +~~from django.template.loader import render_to_string +from django.urls import reverse +from django.utils import timezone +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +from ..utils import ( + build_absolute_uri, + email_address_exists, + generate_unique_username, + get_user_model, + import_attribute, +) +from . import app_settings + + +class DefaultAccountAdapter(object): + + error_messages = { + "username_blacklisted": _( + "Username can not be used. Please use other username." + ), + "username_taken": AbstractUser._meta.get_field("username").error_messages[ + "unique" + ], + + +## ... source file abbreviated to get to render_to_string examples ... + + + def stash_user(self, request, user): + request.session["account_user"] = user + + def unstash_user(self, request): + return request.session.pop("account_user", None) + + def is_email_verified(self, request, email): + ret = False + verified_email = request.session.get("account_verified_email") + if verified_email: + ret = verified_email.lower() == email.lower() + return ret + + def format_email_subject(self, subject): + prefix = app_settings.EMAIL_SUBJECT_PREFIX + if prefix is None: + site = get_current_site(self.request) + prefix = "[{name}] ".format(name=site.name) + return prefix + force_str(subject) + + def get_from_email(self): + return settings.DEFAULT_FROM_EMAIL + + def render_mail(self, template_prefix, email, context): + to = [email] if isinstance(email, str) else email +~~ subject = render_to_string("{0}_subject.txt".format(template_prefix), context) + subject = " ".join(subject.splitlines()).strip() + subject = self.format_email_subject(subject) + + from_email = self.get_from_email() + + bodies = {} + for ext in ["html", "txt"]: + try: + template_name = "{0}_message.{1}".format(template_prefix, ext) +~~ bodies[ext] = render_to_string( + template_name, + context, + self.request, + ).strip() + except TemplateDoesNotExist: + if ext == "txt" and not bodies: + raise + if "txt" in bodies: + msg = EmailMultiAlternatives(subject, bodies["txt"], from_email, to) + if "html" in bodies: + msg.attach_alternative(bodies["html"], "text/html") + else: + msg = EmailMessage(subject, bodies["html"], from_email, to) + msg.content_subtype = "html" # Main content is now text/html + return msg + + def send_mail(self, template_prefix, email, context): + msg = self.render_mail(template_prefix, email, context) + msg.send() + + def get_signup_redirect_url(self, request): + return resolve_url(app_settings.SIGNUP_REDIRECT_URL) + + def get_login_redirect_url(self, request): + + +## ... source file abbreviated to get to render_to_string examples ... + + + min_length = app_settings.PASSWORD_MIN_LENGTH + if min_length and len(password) < min_length: + raise forms.ValidationError( + _("Password must be a minimum of {0} " "characters.").format(min_length) + ) + validate_password(password, user) + return password + + def validate_unique_email(self, email): + if email_address_exists(email): + raise forms.ValidationError(self.error_messages["email_taken"]) + return email + + def add_message( + self, + request, + level, + message_template, + message_context=None, + extra_tags="", + ): + if "django.contrib.messages" in settings.INSTALLED_APPS: + try: + if message_context is None: + message_context = {} +~~ message = render_to_string( + message_template, + message_context, + self.request, + ).strip() + if message: + messages.add_message(request, level, message, extra_tags=extra_tags) + except TemplateDoesNotExist: + pass + + def ajax_response(self, request, response, redirect_to=None, form=None, data=None): + resp = {} + status = response.status_code + + if redirect_to: + status = 200 + resp["location"] = redirect_to + if form: + if request.method == "POST": + if form.is_valid(): + status = 200 + else: + status = 400 + else: + status = 200 + + +## ... source file continues with no further render_to_string examples... + +``` + + +## Example 3 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / templatetags / cms_tags.py**](https://github.com/divio/django-cms/blob/develop/cms/templatetags/cms_tags.py) + +```python +# cms_tags.py +from collections import namedtuple, OrderedDict +from copy import copy +from datetime import datetime + +from django import template +from django.conf import settings +from django.contrib.sites.models import Site +from django.core.mail import mail_managers +from django.db.models import Model +from django.middleware.common import BrokenLinkEmailsMiddleware +~~from django.template.loader import render_to_string +from django.urls import reverse +from django.utils.encoding import force_text, smart_text +from django.utils.html import escape +from django.utils.http import urlencode +from django.utils.translation import ( + get_language, + override as force_language, + gettext_lazy as _, +) + +from classytags.arguments import (Argument, MultiValueArgument, + MultiKeywordArgument) +from classytags.core import Options, Tag +from classytags.helpers import InclusionTag, AsTag +from classytags.parser import Parser +from classytags.utils import flatten_context +from classytags.values import ListValue, StringValue + +from cms.cache.page import get_page_url_cache, set_page_url_cache +from cms.exceptions import PlaceholderNotFound +from cms.models import Page, Placeholder as PlaceholderModel, CMSPlugin, StaticPlaceholder +from cms.plugin_pool import plugin_pool +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils import get_current_site, get_language_from_request, get_site_id + + +## ... source file abbreviated to get to render_to_string examples ... + + + Argument('edit_fields', default=None, required=False), + Argument('language', default=None, required=False), + Argument('filters', default=None, required=False), + Argument('view_url', default=None, required=False), + Argument('view_method', default=None, required=False), + 'as', + Argument('varname', required=False, resolve=False), + ) + + def __init__(self, parser, tokens): + self.parser = parser + super().__init__(parser, tokens) + + def _is_editable(self, request): + return (request and hasattr(request, 'toolbar') and request.toolbar.edit_mode_active) + + def get_template(self, context, **kwargs): + if self._is_editable(context.get('request', None)): + return self.edit_template + return self.template + + def render_tag(self, context, **kwargs): + context.push() + template = self.get_template(context, **kwargs) + data = self.get_context(context, **kwargs) +~~ output = render_to_string(template, flatten_context(data)).strip() + context.pop() + if kwargs.get('varname'): + context[kwargs['varname']] = output + return '' + else: + return output + + def _get_editable_context(self, context, instance, language, edit_fields, + view_method, view_url, querystring, editmode=True): + request = context['request'] + if hasattr(request, 'toolbar'): + lang = request.toolbar.toolbar_language + else: + lang = get_language() + opts = instance._meta + if getattr(instance, '_deferred', False): + opts = opts.proxy_for_model._meta + with force_language(lang): + extra_context = {} + if edit_fields == 'changelist': + instance.get_plugin_name = u"%s %s list" % (smart_text(_('Edit')), smart_text(opts.verbose_name)) + extra_context['attribute_name'] = 'changelist' + elif editmode: + instance.get_plugin_name = u"%s %s" % (smart_text(_('Edit')), smart_text(opts.verbose_name)) + + +## ... source file abbreviated to get to render_to_string examples ... + + + extra_context = self._get_empty_context(context, instance, None, + language, view_url, + view_method, editmode=False) + extra_context['render_model_add'] = True + return extra_context + + +class CMSEditableObjectAddBlock(CMSEditableObject): + name = 'render_model_add_block' + options = Options( + Argument('instance'), + Argument('language', default=None, required=False), + Argument('view_url', default=None, required=False), + Argument('view_method', default=None, required=False), + 'as', + Argument('varname', required=False, resolve=False), + blocks=[('endrender_model_add_block', 'nodelist')], + ) + + def render_tag(self, context, **kwargs): + context.push() + template = self.get_template(context, **kwargs) + data = self.get_context(context, **kwargs) + data['content'] = kwargs['nodelist'].render(data) + data['rendered_content'] = data['content'] +~~ output = render_to_string(template, flatten_context(data)) + context.pop() + if kwargs.get('varname'): + context[kwargs['varname']] = output + return '' + else: + return output + + def get_context(self, context, **kwargs): + instance = kwargs.pop('instance') + if isinstance(instance, Model) and not instance.pk: + instance.pk = 0 + kwargs.pop('varname') + kwargs.pop('nodelist') + extra_context = self._get_empty_context(context, instance, None, + editmode=False, **kwargs) + extra_context['render_model_add'] = True + return extra_context + + +class CMSEditableObjectBlock(CMSEditableObject): + name = 'render_model_block' + options = Options( + Argument('instance'), + Argument('edit_fields', default=None, required=False), + Argument('language', default=None, required=False), + Argument('view_url', default=None, required=False), + Argument('view_method', default=None, required=False), + 'as', + Argument('varname', required=False, resolve=False), + blocks=[('endrender_model_block', 'nodelist')], + ) + + def render_tag(self, context, **kwargs): + context.push() + template = self.get_template(context, **kwargs) + data = self.get_context(context, **kwargs) + data['content'] = kwargs['nodelist'].render(data) + data['rendered_content'] = data['content'] +~~ output = render_to_string(template, flatten_context(data)) + context.pop() + if kwargs.get('varname'): + context[kwargs['varname']] = output + return '' + else: + return output + + def get_context(self, context, **kwargs): + kwargs.pop('varname') + kwargs.pop('nodelist') + extra_context = self._get_empty_context(context, **kwargs) + extra_context['instance'] = kwargs.get('instance') + extra_context['render_model_block'] = True + return extra_context + + +class StaticPlaceholderNode(Tag): + name = 'static_placeholder' + options = PlaceholderOptions( + Argument('code', required=True), + MultiValueArgument('extra_bits', required=False, resolve=False), + blocks=[ + ('endstatic_placeholder', 'nodelist'), + ] + + +## ... source file continues with no further render_to_string examples... + +``` + + +## Example 4 from django-debug-toolbar +[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar) +([project documentation](https://github.com/jazzband/django-debug-toolbar) +and [PyPI page](https://pypi.org/project/django-debug-toolbar/)) +grants a developer detailed request-response cycle information while +developing a [Django](/django.html) web application. +The code for django-debug-toolbar is +[open source](https://github.com/jazzband/django-debug-toolbar/blob/master/LICENSE) +and maintained by the developer community group known as +[Jazzband](https://jazzband.co/). + +[**django-debug-toolbar / debug_toolbar / toolbar.py**](https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/./toolbar.py) + +```python +# toolbar.py + +import uuid +from collections import OrderedDict + +from django.apps import apps +from django.core.exceptions import ImproperlyConfigured +from django.template import TemplateSyntaxError +~~from django.template.loader import render_to_string +from django.urls import path +from django.utils.module_loading import import_string + +from debug_toolbar import settings as dt_settings + + +class DebugToolbar: + def __init__(self, request, get_response): + self.request = request + self.config = dt_settings.get_config().copy() + panels = [] + for panel_class in reversed(self.get_panel_classes()): + panel = panel_class(self, get_response) + panels.append(panel) + if panel.enabled: + get_response = panel.process_request + self.process_request = get_response + self._panels = OrderedDict() + while panels: + panel = panels.pop() + self._panels[panel.panel_id] = panel + self.stats = {} + self.server_timing_stats = {} + self.store_id = None + + + @property + def panels(self): + return list(self._panels.values()) + + @property + def enabled_panels(self): + return [panel for panel in self._panels.values() if panel.enabled] + + def get_panel_by_id(self, panel_id): + return self._panels[panel_id] + + + def render_toolbar(self): + if not self.should_render_panels(): + self.store() + try: + context = {"toolbar": self} +~~ return render_to_string("debug_toolbar/base.html", context) + except TemplateSyntaxError: + if not apps.is_installed("django.contrib.staticfiles"): + raise ImproperlyConfigured( + "The debug toolbar requires the staticfiles contrib app. " + "Add 'django.contrib.staticfiles' to INSTALLED_APPS and " + "define STATIC_URL in your settings." + ) + else: + raise + + def should_render_panels(self): + render_panels = self.config["RENDER_PANELS"] + if render_panels is None: + render_panels = self.request.META["wsgi.multiprocess"] + return render_panels + + + _store = OrderedDict() + + def store(self): + if self.store_id: + return + self.store_id = uuid.uuid4().hex + self._store[self.store_id] = self + + +## ... source file continues with no further render_to_string examples... + +``` + + +## Example 5 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / fields / folder.py**](https://github.com/divio/django-filer/blob/develop/filer/fields/folder.py) + +```python +# folder.py +from __future__ import absolute_import + +import warnings + +from django import forms +from django.contrib.admin.sites import site +from django.contrib.admin.widgets import ForeignKeyRawIdWidget +from django.core.exceptions import ObjectDoesNotExist +from django.db import models +~~from django.template.loader import render_to_string +from django.urls import reverse +from django.utils.http import urlencode +from django.utils.safestring import mark_safe + +from ..models import Folder +from ..utils.compatibility import truncate_words +from ..utils.model_label import get_model_label + + +class AdminFolderWidget(ForeignKeyRawIdWidget): + choices = None + input_type = 'hidden' + is_hidden = False + + def render(self, name, value, attrs=None, renderer=None): + obj = self.obj_for_value(value) + css_id = attrs.get('id') + css_id_folder = "%s_folder" % css_id + css_id_description_txt = "%s_description_txt" % css_id + if attrs is None: + attrs = {} + related_url = None + + if value: + + +## ... source file abbreviated to get to render_to_string examples ... + + + if not related_url: + related_url = reverse('admin:filer-directory_listing-last') + params = self.url_parameters() + params['_pick'] = 'folder' + if params: + url = '?' + urlencode(sorted(params.items())) + else: + url = '' + if 'class' not in attrs: + attrs['class'] = 'vForeignKeyRawIdAdminField' + super_attrs = attrs.copy() + hidden_input = super(ForeignKeyRawIdWidget, self).render(name, value, super_attrs) + + context = { + 'hidden_input': hidden_input, + 'lookup_url': '%s%s' % (related_url, url), + 'lookup_name': name, + 'span_id': css_id_description_txt, + 'object': obj, + 'clear_id': '%s_clear' % css_id, + 'descid': css_id_description_txt, + 'noimg': 'filer/icons/nofile_32x32.png', + 'foldid': css_id_folder, + 'id': css_id, + } +~~ html = render_to_string('admin/filer/widgets/admin_folder.html', context) + return mark_safe(html) + + def label_for_value(self, value): + obj = self.obj_for_value(value) + return ' %s' % truncate_words(obj, 14) + + def obj_for_value(self, value): + if not value: + return None + try: + key = self.rel.get_related_field().name + obj = self.rel.model._default_manager.get(**{key: value}) + except ObjectDoesNotExist: + obj = None + return obj + + class Media(object): + js = ( + 'filer/js/addons/popup_handling.js', + ) + + +class AdminFolderFormField(forms.ModelChoiceField): + widget = AdminFolderWidget + + +## ... source file continues with no further render_to_string examples... + +``` + + +## Example 6 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / panels.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./panels.py) + +```python +# panels.py +import datetime + +from debug_toolbar.panels import DebugPanel +~~from django.template.loader import render_to_string +from django.utils.translation import ugettext_lazy as _ + +from haystack import connections + + +class HaystackDebugPanel(DebugPanel): + + name = "Haystack" + has_content = True + + def __init__(self, *args, **kwargs): + super(self.__class__, self).__init__(*args, **kwargs) + self._offset = dict( + (alias, len(connections[alias].queries)) + for alias in connections.connections_info.keys() + ) + self._search_time = 0 + self._queries = [] + self._backends = {} + + def nav_title(self): + return _("Haystack") + + def nav_subtitle(self): + + +## ... source file abbreviated to get to render_to_string examples ... + + + if query.get("additional_kwargs"): + if query["additional_kwargs"].get("result_class"): + query["additional_kwargs"]["result_class"] = str( + query["additional_kwargs"]["result_class"] + ) + + try: + query["width_ratio"] = (float(query["time"]) / self._search_time) * 100 + except ZeroDivisionError: + query["width_ratio"] = 0 + + query["start_offset"] = width_ratio_tally + width_ratio_tally += query["width_ratio"] + + context = self.context.copy() + context.update( + { + "backends": sorted( + self._backends.items(), key=lambda x: -x[1]["time_spent"] + ), + "queries": [q for a, q in self._queries], + "sql_time": self._search_time, + } + ) + +~~ return render_to_string("panels/haystack.html", context) + + + +## ... source file continues with no further render_to_string examples... + +``` + + +## Example 7 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / dashboard / dashboard.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/dashboard/dashboard.py) + +```python +# dashboard.py +from importlib import import_module +try: + from django.core.urlresolvers import reverse +except ImportError: # Django 1.11 + from django.urls import reverse + +~~from django.template.loader import render_to_string +from jet.dashboard import modules +from jet.dashboard.models import UserDashboardModule +from django.utils.translation import ugettext_lazy as _ +from jet.ordered_set import OrderedSet +from jet.utils import get_admin_site_name, context_to_dict + +try: + from django.template.context_processors import csrf +except ImportError: + from django.core.context_processors import csrf + + +class Dashboard(object): + + columns = 2 + + children = None + + available_children = None + app_label = None + context = None + modules = None + + class Media: + + +## ... source file abbreviated to get to render_to_string examples ... + + + user=self.context['request'].user.pk + ).all() + + if len(module_models) == 0: + module_models = self.create_initial_module_models(self.context['request'].user) + + loaded_modules = [] + + for module_model in module_models: + module_cls = module_model.load_module() + if module_cls is not None: + module = module_cls(model=module_model, context=self.context) + loaded_modules.append(module) + + self.modules = loaded_modules + + def render(self): + context = context_to_dict(self.context) + context.update({ + 'columns': range(self.columns), + 'modules': self.modules, + 'app_label': self.app_label, + }) + context.update(csrf(context['request'])) + +~~ return render_to_string('jet.dashboard/dashboard.html', context) + + def render_tools(self): + context = context_to_dict(self.context) + context.update({ + 'children': self.children, + 'app_label': self.app_label, + 'available_children': self.available_children + }) + context.update(csrf(context['request'])) + +~~ return render_to_string('jet.dashboard/dashboard_tools.html', context) + + def media(self): + unique_css = OrderedSet() + unique_js = OrderedSet() + + for js in getattr(self.Media, 'js', ()): + unique_js.add(js) + for css in getattr(self.Media, 'css', ()): + unique_css.add(css) + + for module in self.modules: + for js in getattr(module.Media, 'js', ()): + unique_js.add(js) + for css in getattr(module.Media, 'css', ()): + unique_css.add(css) + + class Media: + css = list(unique_css) + js = list(unique_js) + + return Media + + +class AppIndexDashboard(Dashboard): + + +## ... source file continues with no further render_to_string examples... + +``` + + +## Example 8 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / templatetags / pipeline.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/templatetags/pipeline.py) + +```python +# pipeline.py +import logging +import subprocess + +from django.contrib.staticfiles.storage import staticfiles_storage + +from django import template +from django.template.base import VariableDoesNotExist +~~from django.template.loader import render_to_string +from django.utils.safestring import mark_safe + +from ..collector import default_collector +from ..conf import settings +from ..exceptions import CompilerError +from ..packager import Packager, PackageNotFound +from ..utils import guess_type + +logger = logging.getLogger(__name__) + +register = template.Library() + + +class PipelineMixin(object): + request = None + _request_var = None + + @property + def request_var(self): + if not self._request_var: + self._request_var = template.Variable('request') + return self._request_var + + def package_for(self, package_name, package_type): + + +## ... source file abbreviated to get to render_to_string examples ... + + + method = getattr(self, f'render_{package_type}') + + return method(package, package.output_filename) + + def render_compressed_sources(self, package, package_name, package_type): + if settings.PIPELINE_COLLECTOR_ENABLED: + default_collector.collect(self.request) + + packager = Packager() + method = getattr(self, f'render_individual_{package_type}') + + try: + paths = packager.compile(package.paths) + except CompilerError as e: + if settings.SHOW_ERRORS_INLINE: + method = getattr(self, f'render_error_{package_type}') + return method(package_name, e) + else: + raise + + templates = packager.pack_templates(package) + + return method(package, paths, templates=templates) + + def render_error(self, package_type, package_name, e): +~~ return render_to_string('pipeline/compile_error.html', { + 'package_type': package_type, + 'package_name': package_name, + 'command': subprocess.list2cmdline(e.command), + 'errors': e.error_output, + }) + + +class StylesheetNode(PipelineMixin, template.Node): + def __init__(self, name): + self.name = name + + def render(self, context): + super(StylesheetNode, self).render(context) + package_name = template.Variable(self.name).resolve(context) + + try: + package = self.package_for(package_name, 'css') + except PackageNotFound: + logger.warn("Package %r is unknown. Check PIPELINE['STYLESHEETS'] in your settings.", package_name) + return '' # fail silently, do not return anything if an invalid group is specified + return self.render_compressed(package, package_name, 'css') + + def render_css(self, package, path): + template_name = package.template_name or "pipeline/css.html" + context = package.extra_context + context.update({ + 'type': guess_type(path, 'text/css'), + 'url': mark_safe(staticfiles_storage.url(path)) + }) +~~ return render_to_string(template_name, context) + + def render_individual_css(self, package, paths, **kwargs): + tags = [self.render_css(package, path) for path in paths] + return '\n'.join(tags) + + def render_error_css(self, package_name, e): + return super(StylesheetNode, self).render_error( + 'CSS', package_name, e) + + +class JavascriptNode(PipelineMixin, template.Node): + def __init__(self, name): + self.name = name + + def render(self, context): + super(JavascriptNode, self).render(context) + package_name = template.Variable(self.name).resolve(context) + + try: + package = self.package_for(package_name, 'js') + except PackageNotFound: + logger.warn("Package %r is unknown. Check PIPELINE['JAVASCRIPT'] in your settings.", package_name) + return '' # fail silently, do not return anything if an invalid group is specified + return self.render_compressed(package, package_name, 'js') + + def render_js(self, package, path): + template_name = package.template_name or "pipeline/js.html" + context = package.extra_context + context.update({ + 'type': guess_type(path, 'text/javascript'), + 'url': mark_safe(staticfiles_storage.url(path)) + }) +~~ return render_to_string(template_name, context) + + def render_inline(self, package, js): + context = package.extra_context + context.update({ + 'source': js + }) +~~ return render_to_string("pipeline/inline_js.html", context) + + def render_individual_js(self, package, paths, templates=None): + tags = [self.render_js(package, js) for js in paths] + if templates: + tags.append(self.render_inline(package, templates)) + return '\n'.join(tags) + + def render_error_js(self, package_name, e): + return super(JavascriptNode, self).render_error( + 'JavaScript', package_name, e) + + +@register.tag +def stylesheet(parser, token): + try: + tag_name, name = token.split_contents() + except ValueError: + raise template.TemplateSyntaxError('%r requires exactly one argument: the name of a group in the PIPELINE.STYLESHEETS setting' % token.split_contents()[0]) + return StylesheetNode(name) + + +@register.tag +def javascript(parser, token): + try: + + +## ... source file continues with no further render_to_string examples... + +``` + + +## Example 9 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / decorators.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./decorators.py) + +```python +# decorators.py +from functools import wraps +from urllib.parse import quote as urlquote + +from django.http import HttpResponseForbidden +from django.http import HttpResponseNotFound +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +~~from django.template.loader import render_to_string +from django.urls import reverse +from wiki.conf import settings +from wiki.core.exceptions import NoRootURL + + +def response_forbidden(request, article, urlpath, read_denied=False): + if request.user.is_anonymous: + qs = request.META.get("QUERY_STRING", "") + if qs: + qs = urlquote("?" + qs) + else: + qs = "" + return redirect(settings.LOGIN_URL + "?next=" + request.path + qs) + else: + return HttpResponseForbidden( +~~ render_to_string( + "wiki/permission_denied.html", + context={ + "article": article, + "urlpath": urlpath, + "read_denied": read_denied, + }, + request=request, + ) + ) + + +def get_article( # noqa: max-complexity=23 + func=None, + can_read=True, + can_write=False, + deleted_contents=False, + not_locked=False, + can_delete=False, + can_moderate=False, + can_create=False, +): + + def wrapper(request, *args, **kwargs): + from . import models + + path = kwargs.pop("path", None) + article_id = kwargs.pop("article_id", None) + + if path is not None: + try: + urlpath = models.URLPath.get_by_path(path, select_related=True) + except NoRootURL: + return redirect("wiki:root_create") + except models.URLPath.DoesNotExist: + try: + pathlist = list( + filter( + lambda x: x != "", + path.split("/"), + ) + ) + path = "/".join(pathlist[:-1]) + parent = models.URLPath.get_by_path(path) + return HttpResponseRedirect( + reverse("wiki:create", kwargs={"path": parent.path}) + + "?slug=%s" % pathlist[-1].lower() + ) + except models.URLPath.DoesNotExist: + return HttpResponseNotFound( +~~ render_to_string( + "wiki/error.html", + context={"error_type": "ancestors_missing"}, + request=request, + ) + ) + if urlpath.article: + article = urlpath.article + else: + return_url = reverse("wiki:get", kwargs={"path": urlpath.parent.path}) + urlpath.delete() + return HttpResponseRedirect(return_url) + + elif article_id: + articles = models.Article.objects + + article = get_object_or_404(articles, id=article_id) + try: + urlpath = models.URLPath.objects.get(articles__article=article) + except ( + models.URLPath.DoesNotExist, + models.URLPath.MultipleObjectsReturned, + ): + urlpath = None + + + +## ... source file continues with no further render_to_string examples... + +``` + + +## Example 10 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / snippets / widgets.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/snippets/widgets.py) + +```python +# widgets.py +import json + +from django import forms +from django.contrib.admin.utils import quote +~~from django.template.loader import render_to_string +from django.urls import reverse +from django.utils.translation import gettext_lazy as _ + +from wagtail.admin.staticfiles import versioned_static +from wagtail.admin.widgets import AdminChooser +from wagtail.admin.widgets.button import ListingButton + + +class AdminSnippetChooser(AdminChooser): + + def __init__(self, model, **kwargs): + self.target_model = model + name = self.target_model._meta.verbose_name + self.choose_one_text = _('Choose %s') % name + self.choose_another_text = _('Choose another %s') % name + self.link_to_chosen_text = _('Edit this %s') % name + + super().__init__(**kwargs) + + def get_value_data(self, value): + if value is None: + return None + elif isinstance(value, self.target_model): + instance = value + else: # assume instance ID + instance = self.target_model.objects.get(pk=value) + + app_label = self.target_model._meta.app_label + model_name = self.target_model._meta.model_name + quoted_id = quote(instance.pk) + edit_url = reverse('wagtailsnippets:edit', args=[app_label, model_name, quoted_id]) + + return { + 'id': instance.pk, + 'string': str(instance), + 'edit_url': edit_url, + } + + def render_html(self, name, value_data, attrs): + value_data = value_data or {} + + original_field_html = super().render_html(name, value_data.get('id'), attrs) + +~~ return render_to_string("wagtailsnippets/widgets/snippet_chooser.html", { + 'widget': self, + 'original_field_html': original_field_html, + 'attrs': attrs, + 'value': bool(value_data), # only used by chooser.html to identify blank values + 'display_title': value_data.get('string', ''), + 'edit_url': value_data.get('edit_url', ''), + }) + + def render_js_init(self, id_, name, value_data): + model = self.target_model + + return "createSnippetChooser({id}, {model});".format( + id=json.dumps(id_), + model=json.dumps('{app}/{model}'.format( + app=model._meta.app_label, + model=model._meta.model_name))) + + @property + def media(self): + return forms.Media(js=[ + versioned_static('wagtailsnippets/js/snippet-chooser-modal.js'), + versioned_static('wagtailsnippets/js/snippet-chooser.js'), + ]) + + + +## ... source file continues with no further render_to_string examples... + +``` + diff --git a/content/pages/examples/django/django-template-loader-select-template.markdown b/content/pages/examples/django/django-template-loader-select-template.markdown new file mode 100644 index 000000000..1b4a15d0e --- /dev/null +++ b/content/pages/examples/django/django-template-loader-select-template.markdown @@ -0,0 +1,124 @@ +title: django.template.loader select_template Example Code +category: page +slug: django-template-loader-select-template-examples +sortorder: 500011394 +toc: False +sidebartitle: django.template.loader select_template +meta: Python example code that shows how to use the select_template callable from the django.template.loader module of the Django project. + + +`select_template` is a callable within the `django.template.loader` module of the Django project. + +get_template +and +render_to_string +are a couple of other callables within the `django.template.loader` package that also have code examples. + +## Example 1 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / templatetags / django_tables2.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/templatetags/django_tables2.py) + +```python +# django_tables2.py +import re +from collections import OrderedDict + +from django import template +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.template import Node, TemplateSyntaxError +~~from django.template.loader import get_template, select_template +from django.templatetags.l10n import register as l10n_register +from django.utils.html import escape +from django.utils.http import urlencode + +import django_tables2 as tables +from django_tables2.paginators import LazyPaginator +from django_tables2.utils import AttributeDict + +register = template.Library() +kwarg_re = re.compile(r"(?:(.+)=)?(.+)") +context_processor_error_msg = ( + "Tag {%% %s %%} requires django.template.context_processors.request to be " + "in the template configuration in " + "settings.TEMPLATES[]OPTIONS.context_processors) in order for the included " + "template tags to function correctly." +) + + +def token_kwargs(bits, parser): + if not bits: + return {} + kwargs = OrderedDict() + while bits: + match = kwarg_re.match(bits[0]) + + +## ... source file abbreviated to get to select_template examples ... + + + self.template_name = template_name + + def render(self, context): + table = self.table.resolve(context) + + request = context.get("request") + + if isinstance(table, tables.Table): + pass + elif hasattr(table, "model"): + queryset = table + + table = tables.table_factory(model=queryset.model)(queryset, request=request) + else: + klass = type(table).__name__ + raise ValueError("Expected table or queryset, not {}".format(klass)) + + if self.template_name: + template_name = self.template_name.resolve(context) + else: + template_name = table.template_name + + if isinstance(template_name, str): + template = get_template(template_name) + else: +~~ template = select_template(template_name) + + try: + table.context = context + table.before_render(request) + + return template.render(context={"table": table}, request=request) + finally: + del table.context + + +@register.tag +def render_table(parser, token): + bits = token.split_contents() + bits.pop(0) + + table = parser.compile_filter(bits.pop(0)) + template = parser.compile_filter(bits.pop(0)) if bits else None + + return RenderTableNode(table, template) + + +register.filter("localize", l10n_register.filters["localize"]) +register.filter("unlocalize", l10n_register.filters["unlocalize"]) + + + +## ... source file continues with no further select_template examples... + +``` + diff --git a/content/pages/examples/django/django-template-loader-tags-blocknode.markdown b/content/pages/examples/django/django-template-loader-tags-blocknode.markdown new file mode 100644 index 000000000..908fd9095 --- /dev/null +++ b/content/pages/examples/django/django-template-loader-tags-blocknode.markdown @@ -0,0 +1,192 @@ +title: django.template.loader_tags BlockNode Example Code +category: page +slug: django-template-loader-tags-blocknode-examples +sortorder: 500011395 +toc: False +sidebartitle: django.template.loader_tags BlockNode +meta: Example code for understanding how to use the BlockNode class from the django.template.loader_tags module of the Django project. + + +`BlockNode` is a class within the `django.template.loader_tags` module of the Django project. + +ExtendsNode +and +IncludeNode +are a couple of other callables within the `django.template.loader_tags` package that also have code examples. + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / utils / placeholder.py**](https://github.com/divio/django-cms/blob/develop/cms/utils/placeholder.py) + +```python +# placeholder.py +import operator +import warnings +from collections import OrderedDict + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db.models.query_utils import Q +from django.template import TemplateSyntaxError, NodeList, Variable, Context, Template, engines +from django.template.base import VariableNode +from django.template.loader import get_template +~~from django.template.loader_tags import BlockNode, ExtendsNode, IncludeNode + +from sekizai.helpers import get_varname + +from cms.exceptions import DuplicatePlaceholderWarning +from cms.utils.conf import get_cms_setting + + +def _get_nodelist(tpl): + if hasattr(tpl, 'template'): + return tpl.template.nodelist + else: + return tpl.nodelist + + +def get_context(): + if engines is not None: + context = Context() + context.template = Template('') + return context + else: + return {} + + +def get_placeholder_conf(setting, placeholder, template=None, default=None): + + +## ... source file abbreviated to get to BlockNode examples ... + + + validate_placeholder_name(slot) + placeholders.append(placeholder) + clean_placeholders.append(slot) + return placeholders + + +def get_static_placeholders(template, context): + compiled_template = get_template(template) + nodes = _scan_static_placeholders(_get_nodelist(compiled_template)) + placeholders = [node.get_declaration(context) for node in nodes] + placeholders_with_code = [] + + for placeholder in placeholders: + if placeholder.slot: + placeholders_with_code.append(placeholder) + else: + warnings.warn('Unable to resolve static placeholder ' + 'name in template "{}"'.format(template), + Warning) + return placeholders_with_code + + +def _get_block_nodes(extend_node): + parent = extend_node.get_parent(get_context()) + parent_nodelist = _get_nodelist(parent) +~~ parent_nodes = parent_nodelist.get_nodes_by_type(BlockNode) + parent_extend_nodes = parent_nodelist.get_nodes_by_type(ExtendsNode) + + if parent_extend_nodes: + nodes = _get_block_nodes(parent_extend_nodes[0]) + else: + nodes = OrderedDict() + + for node in parent_nodes: + nodes[node.name] = node + +~~ current_nodes = _get_nodelist(extend_node).get_nodes_by_type(BlockNode) + + for node in current_nodes: + if node.name in nodes: + node.super = nodes[node.name] + nodes[node.name] = node + return nodes + + +def _get_placeholder_nodes_from_extend(extend_node, node_class): + block_nodes = _get_block_nodes(extend_node) + block_names = list(block_nodes.keys()) + + placeholders = [] + + for block in block_nodes.values(): + placeholders.extend(_scan_placeholders(_get_nodelist(block), node_class, block, block_names)) + + parent_template = _find_topmost_template(extend_node) + placeholders += _scan_placeholders(_get_nodelist(parent_template), node_class, None, block_names) + return placeholders + + +def _find_topmost_template(extend_node): + parent_template = extend_node.get_parent(get_context()) + nodes.append(node) + elif isinstance(node, IncludeNode): + if node.template: + if not callable(getattr(node.template, 'render', None)): + if isinstance(node.template.var, Variable): + continue + else: + template = get_template(node.template.var) + else: + template = node.template + nodes += _scan_placeholders(_get_nodelist(template), node_class, current_block) + elif isinstance(node, ExtendsNode): + nodes += _get_placeholder_nodes_from_extend(node, node_class) + elif isinstance(node, VariableNode) and current_block: + if node.filter_expression.token == 'block.super': + if not hasattr(current_block.super, 'nodelist'): + raise TemplateSyntaxError("Cannot render block.super for blocks without a parent.") + nodes += _scan_placeholders(_get_nodelist(current_block.super), node_class, current_block.super) + elif isinstance(node, BlockNode) and node.name in ignore_blocks: + continue + elif hasattr(node, 'child_nodelists'): + for nodelist_name in node.child_nodelists: + if hasattr(node, nodelist_name): + subnodelist = getattr(node, nodelist_name) + if isinstance(subnodelist, NodeList): +~~ if isinstance(node, BlockNode): + current_block = node + nodes += _scan_placeholders(subnodelist, node_class, current_block, ignore_blocks) + else: + for attr in dir(node): + obj = getattr(node, attr) + if isinstance(obj, NodeList): +~~ if isinstance(node, BlockNode): + current_block = node + nodes += _scan_placeholders(obj, node_class, current_block, ignore_blocks) + return nodes + + +def _scan_static_placeholders(nodelist): + from cms.templatetags.cms_tags import StaticPlaceholderNode + + return _scan_placeholders(nodelist, node_class=StaticPlaceholderNode) + + +def get_placeholders(template): + compiled_template = get_template(template) + + placeholders = [] + nodes = _scan_placeholders(_get_nodelist(compiled_template)) + clean_placeholders = [] + + for node in nodes: + placeholder = node.get_declaration() + slot = placeholder.slot + + if slot in clean_placeholders: + warnings.warn("Duplicate {{% placeholder \"{0}\" %}} " + + +## ... source file continues with no further BlockNode examples... + +``` + diff --git a/content/pages/examples/django/django-template-loader-tags-extendsnode.markdown b/content/pages/examples/django/django-template-loader-tags-extendsnode.markdown new file mode 100644 index 000000000..61b2dd957 --- /dev/null +++ b/content/pages/examples/django/django-template-loader-tags-extendsnode.markdown @@ -0,0 +1,188 @@ +title: django.template.loader_tags ExtendsNode Example Code +category: page +slug: django-template-loader-tags-extendsnode-examples +sortorder: 500011396 +toc: False +sidebartitle: django.template.loader_tags ExtendsNode +meta: Example code for understanding how to use the ExtendsNode class from the django.template.loader_tags module of the Django project. + + +`ExtendsNode` is a class within the `django.template.loader_tags` module of the Django project. + +BlockNode +and +IncludeNode +are a couple of other callables within the `django.template.loader_tags` package that also have code examples. + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / utils / placeholder.py**](https://github.com/divio/django-cms/blob/develop/cms/utils/placeholder.py) + +```python +# placeholder.py +import operator +import warnings +from collections import OrderedDict + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db.models.query_utils import Q +from django.template import TemplateSyntaxError, NodeList, Variable, Context, Template, engines +from django.template.base import VariableNode +from django.template.loader import get_template +~~from django.template.loader_tags import BlockNode, ExtendsNode, IncludeNode + +from sekizai.helpers import get_varname + +from cms.exceptions import DuplicatePlaceholderWarning +from cms.utils.conf import get_cms_setting + + +def _get_nodelist(tpl): + if hasattr(tpl, 'template'): + return tpl.template.nodelist + else: + return tpl.nodelist + + +def get_context(): + if engines is not None: + context = Context() + context.template = Template('') + return context + else: + return {} + + +def get_placeholder_conf(setting, placeholder, template=None, default=None): + + +## ... source file abbreviated to get to ExtendsNode examples ... + + + placeholders.append(placeholder) + clean_placeholders.append(slot) + return placeholders + + +def get_static_placeholders(template, context): + compiled_template = get_template(template) + nodes = _scan_static_placeholders(_get_nodelist(compiled_template)) + placeholders = [node.get_declaration(context) for node in nodes] + placeholders_with_code = [] + + for placeholder in placeholders: + if placeholder.slot: + placeholders_with_code.append(placeholder) + else: + warnings.warn('Unable to resolve static placeholder ' + 'name in template "{}"'.format(template), + Warning) + return placeholders_with_code + + +def _get_block_nodes(extend_node): + parent = extend_node.get_parent(get_context()) + parent_nodelist = _get_nodelist(parent) + parent_nodes = parent_nodelist.get_nodes_by_type(BlockNode) +~~ parent_extend_nodes = parent_nodelist.get_nodes_by_type(ExtendsNode) + + if parent_extend_nodes: + nodes = _get_block_nodes(parent_extend_nodes[0]) + else: + nodes = OrderedDict() + + for node in parent_nodes: + nodes[node.name] = node + + current_nodes = _get_nodelist(extend_node).get_nodes_by_type(BlockNode) + + for node in current_nodes: + if node.name in nodes: + node.super = nodes[node.name] + nodes[node.name] = node + return nodes + + +def _get_placeholder_nodes_from_extend(extend_node, node_class): + block_nodes = _get_block_nodes(extend_node) + block_names = list(block_nodes.keys()) + + placeholders = [] + + for block in block_nodes.values(): + placeholders.extend(_scan_placeholders(_get_nodelist(block), node_class, block, block_names)) + + parent_template = _find_topmost_template(extend_node) + placeholders += _scan_placeholders(_get_nodelist(parent_template), node_class, None, block_names) + return placeholders + + +def _find_topmost_template(extend_node): + parent_template = extend_node.get_parent(get_context()) +~~ for node in _get_nodelist(parent_template).get_nodes_by_type(ExtendsNode): + return _find_topmost_template(node) + return extend_node.get_parent(get_context()) + + +def _scan_placeholders(nodelist, node_class=None, current_block=None, ignore_blocks=None): + from cms.templatetags.cms_tags import Placeholder + + if not node_class: + node_class = Placeholder + + nodes = [] + + if ignore_blocks is None: + ignore_blocks = [] + + for node in nodelist: + if isinstance(node, node_class): + nodes.append(node) + elif isinstance(node, IncludeNode): + if node.template: + if not callable(getattr(node.template, 'render', None)): + if isinstance(node.template.var, Variable): + continue + else: + template = get_template(node.template.var) + else: + template = node.template + nodes += _scan_placeholders(_get_nodelist(template), node_class, current_block) +~~ elif isinstance(node, ExtendsNode): + nodes += _get_placeholder_nodes_from_extend(node, node_class) + elif isinstance(node, VariableNode) and current_block: + if node.filter_expression.token == 'block.super': + if not hasattr(current_block.super, 'nodelist'): + raise TemplateSyntaxError("Cannot render block.super for blocks without a parent.") + nodes += _scan_placeholders(_get_nodelist(current_block.super), node_class, current_block.super) + elif isinstance(node, BlockNode) and node.name in ignore_blocks: + continue + elif hasattr(node, 'child_nodelists'): + for nodelist_name in node.child_nodelists: + if hasattr(node, nodelist_name): + subnodelist = getattr(node, nodelist_name) + if isinstance(subnodelist, NodeList): + if isinstance(node, BlockNode): + current_block = node + nodes += _scan_placeholders(subnodelist, node_class, current_block, ignore_blocks) + else: + for attr in dir(node): + obj = getattr(node, attr) + if isinstance(obj, NodeList): + if isinstance(node, BlockNode): + current_block = node + nodes += _scan_placeholders(obj, node_class, current_block, ignore_blocks) + return nodes + + +## ... source file continues with no further ExtendsNode examples... + +``` + diff --git a/content/pages/examples/django/django-template-loader-tags-includenode.markdown b/content/pages/examples/django/django-template-loader-tags-includenode.markdown new file mode 100644 index 000000000..412c41d09 --- /dev/null +++ b/content/pages/examples/django/django-template-loader-tags-includenode.markdown @@ -0,0 +1,124 @@ +title: django.template.loader_tags IncludeNode Example Code +category: page +slug: django-template-loader-tags-includenode-examples +sortorder: 500011397 +toc: False +sidebartitle: django.template.loader_tags IncludeNode +meta: Example code for understanding how to use the IncludeNode class from the django.template.loader_tags module of the Django project. + + +`IncludeNode` is a class within the `django.template.loader_tags` module of the Django project. + +BlockNode +and +ExtendsNode +are a couple of other callables within the `django.template.loader_tags` package that also have code examples. + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / utils / placeholder.py**](https://github.com/divio/django-cms/blob/develop/cms/utils/placeholder.py) + +```python +# placeholder.py +import operator +import warnings +from collections import OrderedDict + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db.models.query_utils import Q +from django.template import TemplateSyntaxError, NodeList, Variable, Context, Template, engines +from django.template.base import VariableNode +from django.template.loader import get_template +~~from django.template.loader_tags import BlockNode, ExtendsNode, IncludeNode + +from sekizai.helpers import get_varname + +from cms.exceptions import DuplicatePlaceholderWarning +from cms.utils.conf import get_cms_setting + + +def _get_nodelist(tpl): + if hasattr(tpl, 'template'): + return tpl.template.nodelist + else: + return tpl.nodelist + + +def get_context(): + if engines is not None: + context = Context() + context.template = Template('') + return context + else: + return {} + + +def get_placeholder_conf(setting, placeholder, template=None, default=None): + + +## ... source file abbreviated to get to IncludeNode examples ... + + + + +def restore_sekizai_context(context, changes): + varname = get_varname() + sekizai_container = context.get(varname) + for key, values in changes.items(): + sekizai_namespace = sekizai_container[key] + for value in values: + sekizai_namespace.append(value) + + +def _scan_placeholders(nodelist, node_class=None, current_block=None, ignore_blocks=None): + from cms.templatetags.cms_tags import Placeholder + + if not node_class: + node_class = Placeholder + + nodes = [] + + if ignore_blocks is None: + ignore_blocks = [] + + for node in nodelist: + if isinstance(node, node_class): + nodes.append(node) +~~ elif isinstance(node, IncludeNode): + if node.template: + if not callable(getattr(node.template, 'render', None)): + if isinstance(node.template.var, Variable): + continue + else: + template = get_template(node.template.var) + else: + template = node.template + nodes += _scan_placeholders(_get_nodelist(template), node_class, current_block) + elif isinstance(node, ExtendsNode): + nodes += _get_placeholder_nodes_from_extend(node, node_class) + elif isinstance(node, VariableNode) and current_block: + if node.filter_expression.token == 'block.super': + if not hasattr(current_block.super, 'nodelist'): + raise TemplateSyntaxError("Cannot render block.super for blocks without a parent.") + nodes += _scan_placeholders(_get_nodelist(current_block.super), node_class, current_block.super) + elif isinstance(node, BlockNode) and node.name in ignore_blocks: + continue + elif hasattr(node, 'child_nodelists'): + for nodelist_name in node.child_nodelists: + if hasattr(node, nodelist_name): + subnodelist = getattr(node, nodelist_name) + if isinstance(subnodelist, NodeList): + if isinstance(node, BlockNode): + + +## ... source file continues with no further IncludeNode examples... + +``` + diff --git a/content/pages/examples/django/django-template-loader.markdown b/content/pages/examples/django/django-template-loader.markdown new file mode 100644 index 000000000..9098f4881 --- /dev/null +++ b/content/pages/examples/django/django-template-loader.markdown @@ -0,0 +1,1118 @@ +title: django.template loader Example Code +category: page +slug: django-template-loader-examples +sortorder: 500011368 +toc: False +sidebartitle: django.template loader +meta: Python example code that shows how to use the loader callable from the django.template module of the Django project. + + +`loader` is a callable within the `django.template` module of the Django project. + +Context, +Engine, +Library, +Node, +NodeList, +Origin, +RequestContext, +Template, +TemplateDoesNotExist, +TemplateSyntaxError, +Variable, +context, +engine, +and library +are several other callables with code examples from the same `django.template` package. + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_pool.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_pool.py) + +```python +# plugin_pool.py +from operator import attrgetter + +from django.core.exceptions import ImproperlyConfigured +from django.urls import re_path, include +from django.template.defaultfilters import slugify +from django.utils.encoding import force_text +from django.utils.functional import cached_property +from django.utils.module_loading import autodiscover_modules +from django.utils.translation import get_language, deactivate_all, activate +from django.template import TemplateDoesNotExist, TemplateSyntaxError + +from cms.exceptions import PluginAlreadyRegistered, PluginNotRegistered +from cms.plugin_base import CMSPluginBase +from cms.utils.conf import get_cms_setting +from cms.utils.helpers import normalize_name + + +class PluginPool: + + def __init__(self): + self.plugins = {} + self.discovered = False + + def _clear_cached(self): + if 'registered_plugins' in self.__dict__: + del self.__dict__['registered_plugins'] + + if 'plugins_with_extra_menu' in self.__dict__: + del self.__dict__['plugins_with_extra_menu'] + + if 'plugins_with_extra_placeholder_menu' in self.__dict__: + del self.__dict__['plugins_with_extra_placeholder_menu'] + + def discover_plugins(self): + if self.discovered: + + +## ... source file abbreviated to get to loader examples ... + + + autodiscover_modules('cms_plugins') + self.discovered = True + + def clear(self): + self.discovered = False + self.plugins = {} + self._clear_cached() + + def validate_templates(self, plugin=None): + if plugin: + plugins = [plugin] + else: + plugins = self.plugins.values() + for plugin in plugins: + if (plugin.render_plugin and not type(plugin.render_plugin) == property + or hasattr(plugin.model, 'render_template') + or hasattr(plugin, 'get_render_template')): + if (plugin.render_template is None and + not hasattr(plugin, 'get_render_template')): + raise ImproperlyConfigured( + "CMS Plugins must define a render template, " + "a get_render_template method or " + "set render_plugin=False: %s" % plugin + ) + elif not hasattr(plugin, 'get_render_template'): +~~ from django.template import loader + + template = plugin.render_template + if isinstance(template, str) and template: + try: +~~ loader.get_template(template) + except TemplateDoesNotExist as e: + if str(e) == template: + raise ImproperlyConfigured( + "CMS Plugins must define a render template (%s) that exists: %s" + % (plugin, template) + ) + else: + pass + except TemplateSyntaxError: + pass + else: + if plugin.allow_children: + raise ImproperlyConfigured( + "CMS Plugins can not define render_plugin=False and allow_children=True: %s" + % plugin + ) + + def register_plugin(self, plugin): + if not issubclass(plugin, CMSPluginBase): + raise ImproperlyConfigured( + "CMS Plugins must be subclasses of CMSPluginBase, %r is not." + % plugin + ) + plugin_name = plugin.__name__ + + +## ... source file continues with no further loader examples... + +``` + + +## Example 2 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / management / modelviz.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/management/modelviz.py) + +```python +# modelviz.py + +import datetime +import os +import re + +from django.apps import apps +from django.db.models.fields.related import ( + ForeignKey, ManyToManyField, OneToOneField, RelatedField, +) +from django.contrib.contenttypes.fields import GenericRelation +~~from django.template import Context, Template, loader +from django.utils.encoding import force_str +from django.utils.safestring import mark_safe +from django.utils.translation import activate as activate_language + + +__version__ = "1.1" +__license__ = "Python" +__author__ = "Bas van Oostveen ", +__contributors__ = [ + "Antonio Cavedoni " + "Stefano J. Attardi ", + "Carlo C8E Miron", + "Andre Campos ", + "Justin Findlay ", + "Alexander Houben ", + "Joern Hees ", + "Kevin Cherepski ", + "Jose Tomas Tocino ", + "Adam Dobrawy ", + "Mikkel Munch Mortensen ", + "Andrzej Bistram ", + "Daniel Lipsitt ", +] + + +## ... source file abbreviated to get to loader examples ... + + + def use_model(self, model_name): + if self.include_models: + for model_pattern in self.include_models: + model_pattern = '^%s$' % model_pattern.replace('*', '.*') + if re.search(model_pattern, model_name): + return True + if self.exclude_models: + for model_pattern in self.exclude_models: + model_pattern = '^%s$' % model_pattern.replace('*', '.*') + if re.search(model_pattern, model_name): + return False + return not self.include_models + + def skip_field(self, field): + if self.exclude_columns: + if self.verbose_names and field.verbose_name: + if field.verbose_name in self.exclude_columns: + return True + if field.name in self.exclude_columns: + return True + return False + + +def generate_dot(graph_data, template='django_extensions/graph_models/digraph.dot'): + if isinstance(template, str): +~~ template = loader.get_template(template) + + if not isinstance(template, Template) and not (hasattr(template, 'template') and isinstance(template.template, Template)): + raise Exception("Default Django template loader isn't used. " + "This can lead to the incorrect template rendering. " + "Please, check the settings.") + + c = Context(graph_data).flatten() + dot = template.render(c) + + return dot + + +def generate_graph_data(*args, **kwargs): + generator = ModelGraph(*args, **kwargs) + generator.generate_graph_data() + return generator.get_graph_data() + + +def use_model(model, include_models, exclude_models): + generator = ModelGraph([], include_models=include_models, exclude_models=exclude_models) + return generator.use_model(model) + + + +## ... source file continues with no further loader examples... + +``` + + +## Example 3 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / rest_framework / backends.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/rest_framework/backends.py) + +```python +# backends.py +import warnings + +~~from django.template import loader +from django.utils.deprecation import RenameMethodsBase + +from .. import compat, utils +from . import filters, filterset + + +class RenameAttributes(utils.RenameAttributesBase, RenameMethodsBase): + renamed_attributes = ( + ('default_filter_set', 'filterset_base', utils.MigrationNotice), + ) + renamed_methods = ( + ('get_filter_class', 'get_filterset_class', utils.MigrationNotice), + ) + + +class DjangoFilterBackend(metaclass=RenameAttributes): + filterset_base = filterset.FilterSet + raise_exception = True + + @property + def template(self): + if compat.is_crispy(): + return 'django_filters/rest_framework/crispy_form.html' + return 'django_filters/rest_framework/form.html' + + +## ... source file abbreviated to get to loader examples ... + + + return AutoFilterSet + + return None + + def get_filterset_kwargs(self, request, queryset, view): + return { + 'data': request.query_params, + 'queryset': queryset, + 'request': request, + } + + def filter_queryset(self, request, queryset, view): + filterset = self.get_filterset(request, queryset, view) + if filterset is None: + return queryset + + if not filterset.is_valid() and self.raise_exception: + raise utils.translate_validation(filterset.errors) + return filterset.qs + + def to_html(self, request, queryset, view): + filterset = self.get_filterset(request, queryset, view) + if filterset is None: + return None + +~~ template = loader.get_template(self.template) + context = {'filter': filterset} + return template.render(context, request) + + def get_coreschema_field(self, field): + if isinstance(field, filters.NumberFilter): + field_cls = compat.coreschema.Number + else: + field_cls = compat.coreschema.String + return field_cls( + description=str(field.extra.get('help_text', '')) + ) + + def get_schema_fields(self, view): + assert compat.coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`' + assert compat.coreschema is not None, 'coreschema must be installed to use `get_schema_fields()`' + + try: + queryset = view.get_queryset() + except Exception: + queryset = None + warnings.warn( + "{} is not compatible with schema generation".format(view.__class__) + ) + + + +## ... source file continues with no further loader examples... + +``` + + +## Example 4 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / widgets.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./widgets.py) + +```python +# widgets.py +import datetime +import re +from itertools import chain + +import django +from django import forms +from django.conf import settings +from django.forms.widgets import FILE_INPUT_CONTRADICTION +~~from django.template import loader +from django.utils import datetime_safe, formats +from django.utils.dates import MONTHS +from django.utils.encoding import force_str +from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + +from .compat import MULTIVALUE_DICT_TYPES, flatten_contexts + + +from django.forms.utils import to_current_timezone + + +RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$') + + +__all__ = ( + 'TextInput', 'PasswordInput', 'HiddenInput', 'ClearableFileInput', + 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', + 'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple', + 'RadioSelect', 'CheckboxSelectMultiple', 'SearchInput', 'RangeInput', + 'ColorInput', 'EmailInput', 'URLInput', 'PhoneNumberInput', 'NumberInput', + 'IPAddressInput', 'MultiWidget', 'Widget', 'SplitDateTimeWidget', + 'SplitHiddenDateTimeWidget', 'MultipleHiddenInput', 'SelectDateWidget', + + +## ... source file abbreviated to get to loader examples ... + + + + if value is None: + value = '' + + if value != '': + context['value'] = self.format_value(value) + + context.update(self.get_context_data()) + context['attrs'] = self.build_attrs(attrs) + + for key, attr in context['attrs'].items(): + if attr == 1: + if not isinstance(attr, bool): + context['attrs'][key] = str(attr) + + if self.datalist is not None: + context['datalist'] = self.datalist + return context + + def render(self, name, value, attrs=None, **kwargs): + template_name = kwargs.pop('template_name', None) + if template_name is None: + template_name = self.template_name + context = self.get_context(name, value, attrs=attrs or {}) + context = flatten_contexts(self.context_instance, context) +~~ return loader.render_to_string(template_name, context) + + +class TextInput(Input): + template_name = 'floppyforms/text.html' + input_type = 'text' + + def __init__(self, *args, **kwargs): + if kwargs.get('attrs', None) is not None: + self.input_type = kwargs['attrs'].pop('type', self.input_type) + super(TextInput, self).__init__(*args, **kwargs) + + +class PasswordInput(TextInput): + template_name = 'floppyforms/password.html' + input_type = 'password' + + def __init__(self, attrs=None, render_value=False): + super(PasswordInput, self).__init__(attrs) + self.render_value = render_value + + def render(self, name, value, attrs=None, renderer=None): + if not self.render_value: + value = None + return super(PasswordInput, self).render(name, value, attrs, renderer=renderer) + + +## ... source file abbreviated to get to loader examples ... + + + except ValueError: + pass + else: + match = RE_DATE.match(value) + if match: + year_val, month_val, day_val = map(int, match.groups()) + + context = self.get_context(name, value, attrs=attrs, + extra_context=extra_context) + + context['year_choices'] = [(i, i) for i in self.years] + context['year_val'] = year_val + + context['month_choices'] = list(MONTHS.items()) + context['month_val'] = month_val + + context['day_choices'] = [(i, i) for i in range(1, 32)] + context['day_val'] = day_val + + + if self.required is False: + context['year_choices'].insert(0, self.none_value) + context['month_choices'].insert(0, self.none_value) + context['day_choices'].insert(0, self.none_value) + +~~ return loader.render_to_string(self.template_name, context) + + def value_from_datadict(self, data, files, name): + y = data.get(self.year_field % name) + m = data.get(self.month_field % name) + d = data.get(self.day_field % name) + if y == m == d == "0": + return None + if y and m and d: + if settings.USE_L10N: + input_format = formats.get_format('DATE_INPUT_FORMATS')[0] + try: + date_value = datetime.date(int(y), int(m), int(d)) + except ValueError: + return '%s-%s-%s' % (y, m, d) + else: + date_value = datetime_safe.new_date(date_value) + return date_value.strftime(input_format) + else: + return '%s-%s-%s' % (y, m, d) + return data.get(name, None) + + + +## ... source file continues with no further loader examples... + +``` + + +## Example 5 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / fields.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./fields.py) + +```python +# fields.py +import re +from inspect import ismethod + +~~from django.template import loader +from django.utils import datetime_safe + +from haystack.exceptions import SearchFieldError +from haystack.utils import get_model_ct_tuple + + +class NOT_PROVIDED: + pass + + +DATE_REGEX = re.compile( + r"^(?P\d{4})-(?P\d{2})-(?P\d{2})(?:|T00:00:00Z?)$" +) +DATETIME_REGEX = re.compile( + r"^(?P\d{4})-(?P\d{2})-(?P\d{2})(T|\s+)(?P\d{2}):(?P\d{2}):(?P\d{2}).*?$" +) + + + + +class SearchField(object): + + field_type = None + + + +## ... source file abbreviated to get to loader examples ... + + + return [] + + elif not hasattr(current_objects, "__iter__"): + current_objects = [current_objects] + + return current_objects + + def prepare_template(self, obj): + if self.instance_name is None and self.template_name is None: + raise SearchFieldError( + "This field requires either its instance_name variable to be populated or an explicit template_name in order to load the correct template." + ) + + if self.template_name is not None: + template_names = self.template_name + + if not isinstance(template_names, (list, tuple)): + template_names = [template_names] + else: + app_label, model_name = get_model_ct_tuple(obj) + template_names = [ + "search/indexes/%s/%s_%s.txt" + % (app_label, model_name, self.instance_name) + ] + +~~ t = loader.select_template(template_names) + return t.render({"object": obj}) + + def convert(self, value): + return value + + +class CharField(SearchField): + field_type = "string" + + def __init__(self, **kwargs): + if kwargs.get("facet_class") is None: + kwargs["facet_class"] = FacetCharField + + super(CharField, self).__init__(**kwargs) + + def prepare(self, obj): + return self.convert(super(CharField, self).prepare(obj)) + + def convert(self, value): + if value is None: + return None + + return str(value) + + + +## ... source file continues with no further loader examples... + +``` + + +## Example 6 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / renderers.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./renderers.py) + +```python +# renderers.py +import base64 +from collections import OrderedDict +from urllib import parse + +from django import forms +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.core.paginator import Page +from django.http.multipartparser import parse_header +~~from django.template import engines, loader +from django.urls import NoReverseMatch +from django.utils.html import mark_safe + +from rest_framework import VERSION, exceptions, serializers, status +from rest_framework.compat import ( + INDENT_SEPARATORS, LONG_SEPARATORS, SHORT_SEPARATORS, coreapi, coreschema, + pygments_css, yaml +) +from rest_framework.exceptions import ParseError +from rest_framework.request import is_form_media_type, override_method +from rest_framework.settings import api_settings +from rest_framework.utils import encoders, json +from rest_framework.utils.breadcrumbs import get_breadcrumbs +from rest_framework.utils.field_mapping import ClassLookupDict + + +def zero_as_none(value): + return None if value == 0 else value + + +class BaseRenderer: + media_type = None + format = None + charset = 'utf-8' + + +## ... source file abbreviated to get to loader examples ... + + + exception_template_names = [ + '%(status_code)s.html', + 'api_exception.html' + ] + charset = 'utf-8' + + def render(self, data, accepted_media_type=None, renderer_context=None): + renderer_context = renderer_context or {} + view = renderer_context['view'] + request = renderer_context['request'] + response = renderer_context['response'] + + if response.exception: + template = self.get_exception_template(response) + else: + template_names = self.get_template_names(response, view) + template = self.resolve_template(template_names) + + if hasattr(self, 'resolve_context'): + context = self.resolve_context(data, request, response) + else: + context = self.get_template_context(data, renderer_context) + return template.render(context, request=request) + + def resolve_template(self, template_names): +~~ return loader.select_template(template_names) + + def get_template_context(self, data, renderer_context): + response = renderer_context['response'] + if response.exception: + data['status_code'] = response.status_code + return data + + def get_template_names(self, response, view): + if response.template_name: + return [response.template_name] + elif self.template_name: + return [self.template_name] + elif hasattr(view, 'get_template_names'): + return view.get_template_names() + elif hasattr(view, 'template_name'): + return [view.template_name] + raise ImproperlyConfigured( + 'Returned a template response with no `template_name` attribute set on either the view or response' + ) + + def get_exception_template(self, response): + template_names = [name % {'status_code': response.status_code} + for name in self.exception_template_names] + + + +## ... source file abbreviated to get to loader examples ... + + + serializers.JSONField: { + 'base_template': 'textarea.html', + }, + }) + + def render_field(self, field, parent_style): + if isinstance(field._field, serializers.HiddenField): + return '' + + style = self.default_style[field].copy() + style.update(field.style) + if 'template_pack' not in style: + style['template_pack'] = parent_style.get('template_pack', self.template_pack) + style['renderer'] = self + + field = field.as_form_field() + + if style.get('input_type') == 'datetime-local' and isinstance(field.value, str): + field.value = field.value.rstrip('Z') + + if 'template' in style: + template_name = style['template'] + else: + template_name = style['template_pack'].strip('/') + '/' + style['base_template'] + +~~ template = loader.get_template(template_name) + context = {'field': field, 'style': style} + return template.render(context) + + def render(self, data, accepted_media_type=None, renderer_context=None): + renderer_context = renderer_context or {} + form = data.serializer + + style = renderer_context.get('style', {}) + if 'template_pack' not in style: + style['template_pack'] = self.template_pack + style['renderer'] = self + + template_pack = style['template_pack'].strip('/') + template_name = template_pack + '/' + self.base_template +~~ template = loader.get_template(template_name) + context = { + 'form': form, + 'style': style + } + return template.render(context) + + +class BrowsableAPIRenderer(BaseRenderer): + media_type = 'text/html' + format = 'api' + template = 'rest_framework/api.html' + filter_template = 'rest_framework/filters/base.html' + code_style = 'emacs' + charset = 'utf-8' + form_renderer_class = HTMLFormRenderer + + def get_default_renderer(self, view): + renderers = [renderer for renderer in view.renderer_classes + if not issubclass(renderer, BrowsableAPIRenderer)] + non_template_renderers = [renderer for renderer in renderers + if not hasattr(renderer, 'get_template_names')] + + if not renderers: + return None + + +## ... source file abbreviated to get to loader examples ... + + + if not hasattr(view, 'get_queryset') or not hasattr(view, 'filter_backends'): + return + + paginator = getattr(view, 'paginator', None) + if isinstance(data, list): + pass + elif paginator is not None and data is not None: + try: + paginator.get_results(data) + except (TypeError, KeyError): + return + elif not isinstance(data, list): + return + + queryset = view.get_queryset() + elements = [] + for backend in view.filter_backends: + if hasattr(backend, 'to_html'): + html = backend().to_html(request, queryset, view) + if html: + elements.append(html) + + if not elements: + return + +~~ template = loader.get_template(self.filter_template) + context = {'elements': elements} + return template.render(context) + + def get_context(self, data, accepted_media_type, renderer_context): + view = renderer_context['view'] + request = renderer_context['request'] + response = renderer_context['response'] + + renderer = self.get_default_renderer(view) + + raw_data_post_form = self.get_raw_data_form(data, view, 'POST', request) + raw_data_put_form = self.get_raw_data_form(data, view, 'PUT', request) + raw_data_patch_form = self.get_raw_data_form(data, view, 'PATCH', request) + raw_data_put_or_patch_form = raw_data_put_form or raw_data_patch_form + + response_headers = OrderedDict(sorted(response.items())) + renderer_content_type = '' + if renderer: + renderer_content_type = '%s' % renderer.media_type + if renderer.charset: + renderer_content_type += ' ;%s' % renderer.charset + response_headers['Content-Type'] = renderer_content_type + + if getattr(view, 'paginator', None) and view.paginator.display_page_controls: + + +## ... source file abbreviated to get to loader examples ... + + + 'put_form': self.get_rendered_html_form(data, view, 'PUT', request), + 'post_form': self.get_rendered_html_form(data, view, 'POST', request), + 'delete_form': self.get_rendered_html_form(data, view, 'DELETE', request), + 'options_form': self.get_rendered_html_form(data, view, 'OPTIONS', request), + + 'extra_actions': self.get_extra_actions(view, response.status_code), + + 'filter_form': self.get_filter_form(data, view, request), + + 'raw_data_put_form': raw_data_put_form, + 'raw_data_post_form': raw_data_post_form, + 'raw_data_patch_form': raw_data_patch_form, + 'raw_data_put_or_patch_form': raw_data_put_or_patch_form, + + 'display_edit_forms': bool(response.status_code != 403), + + 'api_settings': api_settings, + 'csrf_cookie_name': csrf_cookie_name, + 'csrf_header_name': csrf_header_name + } + + def render(self, data, accepted_media_type=None, renderer_context=None): + self.accepted_media_type = accepted_media_type or '' + self.renderer_context = renderer_context or {} + +~~ template = loader.get_template(self.template) + context = self.get_context(data, accepted_media_type, renderer_context) + ret = template.render(context, request=renderer_context['request']) + + response = renderer_context['response'] + if response.status_code == status.HTTP_204_NO_CONTENT: + response.status_code = status.HTTP_200_OK + + return ret + + +class AdminRenderer(BrowsableAPIRenderer): + template = 'rest_framework/admin.html' + format = 'admin' + + def render(self, data, accepted_media_type=None, renderer_context=None): + self.accepted_media_type = accepted_media_type or '' + self.renderer_context = renderer_context or {} + + response = renderer_context['response'] + request = renderer_context['request'] + view = self.renderer_context['view'] + + if response.status_code == status.HTTP_400_BAD_REQUEST: + self.error_form = self.get_rendered_html_form(data, view, request.method, request) + self.error_title = {'POST': 'Create', 'PUT': 'Edit'}.get(request.method, 'Errors') + + with override_method(view, request, 'GET') as request: + response = view.get(request, *view.args, **view.kwargs) + data = response.data + +~~ template = loader.get_template(self.template) + context = self.get_context(data, accepted_media_type, renderer_context) + ret = template.render(context, request=renderer_context['request']) + + if response.status_code == status.HTTP_201_CREATED and 'Location' in response: + response.status_code = status.HTTP_303_SEE_OTHER + response['Location'] = request.build_absolute_uri() + ret = '' + + if response.status_code == status.HTTP_204_NO_CONTENT: + response.status_code = status.HTTP_303_SEE_OTHER + try: + response['Location'] = self.get_breadcrumbs(request)[-2][1] + except KeyError: + response['Location'] = request.full_path + ret = '' + + return ret + + def get_context(self, data, accepted_media_type, renderer_context): + context = super().get_context( + data, accepted_media_type, renderer_context + ) + + paginator = getattr(context['view'], 'paginator', None) + + +## ... source file abbreviated to get to loader examples ... + + + except (KeyError, NoReverseMatch): + return + + +class DocumentationRenderer(BaseRenderer): + media_type = 'text/html' + format = 'html' + charset = 'utf-8' + template = 'rest_framework/docs/index.html' + error_template = 'rest_framework/docs/error.html' + code_style = 'emacs' + languages = ['shell', 'javascript', 'python'] + + def get_context(self, data, request): + return { + 'document': data, + 'langs': self.languages, + 'lang_htmls': ["rest_framework/docs/langs/%s.html" % language for language in self.languages], + 'lang_intro_htmls': ["rest_framework/docs/langs/%s-intro.html" % language for language in self.languages], + 'code_style': pygments_css(self.code_style), + 'request': request + } + + def render(self, data, accepted_media_type=None, renderer_context=None): + if isinstance(data, coreapi.Document): +~~ template = loader.get_template(self.template) + context = self.get_context(data, renderer_context['request']) + return template.render(context, request=renderer_context['request']) + else: +~~ template = loader.get_template(self.error_template) + context = { + "data": data, + "request": renderer_context['request'], + "response": renderer_context['response'], + "debug": settings.DEBUG, + } + return template.render(context, request=renderer_context['request']) + + +class SchemaJSRenderer(BaseRenderer): + media_type = 'application/javascript' + format = 'javascript' + charset = 'utf-8' + template = 'rest_framework/schema.js' + + def render(self, data, accepted_media_type=None, renderer_context=None): + codec = coreapi.codecs.CoreJSONCodec() + schema = base64.b64encode(codec.encode(data)).decode('ascii') + +~~ template = loader.get_template(self.template) + context = {'schema': mark_safe(schema)} + request = renderer_context['request'] + return template.render(context, request=request) + + +class MultiPartRenderer(BaseRenderer): + media_type = 'multipart/form-data; boundary=BoUnDaRyStRiNg' + format = 'multipart' + charset = 'utf-8' + BOUNDARY = 'BoUnDaRyStRiNg' + + def render(self, data, accepted_media_type=None, renderer_context=None): + from django.test.client import encode_multipart + + if hasattr(data, 'items'): + for key, value in data.items(): + assert not isinstance(value, dict), ( + "Test data contained a dictionary value for key '%s', " + "but multipart uploads do not support nested data. " + "You may want to consider using format='json' in this " + "test case." % key + ) + return encode_multipart(self.BOUNDARY, data) + + + +## ... source file continues with no further loader examples... + +``` + + +## Example 7 from django-request-token +[Django Request Token](https://github.com/yunojuno/django-request-token) +([PyPI package information](https://pypi.org/project/django-request-token/0.13/)) +encapsulates the logic for issuing expiring and one-time tokens +with a [Django](/django.html) web application to use with protected URLs. +Note that [PostgreSQL](/postgresql.html) as your backend +[database](/databases.html) is a dependency for using this project. + +The Django Request Token project is open sourced under the +[MIT license](https://github.com/yunojuno/django-request-token/blob/master/LICENSE). + +[**django-request-token / request_token / apps.py**](https://github.com/yunojuno/django-request-token/blob/master/request_token/./apps.py) + +```python +# apps.py +from __future__ import annotations + +from django.apps import AppConfig +from django.core.exceptions import ImproperlyConfigured +~~from django.template import TemplateDoesNotExist, loader + +from .settings import FOUR03_TEMPLATE + + +class RequestTokenAppConfig(AppConfig): + + name = "request_token" + verbose_name = "JWT Request Tokens" + + def ready(self) -> None: + super(RequestTokenAppConfig, self).ready() + if FOUR03_TEMPLATE: + check_template(FOUR03_TEMPLATE) + + +def check_template(template: str) -> None: + try: +~~ loader.get_template(template) + except TemplateDoesNotExist: + raise ImproperlyConfigured( + f"Custom request token template does not exist: '{template}'" + ) + + + +## ... source file continues with no further loader examples... + +``` + + +## Example 8 from graphite-web +[Graphite](https://github.com/graphite-project/graphite-web) +([project website](http://graphiteapp.org/), +[documentation](https://graphite.readthedocs.io/en/latest/) and +[PyPI package information](https://pypi.org/project/graphite-web/)) +is a metrics collection and visualization tool, built with both +Python and JavaScript. Metrics are collected by a Node.js application +and displayed using a [Django](/django.html) web application, +called "Graphite-Web", which is one of three core projects under +the Graphite umbrella (the other two are +[Carbon](https://github.com/graphite-project/carbon) and +[Whisper](https://github.com/graphite-project/whisper)). + +Graphite is provided as open sourced under the +[Apache License 2.0](https://github.com/graphite-project/whisper/blob/master/LICENSE). + +[**graphite-web / webapp / graphite / views.py**](https://github.com/graphite-project/graphite-web/blob/master/webapp/graphite/views.py) + +```python +# views.py +import traceback +from django.http import HttpResponseServerError +~~from django.template import loader + + +def server_error(request, template_name='500.html'): +~~ template = loader.get_template(template_name) + context = {'stacktrace' : traceback.format_exc()} + return HttpResponseServerError(template.render(context)) + + + +## ... source file continues with no further loader examples... + +``` + diff --git a/content/pages/examples/django/django-template-loaders-filesystem-loader.markdown b/content/pages/examples/django/django-template-loaders-filesystem-loader.markdown new file mode 100644 index 000000000..88ec1cc4a --- /dev/null +++ b/content/pages/examples/django/django-template-loaders-filesystem-loader.markdown @@ -0,0 +1,59 @@ +title: django.template.loaders.filesystem Loader Example Code +category: page +slug: django-template-loaders-filesystem-loader-examples +sortorder: 500011398 +toc: False +sidebartitle: django.template.loaders.filesystem Loader +meta: Example code for understanding how to use the Loader class from the django.template.loaders.filesystem module of the Django project. + + +`Loader` is a class within the `django.template.loaders.filesystem` module of the Django project. + + + +## Example 1 from django-markdown-view +[django-markdown-view](https://github.com/rgs258/django-markdown-view) +([PyPI package information](https://pypi.org/project/django-markdown-view/)) +is a Django extension for serving [Markdown](/markdown.html) files as +[Django templates](/django-templates.html). The project is open +sourced under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/rgs258/django-markdown-view/blob/master/LICENSE). + +[**django-markdown-view / markdown_view / loaders.py**](https://github.com/rgs258/django-markdown-view/blob/master/markdown_view/./loaders.py) + +```python +# loaders.py +from django.conf import settings +from django.core.exceptions import SuspiciousFileOperation +from django.template import Origin +~~from django.template.loaders.filesystem import Loader as FilesystemLoader +from django.template.utils import get_app_template_dirs +from django.utils._os import safe_join + +from markdown_view.constants import DEFAULT_MARKDOWN_VIEW_LOADER_TEMPLATES_DIR + + +class MarkdownLoader(FilesystemLoader): + + def get_dirs(self): + base_dir = getattr( + settings, + "MARKDOWN_VIEW_BASE_DIR", + getattr( + settings, + "BASE_DIR", + None) + ) + dirs = [*get_app_template_dirs( + getattr( + settings, + "MARKDOWN_VIEW_LOADER_TEMPLATES_DIR", + DEFAULT_MARKDOWN_VIEW_LOADER_TEMPLATES_DIR + ) + )] + + +## ... source file continues with no further Loader examples... + +``` + diff --git a/content/pages/examples/django/django-urls-clear-url-caches.markdown b/content/pages/examples/django/django-urls-clear-url-caches.markdown new file mode 100644 index 000000000..9917fae45 --- /dev/null +++ b/content/pages/examples/django/django-urls-clear-url-caches.markdown @@ -0,0 +1,78 @@ +title: django.urls clear_url_caches Example Code +category: page +slug: django-urls-clear-url-caches-examples +sortorder: 500011402 +toc: False +sidebartitle: django.urls clear_url_caches +meta: Python example code for the clear_url_caches callable from the django.urls module of the Django project. + + +clear_url_caches is a callable within the django.urls module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / signals / apphook.py**](https://github.com/divio/django-cms/blob/develop/cms/signals/apphook.py) + +```python +# apphook.py +import logging +import sys + +from django.core.management import color_style +from django.core.signals import request_finished +~~from django.urls import clear_url_caches + +from cms.utils.apphook_reload import mark_urlconf_as_changed + + +logger = logging.getLogger(__name__) + +DISPATCH_UID = 'cms-restart' + + +def trigger_server_restart(**kwargs): + mark_urlconf_as_changed() + + +def set_restart_trigger(): + request_finished.connect(trigger_restart, dispatch_uid=DISPATCH_UID) + + +def trigger_restart(**kwargs): + from cms.signals import urls_need_reloading + + request_finished.disconnect(trigger_restart, dispatch_uid=DISPATCH_UID) + urls_need_reloading.send(sender=None) + + +def debug_server_restart(**kwargs): + from cms.appresolver import clear_app_resolvers + if 'runserver' in sys.argv or 'server' in sys.argv: + clear_app_resolvers() +~~ clear_url_caches() + import cms.urls + try: + reload(cms.urls) + except NameError: #python3 + from imp import reload + reload(cms.urls) + if not 'test' in sys.argv: + msg = 'Application url changed and urls_need_reloading signal fired. ' \ + 'Please reload the urls.py or restart the server.\n' + styles = color_style() + msg = styles.NOTICE(msg) + sys.stderr.write(msg) + + + +## ... source file continues with no further clear_url_caches examples... + +``` + diff --git a/content/pages/examples/django/django-urls-get-callable.markdown b/content/pages/examples/django/django-urls-get-callable.markdown new file mode 100644 index 000000000..367b6e01d --- /dev/null +++ b/content/pages/examples/django/django-urls-get-callable.markdown @@ -0,0 +1,58 @@ +title: django.urls get_callable Example Code +category: page +slug: django-urls-get-callable-examples +sortorder: 500011403 +toc: False +sidebartitle: django.urls get_callable +meta: Python example code for the get_callable callable from the django.urls module of the Django project. + + +get_callable is a callable within the django.urls module of the Django project. + + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / editors / __init__.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/editors/__init__.py) + +```python +# __init__.py +~~from django.urls import get_callable +from wiki.conf import settings + +_EditorClass = None +_editor = None + + +def getEditorClass(): + global _EditorClass + if not _EditorClass: +~~ _EditorClass = get_callable(settings.EDITOR) + return _EditorClass + + +def getEditor(): + global _editor + if not _editor: + _editor = getEditorClass()() + return _editor + + + +## ... source file continues with no further get_callable examples... + +``` + diff --git a/content/pages/examples/django/django-urls-get-resolver.markdown b/content/pages/examples/django/django-urls-get-resolver.markdown new file mode 100644 index 000000000..b88d6017f --- /dev/null +++ b/content/pages/examples/django/django-urls-get-resolver.markdown @@ -0,0 +1,209 @@ +title: django.urls get_resolver Example Code +category: page +slug: django-urls-get-resolver-examples +sortorder: 500011404 +toc: False +sidebartitle: django.urls get_resolver +meta: Python example code for the get_resolver callable from the django.urls module of the Django project. + + +get_resolver is a callable within the django.urls module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / utils / i18n.py**](https://github.com/divio/django-cms/blob/develop/cms/utils/i18n.py) + +```python +# i18n.py +from contextlib import contextmanager + +from django.conf import settings +from django.utils import translation +from django.utils.translation import ugettext_lazy as _ +~~from django.urls import get_resolver + +from cms.exceptions import LanguageError +from cms.utils.compat.dj import LocalePrefixPattern +from cms.utils.conf import get_cms_setting, get_site_id + + +@contextmanager +def force_language(new_lang): + old_lang = get_current_language() + if old_lang != new_lang: + translation.activate(new_lang) + yield + translation.activate(old_lang) + + +def get_languages(site_id=None): + site_id = get_site_id(site_id) + result = get_cms_setting('LANGUAGES').get(site_id) + if not result: + result = [] + defaults = get_cms_setting('LANGUAGES').get('default', {}) + for code, name in settings.LANGUAGES: + lang = {'code': code, 'name': _(name)} + lang.update(defaults) + + +## ... source file abbreviated to get to get_resolver examples ... + + + +def get_fallback_languages(language, site_id=None): + try: + language = get_language_object(language, site_id) + except LanguageError: + language = get_languages(site_id)[0] + return language.get('fallbacks', []) + + +def get_redirect_on_fallback(language, site_id=None): + language = get_language_object(language, site_id) + return language.get('redirect_on_fallback', True) + + +def hide_untranslated(language, site_id=None): + obj = get_language_object(language, site_id) + return obj.get('hide_untranslated', True) + + +def is_language_prefix_patterns_used(): + return any( + isinstance( + getattr(url_pattern, 'pattern', url_pattern), + LocalePrefixPattern + ) +~~ for url_pattern in get_resolver(None).url_patterns + ) + + +def is_valid_site_language(language, site_id): + return language in get_language_list(site_id) + + + +## ... source file continues with no further get_resolver examples... + +``` + + +## Example 2 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / admin.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./admin.py) + +```python +# admin.py +from typing import Tuple, Type, Optional + +from django import forms +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import admin +from django.contrib import messages +from django.contrib.admin.sites import NotRegistered +from django.http import HttpResponseRedirect, HttpRequest, HttpResponse +~~from django.urls import get_urlconf, get_resolver +from django.utils.translation import gettext_lazy as _ + +from .fields import TreeItemChoiceField +from .settings import MODEL_TREE, MODEL_TREE_ITEM +from .utils import get_tree_model, get_tree_item_model, get_app_n_model + +if False: # pragma: nocover + from .models import TreeItemBase, TreeBase # noqa + + +SMUGGLER_INSTALLED = 'smuggler' in django_settings.INSTALLED_APPS + +MODEL_TREE_CLASS = get_tree_model() +MODEL_TREE_ITEM_CLASS = get_tree_item_model() + +_TREE_ADMIN = lambda: TreeAdmin +_ITEM_ADMIN = lambda: TreeItemAdmin + + +def get_model_url_name(model_nfo: Tuple[str, str], page: str, with_namespace: bool = False) -> str: + prefix = '' + if with_namespace: + prefix = 'admin:' + return (f'{prefix}%s_{page}' % '%s_%s' % model_nfo).lower() + + +## ... source file abbreviated to get to get_resolver examples ... + + + elif '_continue' in request.POST: + return response + + return HttpResponseRedirect('') + + def response_add(self, request, obj, post_url_continue=None, **kwargs): + if post_url_continue is None: + post_url_continue = f'../item_{obj.pk}/' + + return self._redirect(request, super().response_add(request, obj, post_url_continue)) + + def response_change(self, request, obj, **kwargs): + return self._redirect(request, super().response_change(request, obj)) + + def get_form(self, request, obj=None, **kwargs): + if obj is not None and obj.parent is not None: + self.previous_parent = obj.parent + + form = super().get_form(request, obj, **kwargs) + form.base_fields['parent'].choices_init(self.tree) + + if not getattr(self, 'known_url_names', False): + self.known_url_names = [] + self.known_url_rules = [] + +~~ resolver = get_resolver(get_urlconf()) + + for ns, (url_prefix, ns_resolver) in resolver.namespace_dict.items(): + if ns != 'admin': + self._stack_known_urls(ns_resolver.reverse_dict, ns) + + self._stack_known_urls(resolver.reverse_dict) + self.known_url_rules = sorted(self.known_url_rules) + + form.known_url_names_hint = _( + 'You are seeing this warning because "URL as Pattern" option is active and pattern entered above ' + 'seems to be invalid. Currently registered URL pattern names and parameters: ') + + form.known_url_names = self.known_url_names + form.known_url_rules = self.known_url_rules + + return form + + def _stack_known_urls(self, reverse_dict, ns=None): + for url_name, url_rules in reverse_dict.items(): + if isinstance(url_name, str): + if ns is not None: + url_name = f'{ns}:{url_name}' + self.known_url_names.append(url_name) + self.known_url_rules.append(f"{url_name} {' '.join(url_rules[0][0][1])}") + + +## ... source file continues with no further get_resolver examples... + +``` + diff --git a/content/pages/examples/django/django-urls-get-script-prefix.markdown b/content/pages/examples/django/django-urls-get-script-prefix.markdown new file mode 100644 index 000000000..375b7cc92 --- /dev/null +++ b/content/pages/examples/django/django-urls-get-script-prefix.markdown @@ -0,0 +1,124 @@ +title: django.urls get_script_prefix Example Code +category: page +slug: django-urls-get-script-prefix-examples +sortorder: 500011405 +toc: False +sidebartitle: django.urls get_script_prefix +meta: Python example code for the get_script_prefix callable from the django.urls module of the Django project. + + +get_script_prefix is a callable within the django.urls module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / relations.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./relations.py) + +```python +# relations.py +import sys +from collections import OrderedDict +from urllib import parse + +from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist +from django.db.models import Manager +from django.db.models.query import QuerySet +~~from django.urls import NoReverseMatch, Resolver404, get_script_prefix, resolve +from django.utils.encoding import smart_str, uri_to_iri +from django.utils.translation import gettext_lazy as _ + +from rest_framework.fields import ( + Field, empty, get_attribute, is_simple_callable, iter_options +) +from rest_framework.reverse import reverse +from rest_framework.settings import api_settings +from rest_framework.utils import html + + +def method_overridden(method_name, klass, instance): + method = getattr(klass, method_name) + default_method = getattr(method, '__func__', method) # Python 3 compat + return default_method is not getattr(instance, method_name).__func__ + + +class ObjectValueError(ValueError): + + +class ObjectTypeError(TypeError): + + +class Hyperlink(str): + + +## ... source file abbreviated to get to get_script_prefix examples ... + + + return queryset.get(**lookup_kwargs) + except ValueError: + exc = ObjectValueError(str(sys.exc_info()[1])) + raise exc.with_traceback(sys.exc_info()[2]) + except TypeError: + exc = ObjectTypeError(str(sys.exc_info()[1])) + raise exc.with_traceback(sys.exc_info()[2]) + + def get_url(self, obj, view_name, request, format): + if hasattr(obj, 'pk') and obj.pk in (None, ''): + return None + + lookup_value = getattr(obj, self.lookup_field) + kwargs = {self.lookup_url_kwarg: lookup_value} + return self.reverse(view_name, kwargs=kwargs, request=request, format=format) + + def to_internal_value(self, data): + request = self.context.get('request', None) + try: + http_prefix = data.startswith(('http:', 'https:')) + except AttributeError: + self.fail('incorrect_type', data_type=type(data).__name__) + + if http_prefix: + data = parse.urlparse(data).path +~~ prefix = get_script_prefix() + if data.startswith(prefix): + data = '/' + data[len(prefix):] + + data = uri_to_iri(parse.unquote(data)) + + try: + match = resolve(data) + except Resolver404: + self.fail('no_match') + + try: + expected_viewname = request.versioning_scheme.get_versioned_viewname( + self.view_name, request + ) + except AttributeError: + expected_viewname = self.view_name + + if match.view_name != expected_viewname: + self.fail('incorrect_match') + + try: + return self.get_object(match.view_name, match.args, match.kwargs) + except (ObjectDoesNotExist, ObjectValueError, ObjectTypeError): + self.fail('does_not_exist') + + +## ... source file continues with no further get_script_prefix examples... + +``` + diff --git a/content/pages/examples/django/django-urls-include.markdown b/content/pages/examples/django/django-urls-include.markdown new file mode 100644 index 000000000..30788b92a --- /dev/null +++ b/content/pages/examples/django/django-urls-include.markdown @@ -0,0 +1,328 @@ +title: django.urls include Example Code +category: page +slug: django-urls-include-examples +sortorder: 500011406 +toc: False +sidebartitle: django.urls include +meta: Python example code for the include callable from the django.urls module of the Django project. + + +include is a callable within the django.urls module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / wwwdccn / urls.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/wwwdccn/urls.py) + +```python +# urls.py +from django.conf import settings +from django.conf.urls.static import static +~~from django.urls import path, include + +urlpatterns = [ +~~ path('', include('public_site.urls')), +~~ path('user/', include('user_site.urls')), +~~ path('auth/', include('auth_app.urls')), +~~ path('users/', include('users.urls')), +~~ path('registration/', include('registration.urls')), +~~ path('conferences/', include('conferences.urls')), +~~ path('submissions/', include('submissions.urls')), +~~ path('chair/', include('chair.urls')), +~~ path('chair_mail/', include('chair_mail.urls')), +~~ path('review/', include('review.urls')), +~~ path('gears/', include('gears.urls')), +~~ path('proceedings/', include('proceedings.urls')), +] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + +if settings.USE_LOCAL_MEDIA: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + +if settings.USE_DEBUG_TOOLBAR: + import debug_toolbar + urlpatterns = [ +~~ path('__debug__/', include(debug_toolbar.urls)), + + + ] + urlpatterns + + + +## ... source file continues with no further include examples... + +``` + + +## Example 2 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / urls.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/./urls.py) + +```python +# urls.py +from importlib import import_module + +~~from django.urls import include, path + +from allauth.socialaccount import providers + +from . import app_settings + + +~~urlpatterns = [path('', include('allauth.account.urls'))] + +if app_settings.SOCIALACCOUNT_ENABLED: +~~ urlpatterns += [path('social/', include('allauth.socialaccount.urls'))] + +provider_urlpatterns = [] +for provider in providers.registry.get_list(): + try: + prov_mod = import_module(provider.get_package() + '.urls') + except ImportError: + continue + prov_urlpatterns = getattr(prov_mod, 'urlpatterns', None) + if prov_urlpatterns: + provider_urlpatterns += prov_urlpatterns +urlpatterns += provider_urlpatterns + + + +## ... source file continues with no further include examples... + +``` + + +## Example 3 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / sites.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./sites.py) + +```python +# sites.py +from django.apps import apps +~~from django.urls import include +from django.urls import re_path +from django.utils.functional import LazyObject +from django.utils.module_loading import import_string +from wiki.conf import settings +from wiki.core.plugins import registry + + +class WikiSite: + + def __init__(self, name="wiki"): + from wiki.views import accounts, article, deleted_list + + self.name = name + + self.root_view = getattr(self, "root_view", article.CreateRootView.as_view()) + self.root_missing_view = getattr( + self, "root_missing_view", article.MissingRootView.as_view() + ) + + self.article_view = getattr(self, "article_view", article.ArticleView.as_view()) + self.article_create_view = getattr( + self, "article_create_view", article.Create.as_view() + ) + self.article_delete_view = getattr( + + +## ... source file abbreviated to get to include examples ... + + + re_path( + r"^_accounts/settings/$", + self.profile_update_view, + name="profile_update", + ), + ] + else: + urlpatterns = [] + return urlpatterns + + def get_revision_urls(self): + urlpatterns = [ + re_path( + r"^change/(?P[0-9]+)/$", + self.revision_change_view, + name="change_revision", + ), + re_path(r"^preview/$", self.article_preview_view, name="preview_revision"), + re_path( + r"^merge/(?P[0-9]+)/preview/$", + self.revision_preview_merge_view, + name="merge_revision_preview", + ), + ] + return [ +~~ re_path(r"^_revision/(?P[0-9]+)/", include(urlpatterns)), + ] + + def get_article_urls(self): + urlpatterns = [ + re_path(r"^$", self.article_view, name="get"), + re_path(r"^delete/$", self.article_delete_view, name="delete"), + re_path(r"^deleted/$", self.article_deleted_view, name="deleted"), + re_path(r"^edit/$", self.article_edit_view, name="edit"), + re_path(r"^move/$", self.article_move_view, name="move"), + re_path(r"^preview/$", self.article_preview_view, name="preview"), + re_path(r"^history/$", self.article_history_view, name="history"), + re_path(r"^settings/$", self.article_settings_view, name="settings"), + re_path(r"^source/$", self.article_source_view, name="source"), + re_path( + r"^revision/change/(?P[0-9]+)/$", + self.revision_change_view, + name="change_revision", + ), + re_path( + r"^revision/merge/(?P[0-9]+)/$", + self.revision_merge_view, + name="merge_revision", + ), + re_path( + r"^plugin/(?P\w+)/$", self.article_plugin_view, name="plugin" + ), + ] + return [ +~~ re_path(r"^(?P[0-9]+)/", include(urlpatterns)), + ] + + def get_article_path_urls(self): + urlpatterns = [ + re_path( + r"^(?P.+/|)_create/$", self.article_create_view, name="create" + ), + re_path( + r"^(?P.+/|)_delete/$", self.article_delete_view, name="delete" + ), + re_path( + r"^(?P.+/|)_deleted/$", self.article_deleted_view, name="deleted" + ), + re_path(r"^(?P.+/|)_edit/$", self.article_edit_view, name="edit"), + re_path(r"^(?P.+/|)_move/$", self.article_move_view, name="move"), + re_path( + r"^(?P.+/|)_preview/$", self.article_preview_view, name="preview" + ), + re_path( + r"^(?P.+/|)_history/$", self.article_history_view, name="history" + ), + re_path(r"^(?P.+/|)_dir/$", self.article_dir_view, name="dir"), + re_path(r"^(?P.+/|)_search/$", self.search_view, name="search"), + re_path( + + +## ... source file abbreviated to get to include examples ... + + + name="change_revision", + ), + re_path( + r"^(?P.+/|)_revision/merge/(?P[0-9]+)/$", + self.revision_merge_view, + name="merge_revision", + ), + re_path( + r"^(?P.+/|)_plugin/(?P\w+)/$", + self.article_plugin_view, + name="plugin", + ), + re_path(r"^(?P.+/|)$", self.article_view, name="get"), + ] + return urlpatterns + + def get_plugin_urls(self): + urlpatterns = [] + for plugin in registry.get_plugins().values(): + slug = getattr(plugin, "slug", None) + if slug: + article_urlpatterns = plugin.urlpatterns.get("article", []) + urlpatterns += [ + re_path( + r"^(?P[0-9]+)/plugin/" + slug + "/", +~~ include(article_urlpatterns), + ), + re_path( + r"^(?P.+/|)_plugin/" + slug + "/", +~~ include(article_urlpatterns), + ), + ] + root_urlpatterns = plugin.urlpatterns.get("root", []) + urlpatterns += [ +~~ re_path(r"^_plugin/" + slug + "/", include(root_urlpatterns)), + ] + return urlpatterns + + +class DefaultWikiSite(LazyObject): + def _setup(self): + WikiSiteClass = import_string(apps.get_app_config("wiki").default_site) + self._wrapped = WikiSiteClass() + + +site = DefaultWikiSite() + + + +## ... source file continues with no further include examples... + +``` + + +## Example 4 from drf-action-serializer +[drf-action-serializer](https://github.com/gregschmit/drf-action-serializer) +([PyPI page](https://pypi.org/project/drf-action-serializer/)) +that makes it easier to configure specific serializers to use based on the +client's request action. For example, a list view should have one serializer +whereas the detail view would have a different serializer. + +The project is open source under the +[MIT license](https://github.com/gregschmit/drf-action-serializer/blob/master/LICENSE). + +[**drf-action-serializer / action_serializer / urls.py**](https://github.com/gregschmit/drf-action-serializer/blob/master/action_serializer/./urls.py) + +```python +# urls.py +from django.contrib import admin +~~from django.urls import include, path +from rest_framework.routers import DefaultRouter + +from .sample_group_viewset import GroupViewSet + + +router = DefaultRouter() +router.register("auth/group", GroupViewSet) +router.register("auth/groups", GroupViewSet) + +urlpatterns = [ +~~ path("api/", include(router.urls)), +~~ path("admin/doc/", include("django.contrib.admindocs.urls")), + path("admin/", admin.site.urls), +] + + + +## ... source file continues with no further include examples... + +``` + diff --git a/content/pages/examples/django/django-urls-re-path.markdown b/content/pages/examples/django/django-urls-re-path.markdown new file mode 100644 index 000000000..e150f7d10 --- /dev/null +++ b/content/pages/examples/django/django-urls-re-path.markdown @@ -0,0 +1,359 @@ +title: django.urls re_path Example Code +category: page +slug: django-urls-re-path-examples +sortorder: 500011408 +toc: False +sidebartitle: django.urls re_path +meta: Python example code for the re_path callable from the django.urls module of the Django project. + + +re_path is a callable within the django.urls module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / urls.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/urls.py) + +```python +# urls.py +~~from django.urls import path, re_path + +from . import views + + +urlpatterns = [ + path("signup/", views.signup, name="account_signup"), + path("login/", views.login, name="account_login"), + path("logout/", views.logout, name="account_logout"), + path("password/change/", views.password_change, + name="account_change_password"), + path("password/set/", views.password_set, name="account_set_password"), + path("inactive/", views.account_inactive, name="account_inactive"), + + path("email/", views.email, name="account_email"), + path("confirm-email/", views.email_verification_sent, + name="account_email_verification_sent"), +~~ re_path(r"^confirm-email/(?P[-:\w]+)/$", views.confirm_email, + name="account_confirm_email"), + + path("password/reset/", views.password_reset, + name="account_reset_password"), + path("password/reset/done/", views.password_reset_done, + name="account_reset_password_done"), +~~ re_path(r"^password/reset/key/(?P[0-9A-Za-z]+)-(?P.+)/$", + views.password_reset_from_key, + name="account_reset_password_from_key"), + path("password/reset/key/done/", views.password_reset_from_key_done, + name="account_reset_password_from_key_done"), +] + + + +## ... source file continues with no further re_path examples... + +``` + + +## Example 2 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / urls.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./urls.py) + +```python +# urls.py +~~from django.urls import re_path + +from . import views + + +app_name = "oauth2_provider" + + +base_urlpatterns = [ +~~ re_path(r"^authorize/$", views.AuthorizationView.as_view(), name="authorize"), +~~ re_path(r"^token/$", views.TokenView.as_view(), name="token"), +~~ re_path(r"^revoke_token/$", views.RevokeTokenView.as_view(), name="revoke-token"), +~~ re_path(r"^introspect/$", views.IntrospectTokenView.as_view(), name="introspect"), +] + + +management_urlpatterns = [ +~~ re_path(r"^applications/$", views.ApplicationList.as_view(), name="list"), +~~ re_path(r"^applications/register/$", views.ApplicationRegistration.as_view(), name="register"), +~~ re_path(r"^applications/(?P[\w-]+)/$", views.ApplicationDetail.as_view(), name="detail"), +~~ re_path(r"^applications/(?P[\w-]+)/delete/$", views.ApplicationDelete.as_view(), name="delete"), +~~ re_path(r"^applications/(?P[\w-]+)/update/$", views.ApplicationUpdate.as_view(), name="update"), +~~ re_path(r"^authorized_tokens/$", views.AuthorizedTokensListView.as_view(), name="authorized-token-list"), +~~ re_path(r"^authorized_tokens/(?P[\w-]+)/delete/$", views.AuthorizedTokenDeleteView.as_view(), + name="authorized-token-delete"), +] + + +urlpatterns = base_urlpatterns + management_urlpatterns + + + +## ... source file continues with no further re_path examples... + +``` + + +## Example 3 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / sites.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./sites.py) + +```python +# sites.py +from django.apps import apps +from django.urls import include +~~from django.urls import re_path +from django.utils.functional import LazyObject +from django.utils.module_loading import import_string +from wiki.conf import settings +from wiki.core.plugins import registry + + +class WikiSite: + + def __init__(self, name="wiki"): + from wiki.views import accounts, article, deleted_list + + self.name = name + + self.root_view = getattr(self, "root_view", article.CreateRootView.as_view()) + self.root_missing_view = getattr( + self, "root_missing_view", article.MissingRootView.as_view() + ) + + self.article_view = getattr(self, "article_view", article.ArticleView.as_view()) + self.article_create_view = getattr( + self, "article_create_view", article.Create.as_view() + ) + self.article_delete_view = getattr( + self, "article_delete_view", article.Delete.as_view() + + +## ... source file abbreviated to get to re_path examples ... + + + self.profile_update_view = getattr( + self, "profile_update_view", accounts.Update.as_view() + ) + + self.deleted_list_view = getattr( + self, "deleted_list_view", deleted_list.DeletedListView.as_view() + ) + + def get_urls(self): + urlpatterns = self.get_root_urls() + urlpatterns += self.get_accounts_urls() + urlpatterns += self.get_deleted_list_urls() + urlpatterns += self.get_revision_urls() + urlpatterns += self.get_article_urls() + urlpatterns += self.get_plugin_urls() + + urlpatterns += self.get_article_path_urls() + return urlpatterns + + @property + def urls(self): + return self.get_urls(), "wiki", self.name + + def get_root_urls(self): + urlpatterns = [ +~~ re_path(r"^$", self.article_view, name="root", kwargs={"path": ""}), +~~ re_path(r"^create-root/$", self.root_view, name="root_create"), +~~ re_path(r"^missing-root/$", self.root_missing_view, name="root_missing"), +~~ re_path(r"^_search/$", self.search_view, name="search"), +~~ re_path( + r"^_revision/diff/(?P[0-9]+)/$", + self.article_diff_view, + name="diff", + ), + ] + return urlpatterns + + def get_deleted_list_urls(self): + urlpatterns = [ +~~ re_path("^_admin/$", self.deleted_list_view, name="deleted_list"), + ] + return urlpatterns + + def get_accounts_urls(self): + if settings.ACCOUNT_HANDLING: + urlpatterns = [ +~~ re_path(r"^_accounts/sign-up/$", self.signup_view, name="signup"), +~~ re_path(r"^_accounts/logout/$", self.logout_view, name="logout"), +~~ re_path(r"^_accounts/login/$", self.login_view, name="login"), +~~ re_path( + r"^_accounts/settings/$", + self.profile_update_view, + name="profile_update", + ), + ] + else: + urlpatterns = [] + return urlpatterns + + def get_revision_urls(self): + urlpatterns = [ +~~ re_path( + r"^change/(?P[0-9]+)/$", + self.revision_change_view, + name="change_revision", + ), +~~ re_path(r"^preview/$", self.article_preview_view, name="preview_revision"), +~~ re_path( + r"^merge/(?P[0-9]+)/preview/$", + self.revision_preview_merge_view, + name="merge_revision_preview", + ), + ] + return [ +~~ re_path(r"^_revision/(?P[0-9]+)/", include(urlpatterns)), + ] + + def get_article_urls(self): + urlpatterns = [ +~~ re_path(r"^$", self.article_view, name="get"), +~~ re_path(r"^delete/$", self.article_delete_view, name="delete"), +~~ re_path(r"^deleted/$", self.article_deleted_view, name="deleted"), +~~ re_path(r"^edit/$", self.article_edit_view, name="edit"), +~~ re_path(r"^move/$", self.article_move_view, name="move"), +~~ re_path(r"^preview/$", self.article_preview_view, name="preview"), +~~ re_path(r"^history/$", self.article_history_view, name="history"), +~~ re_path(r"^settings/$", self.article_settings_view, name="settings"), +~~ re_path(r"^source/$", self.article_source_view, name="source"), +~~ re_path( + r"^revision/change/(?P[0-9]+)/$", + self.revision_change_view, + name="change_revision", + ), +~~ re_path( + r"^revision/merge/(?P[0-9]+)/$", + self.revision_merge_view, + name="merge_revision", + ), +~~ re_path( + r"^plugin/(?P\w+)/$", self.article_plugin_view, name="plugin" + ), + ] + return [ +~~ re_path(r"^(?P[0-9]+)/", include(urlpatterns)), + ] + + def get_article_path_urls(self): + urlpatterns = [ +~~ re_path( + r"^(?P.+/|)_create/$", self.article_create_view, name="create" + ), +~~ re_path( + r"^(?P.+/|)_delete/$", self.article_delete_view, name="delete" + ), +~~ re_path( + r"^(?P.+/|)_deleted/$", self.article_deleted_view, name="deleted" + ), +~~ re_path(r"^(?P.+/|)_edit/$", self.article_edit_view, name="edit"), +~~ re_path(r"^(?P.+/|)_move/$", self.article_move_view, name="move"), +~~ re_path( + r"^(?P.+/|)_preview/$", self.article_preview_view, name="preview" + ), +~~ re_path( + r"^(?P.+/|)_history/$", self.article_history_view, name="history" + ), +~~ re_path(r"^(?P.+/|)_dir/$", self.article_dir_view, name="dir"), +~~ re_path(r"^(?P.+/|)_search/$", self.search_view, name="search"), +~~ re_path( + r"^(?P.+/|)_settings/$", + self.article_settings_view, + name="settings", + ), +~~ re_path( + r"^(?P.+/|)_source/$", self.article_source_view, name="source" + ), +~~ re_path( + r"^(?P.+/|)_revision/change/(?P[0-9]+)/$", + self.revision_change_view, + name="change_revision", + ), +~~ re_path( + r"^(?P.+/|)_revision/merge/(?P[0-9]+)/$", + self.revision_merge_view, + name="merge_revision", + ), +~~ re_path( + r"^(?P.+/|)_plugin/(?P\w+)/$", + self.article_plugin_view, + name="plugin", + ), +~~ re_path(r"^(?P.+/|)$", self.article_view, name="get"), + ] + return urlpatterns + + def get_plugin_urls(self): + urlpatterns = [] + for plugin in registry.get_plugins().values(): + slug = getattr(plugin, "slug", None) + if slug: + article_urlpatterns = plugin.urlpatterns.get("article", []) + urlpatterns += [ +~~ re_path( + r"^(?P[0-9]+)/plugin/" + slug + "/", + include(article_urlpatterns), + ), +~~ re_path( + r"^(?P.+/|)_plugin/" + slug + "/", + include(article_urlpatterns), + ), + ] + root_urlpatterns = plugin.urlpatterns.get("root", []) + urlpatterns += [ +~~ re_path(r"^_plugin/" + slug + "/", include(root_urlpatterns)), + ] + return urlpatterns + + +class DefaultWikiSite(LazyObject): + def _setup(self): + WikiSiteClass = import_string(apps.get_app_config("wiki").default_site) + self._wrapped = WikiSiteClass() + + +site = DefaultWikiSite() + + + +## ... source file continues with no further re_path examples... + +``` + diff --git a/content/pages/examples/django/django-urls-register-converter.markdown b/content/pages/examples/django/django-urls-register-converter.markdown new file mode 100644 index 000000000..652ace426 --- /dev/null +++ b/content/pages/examples/django/django-urls-register-converter.markdown @@ -0,0 +1,101 @@ +title: django.urls register_converter Example Code +category: page +slug: django-urls-register-converter-examples +sortorder: 500011409 +toc: False +sidebartitle: django.urls register_converter +meta: Python example code for the register_converter callable from the django.urls module of the Django project. + + +register_converter is a callable within the django.urls module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / urlpatterns.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./urlpatterns.py) + +```python +# urlpatterns.py +from django.conf.urls import include, url +~~from django.urls import URLResolver, path, register_converter +from django.urls.resolvers import RoutePattern + +from rest_framework.settings import api_settings + + +def _get_format_path_converter(suffix_kwarg, allowed): + if allowed: + if len(allowed) == 1: + allowed_pattern = allowed[0] + else: + allowed_pattern = '(?:%s)' % '|'.join(allowed) + suffix_pattern = r"\.%s/?" % allowed_pattern + else: + suffix_pattern = r"\.[a-z0-9]+/?" + + class FormatSuffixConverter: + regex = suffix_pattern + + def to_python(self, value): + return value.strip('./') + + def to_url(self, value): + return '.' + value + '/' + + + +## ... source file abbreviated to get to register_converter examples ... + + + assert path is not None + assert suffix_route is not None + route = str(urlpattern.pattern).rstrip('$').rstrip('/') + suffix_route + new_pattern = path(route, view, kwargs, name) + else: + new_pattern = url(regex, view, kwargs, name) + + ret.append(new_pattern) + + return ret + + +def format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None): + suffix_kwarg = api_settings.FORMAT_SUFFIX_KWARG + if allowed: + if len(allowed) == 1: + allowed_pattern = allowed[0] + else: + allowed_pattern = '(%s)' % '|'.join(allowed) + suffix_pattern = r'\.(?P<%s>%s)/?$' % (suffix_kwarg, allowed_pattern) + else: + suffix_pattern = r'\.(?P<%s>[a-z0-9]+)/?$' % suffix_kwarg + + if path and register_converter: + converter_name, suffix_converter = _get_format_path_converter(suffix_kwarg, allowed) +~~ register_converter(suffix_converter, converter_name) + + suffix_route = '<%s:%s>' % (converter_name, suffix_kwarg) + else: + suffix_route = None + + return apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required, suffix_route) + + + +## ... source file continues with no further register_converter examples... + +``` + diff --git a/content/pages/examples/django/django-urls-resolve.markdown b/content/pages/examples/django/django-urls-resolve.markdown new file mode 100644 index 000000000..3b34c1096 --- /dev/null +++ b/content/pages/examples/django/django-urls-resolve.markdown @@ -0,0 +1,615 @@ +title: django.urls resolve Example Code +category: page +slug: django-urls-resolve-examples +sortorder: 500011410 +toc: False +sidebartitle: django.urls resolve +meta: Python example code for the resolve callable from the django.urls module of the Django project. + + +resolve is a callable within the django.urls module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / core / urlresolvers.py**](https://github.com/jrief/django-angular/blob/master/djng/core/urlresolvers.py) + +```python +# urlresolvers.py +from inspect import isclass + +~~from django.urls import (get_resolver, get_urlconf, resolve, reverse, NoReverseMatch) +from django.core.exceptions import ImproperlyConfigured + +try: + from django.utils.module_loading import import_string +except ImportError: + from django.utils.module_loading import import_by_path as import_string + +from djng.views.mixins import JSONResponseMixin + + +def _get_remote_methods_for(view_object, url): + result = {} + for field in dir(view_object): + member = getattr(view_object, field, None) + if callable(member) and hasattr(member, 'allow_rmi'): + config = { + 'url': url, + 'method': getattr(member, 'allow_rmi'), + 'headers': {'DjNg-Remote-Method': field}, + } + result.update({field: config}) + return result + + +def get_all_remote_methods(resolver=None, ns_prefix=''): + if not resolver: + resolver = get_resolver(get_urlconf()) + result = {} + for name in resolver.reverse_dict.keys(): + if not isinstance(name, str): + continue + try: + url = reverse(ns_prefix + name) +~~ resmgr = resolve(url) + ViewClass = import_string('{0}.{1}'.format(resmgr.func.__module__, resmgr.func.__name__)) + if isclass(ViewClass) and issubclass(ViewClass, JSONResponseMixin): + result[name] = _get_remote_methods_for(ViewClass, url) + except (NoReverseMatch, ImproperlyConfigured): + pass + for namespace, ns_pattern in resolver.namespace_dict.items(): + sub_res = get_all_remote_methods(ns_pattern[1], ns_prefix + namespace + ':') + if sub_res: + result[namespace] = sub_res + return result + + +def get_current_remote_methods(view): + if isinstance(view, JSONResponseMixin): + return _get_remote_methods_for(view, view.request.path_info) + + + +## ... source file continues with no further resolve examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / page_rendering.py**](https://github.com/divio/django-cms/blob/develop/cms/./page_rendering.py) + +```python +# page_rendering.py +from django.conf import settings +from django.http import Http404 +from django.shortcuts import render +from django.template.response import TemplateResponse +~~from django.urls import Resolver404, resolve, reverse + +from cms import __version__ +from cms.cache.page import set_page_cache +from cms.models import Page +from cms.utils.conf import get_cms_setting +from cms.utils.page import get_page_template_from_request +from cms.utils.page_permissions import user_can_change_page, user_can_view_page + + +def render_page(request, page, current_language, slug): + context = {} + context['lang'] = current_language + context['current_page'] = page + context['has_change_permissions'] = user_can_change_page(request.user, page) + context['has_view_permissions'] = user_can_view_page(request.user, page) + + if not context['has_view_permissions']: + return _handle_no_page(request) + + template = get_page_template_from_request(request) + response = TemplateResponse(request, template, context) + response.add_post_render_callback(set_page_cache) + + xframe_options = page.get_xframe_options() + if xframe_options == Page.X_FRAME_OPTIONS_INHERIT or xframe_options is None: + return response + + response.xframe_options_exempt = True + + if xframe_options == Page.X_FRAME_OPTIONS_ALLOW: + return response + elif xframe_options == Page.X_FRAME_OPTIONS_SAMEORIGIN: + response['X-Frame-Options'] = 'SAMEORIGIN' + elif xframe_options == Page.X_FRAME_OPTIONS_DENY: + response['X-Frame-Options'] = 'DENY' + return response + + +def render_object_structure(request, obj): + context = { + 'object': obj, + 'cms_toolbar': request.toolbar, + } + return render(request, 'cms/toolbar/structure.html', context) + + +def _handle_no_page(request): + try: +~~ resolve('%s$' % request.path) + except Resolver404 as e: + exc = Http404(dict(path=request.path, tried=e.args[0]['tried'])) + raise exc + raise Http404('CMS Page not found: %s' % request.path) + + +def _render_welcome_page(request): + context = { + 'cms_version': __version__, + 'cms_edit_on': get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'), + 'django_debug': settings.DEBUG, + 'next_url': reverse('pages-root'), + } + return TemplateResponse(request, "cms/welcome.html", context) + + + +## ... source file continues with no further resolve examples... + +``` + + +## Example 3 from django-debug-toolbar +[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar) +([project documentation](https://github.com/jazzband/django-debug-toolbar) +and [PyPI page](https://pypi.org/project/django-debug-toolbar/)) +grants a developer detailed request-response cycle information while +developing a [Django](/django.html) web application. +The code for django-debug-toolbar is +[open source](https://github.com/jazzband/django-debug-toolbar/blob/master/LICENSE) +and maintained by the developer community group known as +[Jazzband](https://jazzband.co/). + +[**django-debug-toolbar / debug_toolbar / panels / request.py**](https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/panels/request.py) + +```python +# request.py +from django.http import Http404 +~~from django.urls import resolve +from django.utils.translation import gettext_lazy as _ + +from debug_toolbar.panels import Panel +from debug_toolbar.utils import get_name_from_obj + + +class RequestPanel(Panel): + + template = "debug_toolbar/panels/request.html" + + title = _("Request") + + @property + def nav_subtitle(self): + view_func = self.get_stats().get("view_func", "") + return view_func.rsplit(".", 1)[-1] + + def generate_stats(self, request, response): + self.record_stats( + { + "get": [(k, request.GET.getlist(k)) for k in sorted(request.GET)], + "post": [(k, request.POST.getlist(k)) for k in sorted(request.POST)], + "cookies": [ + (k, request.COOKIES.get(k)) for k in sorted(request.COOKIES) + ], + } + ) + view_info = { + "view_func": _(""), + "view_args": "None", + "view_kwargs": "None", + "view_urlname": "None", + } + try: +~~ match = resolve(request.path) + func, args, kwargs = match + view_info["view_func"] = get_name_from_obj(func) + view_info["view_args"] = args + view_info["view_kwargs"] = kwargs + view_info["view_urlname"] = getattr(match, "url_name", _("")) + except Http404: + pass + self.record_stats(view_info) + + if hasattr(request, "session"): + self.record_stats( + { + "session": [ + (k, request.session.get(k)) + for k in sorted(request.session.keys()) + ] + } + ) + + + +## ... source file continues with no further resolve examples... + +``` + + +## Example 4 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / utils.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./utils.py) + +```python +# utils.py +import datetime +import json +from django.template import Context +from django.utils import translation +from jet import settings +from jet.models import PinnedApplication + +try: + from django.apps.registry import apps +except ImportError: + try: + from django.apps import apps # Fix Django 1.7 import issue + except ImportError: + pass +from django.core.serializers.json import DjangoJSONEncoder +from django.http import HttpResponse +try: + from django.core.urlresolvers import reverse, resolve, NoReverseMatch +except ImportError: # Django 1.11 +~~ from django.urls import reverse, resolve, NoReverseMatch + +from django.contrib.admin import AdminSite +from django.utils.encoding import smart_text +from django.utils.text import capfirst +from django.contrib import messages +from django.utils.encoding import force_text +from django.utils.functional import Promise +from django.contrib.admin.options import IncorrectLookupParameters +from django.contrib import admin +from django.utils.translation import ugettext_lazy as _ +from django.utils.text import slugify + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # Python 2.6 + + +class JsonResponse(HttpResponse): + + def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs): + if safe and not isinstance(data, dict): + raise TypeError('In order to allow non-dict objects to be ' + 'serialized set the safe parameter to False') + + +## ... source file abbreviated to get to resolve examples ... + + + app_dict[app_label] = { + 'name': name, + 'app_label': app_label, + 'app_url': reverse( + 'admin:app_list', + kwargs={'app_label': app_label}, + current_app=admin_site.name, + ), + 'has_module_perms': has_module_perms, + 'models': [model_dict], + } + + app_list = list(app_dict.values()) + + if order: + app_list.sort(key=lambda x: x['name'].lower()) + + for app in app_list: + app['models'].sort(key=lambda x: x['name']) + + return app_list + + +def get_admin_site(context): + try: +~~ current_resolver = resolve(context.get('request').path) +~~ index_resolver = resolve(reverse('%s:index' % current_resolver.namespaces[0])) + + if hasattr(index_resolver.func, 'admin_site'): + return index_resolver.func.admin_site + + for func_closure in index_resolver.func.__closure__: + if isinstance(func_closure.cell_contents, AdminSite): + return func_closure.cell_contents + except: + pass + + return admin.site + + +def get_admin_site_name(context): + return get_admin_site(context).name + + +class LazyDateTimeEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date): + return obj.isoformat() + elif isinstance(obj, Promise): + return force_text(obj) + return self.encode(obj) + + +## ... source file continues with no further resolve examples... + +``` + + +## Example 5 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / relations.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./relations.py) + +```python +# relations.py +import sys +from collections import OrderedDict +from urllib import parse + +from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist +from django.db.models import Manager +from django.db.models.query import QuerySet +~~from django.urls import NoReverseMatch, Resolver404, get_script_prefix, resolve +from django.utils.encoding import smart_str, uri_to_iri +from django.utils.translation import gettext_lazy as _ + +from rest_framework.fields import ( + Field, empty, get_attribute, is_simple_callable, iter_options +) +from rest_framework.reverse import reverse +from rest_framework.settings import api_settings +from rest_framework.utils import html + + +def method_overridden(method_name, klass, instance): + method = getattr(klass, method_name) + default_method = getattr(method, '__func__', method) # Python 3 compat + return default_method is not getattr(instance, method_name).__func__ + + +class ObjectValueError(ValueError): + + +class ObjectTypeError(TypeError): + + +class Hyperlink(str): + + +## ... source file abbreviated to get to resolve examples ... + + + + def get_url(self, obj, view_name, request, format): + if hasattr(obj, 'pk') and obj.pk in (None, ''): + return None + + lookup_value = getattr(obj, self.lookup_field) + kwargs = {self.lookup_url_kwarg: lookup_value} + return self.reverse(view_name, kwargs=kwargs, request=request, format=format) + + def to_internal_value(self, data): + request = self.context.get('request', None) + try: + http_prefix = data.startswith(('http:', 'https:')) + except AttributeError: + self.fail('incorrect_type', data_type=type(data).__name__) + + if http_prefix: + data = parse.urlparse(data).path + prefix = get_script_prefix() + if data.startswith(prefix): + data = '/' + data[len(prefix):] + + data = uri_to_iri(parse.unquote(data)) + + try: +~~ match = resolve(data) + except Resolver404: + self.fail('no_match') + + try: + expected_viewname = request.versioning_scheme.get_versioned_viewname( + self.view_name, request + ) + except AttributeError: + expected_viewname = self.view_name + + if match.view_name != expected_viewname: + self.fail('incorrect_match') + + try: + return self.get_object(match.view_name, match.args, match.kwargs) + except (ObjectDoesNotExist, ObjectValueError, ObjectTypeError): + self.fail('does_not_exist') + + def to_representation(self, value): + assert 'request' in self.context, ( + "`%s` requires the request in the serializer" + " context. Add `context={'request': request}` when instantiating " + "the serializer." % self.__class__.__name__ + ) + + +## ... source file continues with no further resolve examples... + +``` + + +## Example 6 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / forms.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./forms.py) + +```python +# forms.py + "UserCreationForm", + "UserUpdateForm", + "WikiSlugField", + "SpamProtectionMixin", + "CreateRootForm", + "MoveForm", + "EditForm", + "SelectWidgetBootstrap", + "TextInputPrepend", + "CreateForm", + "DeleteForm", + "PermissionsForm", + "DirFilterForm", + "SearchForm", +] + +from datetime import timedelta + +from django import forms +from django.apps import apps +from django.contrib.auth import get_user_model +from django.core import validators +from django.core.validators import RegexValidator +from django.forms.widgets import HiddenInput +from django.shortcuts import get_object_or_404 +~~from django.urls import Resolver404, resolve +from django.utils import timezone +from django.utils.safestring import mark_safe +from django.utils.translation import gettext, gettext_lazy as _, pgettext_lazy +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.plugins.base import PluginSettingsFormMixin +from wiki.editors import getEditor + +from .forms_account_handling import UserCreationForm, UserUpdateForm + +validate_slug_numbers = RegexValidator( + r"^[0-9]+$", + _("A 'slug' cannot consist solely of numbers."), + "invalid", + inverse_match=True, +) + + +class WikiSlugField(forms.CharField): + + default_validators = [validators.validate_slug, validate_slug_numbers] + + + +## ... source file abbreviated to get to resolve examples ... + + + raise forms.ValidationError(gettext("A slug may not begin with an underscore.")) + if slug == "admin": + raise forms.ValidationError(gettext("'admin' is not a permitted slug name.")) + + if settings.URL_CASE_SENSITIVE: + already_existing_slug = models.URLPath.objects.filter(slug=slug, parent=urlpath) + else: + slug = slug.lower() + already_existing_slug = models.URLPath.objects.filter( + slug__iexact=slug, parent=urlpath + ) + if already_existing_slug: + already_urlpath = already_existing_slug[0] + if already_urlpath.article and already_urlpath.article.current_revision.deleted: + raise forms.ValidationError( + gettext('A deleted article with slug "%s" already exists.') + % already_urlpath.slug + ) + else: + raise forms.ValidationError( + gettext('A slug named "%s" already exists.') % already_urlpath.slug + ) + + if settings.CHECK_SLUG_URL_AVAILABLE: + try: +~~ match = resolve(urlpath.path + "/" + slug + "/") + if match.app_name != "wiki": + raise forms.ValidationError( + gettext("This slug conflicts with an existing URL.") + ) + except Resolver404: + pass + + return slug + + +User = get_user_model() +Group = apps.get_model(settings.GROUP_MODEL) + + +class SpamProtectionMixin: + + + revision_model = models.ArticleRevision + + def check_spam(self): # noqa + request = self.request + user = None + ip_address = None + if request.user.is_authenticated: + + +## ... source file continues with no further resolve examples... + +``` + diff --git a/content/pages/examples/django/django-urls-reverse.markdown b/content/pages/examples/django/django-urls-reverse.markdown new file mode 100644 index 000000000..b56cbce5b --- /dev/null +++ b/content/pages/examples/django/django-urls-reverse.markdown @@ -0,0 +1,2796 @@ +title: django.urls reverse Example Code +category: page +slug: django-urls-reverse-examples +sortorder: 500011411 +toc: False +sidebartitle: django.urls reverse +meta: Python example code for the reverse callable from the django.urls module of the Django project. + + +reverse is a callable within the django.urls module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / chair / forms.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/chair/forms.py) + +```python +# forms.py +from functools import reduce + +from django import forms +from django.contrib.auth import get_user_model +from django.db import models +from django.db.models import Q, F, Count, Max, Subquery, OuterRef, Value +from django.db.models.functions import Concat +from django.forms import MultipleChoiceField, ChoiceField, Form +~~from django.urls import reverse +from django.utils.translation import ugettext_lazy as _ + +from django_countries import countries + +from conferences.models import Conference, ArtifactDescriptor +from gears.widgets import CustomCheckboxSelectMultiple, CustomFileInput +from review.models import Reviewer, Review, ReviewStats +from review.utilities import get_average_score +from submissions.models import Submission, Attachment +from users.models import Profile + +User = get_user_model() + + +def clean_data_to_int(iterable, empty=None): + return [int(x) if x != '' else None for x in iterable] + + +def q_or(disjuncts, default=True): + if disjuncts: + return reduce(lambda acc, d: acc | d, disjuncts) + return Q(pk__isnull=(not default)) # otherwise, check whether PK is null + + + + +## ... source file abbreviated to get to reverse examples ... + + + record[self.ORDER_COLUMN] = order + + if self.ID_COLUMN in columns: + record[self.ID_COLUMN] = sub.pk + + if self.TITLE_COLUMN in columns: + record[self.TITLE_COLUMN] = sub.title + + if self.AUTHORS_COLUMN in columns: + names = [get_user_name(profiles[a.user_id]) for a in authors] + record[self.AUTHORS_COLUMN] = '; '.join(names) + + if self.COUNTRY_COLUMN in columns: + countries_list = [ + profiles[a.user_id].get_country_display() for a in authors] + countries_list = list(set(countries_list)) # remove duplicates + countries_list.sort() + record[self.COUNTRY_COLUMN] = '; '.join(countries_list) + + if self.STYPE_COLUMN in columns: + record[self.STYPE_COLUMN] = ( + sub.stype.get_language_display() if sub.stype else '') + + if self.REVIEW_PAPER_COLUMN in columns: + record[self.REVIEW_PAPER_COLUMN] = request.build_absolute_uri( +~~ reverse('submissions:download-manuscript', args=[sub.pk])) + + if self.REVIEW_SCORE_COLUMN in columns: + score = get_average_score(sub) + score_string = f'{score:.1f}' if score else '-' + record[self.REVIEW_SCORE_COLUMN] = score_string + + if self.STATUS_COLUMN in columns: + record[self.STATUS_COLUMN] = sub.get_status_display() + + if self.TOPICS_COLUMN in columns: + record[self.TOPICS_COLUMN] = '; '.join(sub.topics.values_list( + 'name', flat=True)) + + + result.append(record) + return result + + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 2 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / socialaccount / adapter.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/adapter.py) + +```python +# adapter.py +from __future__ import absolute_import + +from django.core.exceptions import ValidationError +~~from django.urls import reverse +from django.utils.translation import gettext_lazy as _ + +from ..account import app_settings as account_settings +from ..account.adapter import get_adapter as get_account_adapter +from ..account.app_settings import EmailVerificationMethod +from ..account.models import EmailAddress +from ..account.utils import user_email, user_field, user_username +from ..utils import ( + deserialize_instance, + email_address_exists, + import_attribute, + serialize_instance, + valid_email_or_none, +) +from . import app_settings + + +class DefaultSocialAccountAdapter(object): + + error_messages = { + 'email_taken': + _("An account already exists with this e-mail address." + " Please sign in to that account first, then connect" + " your %s account.") + + +## ... source file abbreviated to get to reverse examples ... + + + get_account_adapter().save_user(request, u, form) + else: + get_account_adapter().populate_username(request, u) + sociallogin.save(request) + return u + + def populate_user(self, + request, + sociallogin, + data): + username = data.get('username') + first_name = data.get('first_name') + last_name = data.get('last_name') + email = data.get('email') + name = data.get('name') + user = sociallogin.user + user_username(user, username or '') + user_email(user, valid_email_or_none(email) or '') + name_parts = (name or '').partition(' ') + user_field(user, 'first_name', first_name or name_parts[0]) + user_field(user, 'last_name', last_name or name_parts[2]) + return user + + def get_connect_redirect_url(self, request, socialaccount): + assert request.user.is_authenticated +~~ url = reverse('socialaccount_connections') + return url + + def validate_disconnect(self, account, accounts): + if len(accounts) == 1: + if not account.user.has_usable_password(): + raise ValidationError(_("Your account has no password set" + " up.")) + if app_settings.EMAIL_VERIFICATION \ + == EmailVerificationMethod.MANDATORY: + if EmailAddress.objects.filter(user=account.user, + verified=True).count() == 0: + raise ValidationError(_("Your account has no verified" + " e-mail address.")) + + def is_auto_signup_allowed(self, request, sociallogin): + auto_signup = app_settings.AUTO_SIGNUP + if auto_signup: + email = user_email(sociallogin.user) + if email: + if account_settings.UNIQUE_EMAIL: + if email_address_exists(email): + auto_signup = False + elif app_settings.EMAIL_REQUIRED: + auto_signup = False + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 3 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / urls.py**](https://github.com/jrief/django-angular/blob/master/djng/./urls.py) + +```python +# urls.py +import warnings +~~from django.urls import reverse +from django.conf.urls import url +from django.http.response import HttpResponsePermanentRedirect + + +warnings.warn("Reversing URL's using urlpatterns is deprecated. Please use the middleware instead", + DeprecationWarning) + + +def angular_reverse(request, *args, **kwargs): + url_name = request.GET.get('djng_url_name') + url_args = request.GET.getlist('djng_url_args', None) + url_kwargs = {} + + prefix = 'djng_url_kwarg_' + for param in request.GET: + if param.startswith(prefix): + url_kwargs[param[len(prefix):]] = request.GET[param] + +~~ url = reverse(url_name, args=url_args, kwargs=url_kwargs) + return HttpResponsePermanentRedirect(url) + + +urlpatterns = [ + url(r'^reverse/$', angular_reverse), +] + + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 4 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / tests / test_handlers.py**](https://github.com/jazzband/django-axes/blob/master/axes/tests/test_handlers.py) + +```python +# test_handlers.py +from unittest.mock import MagicMock, patch + +from django.test import override_settings +~~from django.urls import reverse +from django.utils import timezone +from django.utils.timezone import timedelta + +from axes.conf import settings +from axes.handlers.proxy import AxesProxyHandler +from axes.helpers import get_client_str +from axes.models import AccessAttempt, AccessLog +from axes.tests.base import AxesTestCase + + +@override_settings(AXES_HANDLER="axes.handlers.base.AxesHandler") +class AxesHandlerTestCase(AxesTestCase): + def test_base_handler_reset_attempts_raises(self): + with self.assertRaises(NotImplementedError): + AxesProxyHandler.reset_attempts() + + def test_base_handler_reset_logs_raises(self): + with self.assertRaises(NotImplementedError): + AxesProxyHandler.reset_logs() + + def test_base_handler_raises_on_undefined_is_allowed_to_authenticate(self): + with self.assertRaises(NotImplementedError): + AxesProxyHandler.is_allowed(self.request, {}) + + + +## ... source file abbreviated to get to reverse examples ... + + + @override_settings( + AXES_NEVER_LOCKOUT_WHITELIST=True, AXES_IP_WHITELIST=["127.0.0.1"] + ) + def test_is_allowed_with_whitelisted_ip_address(self): + self.assertTrue(AxesProxyHandler.is_allowed(self.request)) + + @override_settings(AXES_NEVER_LOCKOUT_GET=True) + def test_is_allowed_with_whitelisted_method(self): + self.request.method = "GET" + self.assertTrue(AxesProxyHandler.is_allowed(self.request)) + + @override_settings(AXES_LOCK_OUT_AT_FAILURE=False) + def test_is_allowed_no_lock_out(self): + self.assertTrue(AxesProxyHandler.is_allowed(self.request)) + + @override_settings(AXES_ONLY_ADMIN_SITE=True) + def test_only_admin_site(self): + request = MagicMock() + request.path = "/test/" + self.assertTrue(AxesProxyHandler.is_allowed(self.request)) + + def test_is_admin_site(self): + request = MagicMock() + tests = ( # (AXES_ONLY_ADMIN_SITE, URL, Expected) + (True, "/test/", True), +~~ (True, reverse("admin:index"), False), + (False, "/test/", False), +~~ (False, reverse("admin:index"), False), + ) + + for setting_value, url, expected in tests: + with override_settings(AXES_ONLY_ADMIN_SITE=setting_value): + request.path = url + self.assertEqual(AxesProxyHandler().is_admin_site(request), expected) + + @override_settings(ROOT_URLCONF="axes.tests.urls_empty") + @override_settings(AXES_ONLY_ADMIN_SITE=True) + def test_is_admin_site_no_admin_site(self): + request = MagicMock() + request.path = "/admin/" + self.assertTrue(AxesProxyHandler().is_admin_site(self.request)) + + +class AxesProxyHandlerTestCase(AxesTestCase): + def setUp(self): + self.sender = MagicMock() + self.credentials = MagicMock() + self.request = MagicMock() + self.user = MagicMock() + self.instance = MagicMock() + + @patch("axes.handlers.proxy.AxesProxyHandler.implementation", None) + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 5 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / page_rendering.py**](https://github.com/divio/django-cms/blob/develop/cms/./page_rendering.py) + +```python +# page_rendering.py +from django.conf import settings +from django.http import Http404 +from django.shortcuts import render +from django.template.response import TemplateResponse +~~from django.urls import Resolver404, resolve, reverse + +from cms import __version__ +from cms.cache.page import set_page_cache +from cms.models import Page +from cms.utils.conf import get_cms_setting +from cms.utils.page import get_page_template_from_request +from cms.utils.page_permissions import user_can_change_page, user_can_view_page + + +def render_page(request, page, current_language, slug): + context = {} + context['lang'] = current_language + context['current_page'] = page + context['has_change_permissions'] = user_can_change_page(request.user, page) + context['has_view_permissions'] = user_can_view_page(request.user, page) + + if not context['has_view_permissions']: + return _handle_no_page(request) + + template = get_page_template_from_request(request) + response = TemplateResponse(request, template, context) + response.add_post_render_callback(set_page_cache) + + xframe_options = page.get_xframe_options() + + +## ... source file abbreviated to get to reverse examples ... + + + return response + + +def render_object_structure(request, obj): + context = { + 'object': obj, + 'cms_toolbar': request.toolbar, + } + return render(request, 'cms/toolbar/structure.html', context) + + +def _handle_no_page(request): + try: + resolve('%s$' % request.path) + except Resolver404 as e: + exc = Http404(dict(path=request.path, tried=e.args[0]['tried'])) + raise exc + raise Http404('CMS Page not found: %s' % request.path) + + +def _render_welcome_page(request): + context = { + 'cms_version': __version__, + 'cms_edit_on': get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'), + 'django_debug': settings.DEBUG, +~~ 'next_url': reverse('pages-root'), + } + return TemplateResponse(request, "cms/welcome.html", context) + + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 6 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / admin / widgets.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/admin/widgets.py) + +```python +# widgets.py +import six +from six.moves import urllib +from django import forms +from django.contrib.admin.sites import site +from django.contrib.admin.widgets import ForeignKeyRawIdWidget +from django.template.loader import render_to_string +from django.templatetags.static import static +~~from django.urls import reverse +from django.utils.safestring import mark_safe +from django.utils.text import Truncator + + +class ForeignKeySearchInput(ForeignKeyRawIdWidget): + + widget_template = None + search_path = None + + def _media(self): + js_files = [ + static('django_extensions/js/jquery.bgiframe.js'), + static('django_extensions/js/jquery.ajaxQueue.js'), + static('django_extensions/js/jquery.autocomplete.js'), + ] + + return forms.Media( + css={'all': (static('django_extensions/css/jquery.autocomplete.css'), )}, + js=js_files, + ) + media = property(_media) + + def label_for_value(self, value): + key = self.rel.get_related_field().name + obj = self.rel.model._default_manager.get(**{key: value}) + + return Truncator(obj).words(14, truncate='...') + + def __init__(self, rel, search_fields, attrs=None): + self.search_fields = search_fields + super().__init__(rel, site, attrs) + + def render(self, name, value, attrs=None, renderer=None): + if attrs is None: + attrs = {} + opts = self.rel.model._meta + app_label = opts.app_label + model_name = opts.object_name.lower() +~~ related_url = reverse('admin:%s_%s_changelist' % (app_label, model_name)) + if not self.search_path: + self.search_path = urllib.parse.urljoin(related_url, 'foreignkey_autocomplete/') + params = self.url_parameters() + if params: + url = '?' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()]) + else: + url = '' + + if 'class' not in attrs: + attrs['class'] = 'vForeignKeyRawIdAdminField' + output = [forms.TextInput.render(self, name, value, attrs)] + + if value: + label = self.label_for_value(value) + else: + label = six.u('') + + context = { + 'url': url, + 'related_url': related_url, + 'search_path': self.search_path, + 'search_fields': ','.join(self.search_fields), + 'app_label': app_label, + 'model_name': model_name, + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 7 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / fileadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/fileadmin.py) + +```python +# fileadmin.py +from __future__ import absolute_import + +from django import forms +from django.contrib.admin.utils import unquote +from django.http import HttpResponseRedirect +~~from django.urls import reverse +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _ + +from .. import settings +from ..models import File +from .permissions import PrimitivePermissionAwareModelAdmin +from .tools import AdminContext, admin_url_params_encoded, popup_status + + +class FileAdminChangeFrom(forms.ModelForm): + class Meta(object): + model = File + exclude = () + + +class FileAdmin(PrimitivePermissionAwareModelAdmin): + list_display = ('label',) + list_per_page = 10 + search_fields = ['name', 'original_filename', 'sha1', 'description'] + raw_id_fields = ('owner',) + readonly_fields = ('sha1', 'display_canonical') + + form = FileAdminChangeFrom + + + +## ... source file abbreviated to get to reverse examples ... + + + (_('Advanced'), { + 'fields': ( + 'file', + 'sha1', + 'display_canonical', + ) + extra_advanced_fields, + 'classes': ('collapse',), + }), + ) + extra_fieldsets + if settings.FILER_ENABLE_PERMISSIONS: + fieldsets = fieldsets + ( + (None, { + 'fields': ('is_public',) + }), + ) + return fieldsets + + def response_change(self, request, obj): + if ( + request.POST + and '_continue' not in request.POST + and '_saveasnew' not in request.POST + and '_addanother' not in request.POST + ): + if obj.folder: +~~ url = reverse('admin:filer-directory_listing', + kwargs={'folder_id': obj.folder.id}) + else: +~~ url = reverse( + 'admin:filer-directory_listing-unfiled_images') + url = "{0}{1}".format( + url, + admin_url_params_encoded(request), + ) + return HttpResponseRedirect(url) + return super(FileAdmin, self).response_change(request, obj) + + def render_change_form(self, request, context, add=False, change=False, + form_url='', obj=None): + info = self.model._meta.app_label, self.model._meta.model_name + extra_context = {'show_delete': True, + 'history_url': 'admin:%s_%s_history' % info, + 'is_popup': popup_status(request), + 'filer_admin_context': AdminContext(request)} + context.update(extra_context) + return super(FileAdmin, self).render_change_form( + request=request, context=context, add=add, change=change, + form_url=form_url, obj=obj) + + def delete_view(self, request, object_id, extra_context=None): + try: + obj = self.get_queryset(request).get(pk=unquote(object_id)) + parent_folder = obj.folder + except self.model.DoesNotExist: + parent_folder = None + + if request.POST: + super(FileAdmin, self).delete_view( + request=request, object_id=object_id, + extra_context=extra_context) + if parent_folder: +~~ url = reverse('admin:filer-directory_listing', + kwargs={'folder_id': parent_folder.id}) + else: +~~ url = reverse('admin:filer-directory_listing-unfiled_images') + url = "{0}{1}".format( + url, + admin_url_params_encoded(request) + ) + return HttpResponseRedirect(url) + + return super(FileAdmin, self).delete_view( + request=request, object_id=object_id, + extra_context=extra_context) + + def get_model_perms(self, request): + return { + 'add': False, + 'change': False, + 'delete': False, + } + + def display_canonical(self, instance): + canonical = instance.canonical_url + if canonical: + return mark_safe('%s' % (canonical, canonical)) + else: + return '-' + display_canonical.allow_tags = True + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 8 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / admin.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./admin.py) + +```python +# admin.py +from collections import OrderedDict + +from django import forms +from django.conf import settings +from django.contrib import admin, messages +from django.contrib.admin.widgets import FilteredSelectMultiple +from django.contrib.auth import get_user_model +from django.shortcuts import get_object_or_404, redirect, render +~~from django.urls import reverse, path +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import gettext +from guardian.forms import GroupObjectPermissionsForm, UserObjectPermissionsForm +from django.contrib.auth.models import Group +from guardian.shortcuts import (get_group_perms, get_groups_with_perms, get_perms_for_model, get_user_perms, + get_users_with_perms) + + +class AdminUserObjectPermissionsForm(UserObjectPermissionsForm): + + def get_obj_perms_field_widget(self): + return FilteredSelectMultiple(_("Permissions"), False) + + +class AdminGroupObjectPermissionsForm(GroupObjectPermissionsForm): + + def get_obj_perms_field_widget(self): + return FilteredSelectMultiple(_("Permissions"), False) + + +class GuardedModelAdminMixin: + change_form_template = \ + 'admin/guardian/model/change_form.html' + obj_perms_manage_template = \ + + +## ... source file abbreviated to get to reverse examples ... + + + path('/permissions/group-manage//', + view=self.admin_site.admin_view( + self.obj_perms_manage_group_view), + name='%s_%s_permissions_manage_group' % info), + ] + urls = myurls + urls + return urls + + def get_obj_perms_base_context(self, request, obj): + context = self.admin_site.each_context(request) + context.update({ + 'adminform': {'model_admin': self}, + 'media': self.media, + 'object': obj, + 'app_label': self.model._meta.app_label, + 'opts': self.model._meta, + 'original': str(obj), + 'has_change_permission': self.has_change_permission(request, obj), + 'model_perms': get_perms_for_model(obj), + 'title': _("Object permissions"), + }) + return context + + def obj_perms_manage_view(self, request, object_pk): + if not self.has_change_permission(request, None): +~~ post_url = reverse('admin:index', current_app=self.admin_site.name) + return redirect(post_url) + + from django.contrib.admin.utils import unquote + obj = get_object_or_404(self.get_queryset( + request), pk=unquote(object_pk)) + users_perms = OrderedDict( + sorted( + get_users_with_perms(obj, attach_perms=True, + with_group_users=False).items(), + key=lambda user: getattr( + user[0], get_user_model().USERNAME_FIELD) + ) + ) + + groups_perms = OrderedDict( + sorted( + get_groups_with_perms(obj, attach_perms=True).items(), + key=lambda group: group[0].name + ) + ) + + if request.method == 'POST' and 'submit_manage_user' in request.POST: + user_form = self.get_obj_perms_user_select_form( + request)(request.POST) + group_form = self.get_obj_perms_group_select_form( + request)(request.POST) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + if user_form.is_valid(): + user_id = user_form.cleaned_data['user'].pk +~~ url = reverse( + '%s:%s_%s_permissions_manage_user' % info, + args=[obj.pk, user_id] + ) + return redirect(url) + elif request.method == 'POST' and 'submit_manage_group' in request.POST: + user_form = self.get_obj_perms_user_select_form( + request)(request.POST) + group_form = self.get_obj_perms_group_select_form( + request)(request.POST) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + if group_form.is_valid(): + group_id = group_form.cleaned_data['group'].id +~~ url = reverse( + '%s:%s_%s_permissions_manage_group' % info, + args=[obj.pk, group_id] + ) + return redirect(url) + else: + user_form = self.get_obj_perms_user_select_form(request)() + group_form = self.get_obj_perms_group_select_form(request)() + + context = self.get_obj_perms_base_context(request, obj) + context['users_perms'] = users_perms + context['groups_perms'] = groups_perms + context['user_form'] = user_form + context['group_form'] = group_form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_template(), context) + + def get_obj_perms_manage_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage.html' + return self.obj_perms_manage_template + + def obj_perms_manage_user_view(self, request, object_pk, user_id): + if not self.has_change_permission(request, None): +~~ post_url = reverse('admin:index', current_app=self.admin_site.name) + return redirect(post_url) + + user = get_object_or_404(get_user_model(), pk=user_id) + obj = get_object_or_404(self.get_queryset(request), pk=object_pk) + form_class = self.get_obj_perms_manage_user_form(request) + form = form_class(user, obj, request.POST or None) + + if request.method == 'POST' and form.is_valid(): + form.save_obj_perms() + msg = gettext("Permissions saved.") + messages.success(request, msg) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) +~~ url = reverse( + '%s:%s_%s_permissions_manage_user' % info, + args=[obj.pk, user.pk] + ) + return redirect(url) + + context = self.get_obj_perms_base_context(request, obj) + context['user_obj'] = user + context['user_perms'] = get_user_perms(user, obj) + context['form'] = form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_user_template(), context) + + def get_obj_perms_manage_user_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage_user.html' + return self.obj_perms_manage_user_template + + def get_obj_perms_user_select_form(self, request): + return UserManage + + def get_obj_perms_group_select_form(self, request): + return GroupManage + + def get_obj_perms_manage_user_form(self, request): + return AdminUserObjectPermissionsForm + + def obj_perms_manage_group_view(self, request, object_pk, group_id): + if not self.has_change_permission(request, None): +~~ post_url = reverse('admin:index', current_app=self.admin_site.name) + return redirect(post_url) + + group = get_object_or_404(Group, id=group_id) + obj = get_object_or_404(self.get_queryset(request), pk=object_pk) + form_class = self.get_obj_perms_manage_group_form(request) + form = form_class(group, obj, request.POST or None) + + if request.method == 'POST' and form.is_valid(): + form.save_obj_perms() + msg = gettext("Permissions saved.") + messages.success(request, msg) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) +~~ url = reverse( + '%s:%s_%s_permissions_manage_group' % info, + args=[obj.pk, group.id] + ) + return redirect(url) + + context = self.get_obj_perms_base_context(request, obj) + context['group_obj'] = group + context['group_perms'] = get_group_perms(group, obj) + context['form'] = form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_group_template(), context) + + def get_obj_perms_manage_group_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage_group.html' + return self.obj_perms_manage_group_template + + def get_obj_perms_manage_group_form(self, request): + return AdminGroupObjectPermissionsForm + + +class GuardedModelAdmin(GuardedModelAdminMixin, admin.ModelAdmin): + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 9 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / admin.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./admin.py) + +```python +# admin.py +from datetime import datetime + +import django +from django import forms +from django.conf import settings +from django.conf.urls import url +from django.contrib import admin, messages +from django.contrib.admin.models import ADDITION, CHANGE, DELETION, LogEntry +from django.contrib.auth import get_permission_codename +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import PermissionDenied +from django.http import HttpResponse, HttpResponseRedirect +from django.template.response import TemplateResponse +~~from django.urls import reverse +from django.utils.decorators import method_decorator +from django.utils.encoding import force_str +from django.utils.module_loading import import_string +from django.utils.translation import gettext_lazy as _ +from django.views.decorators.http import require_POST + +from .formats.base_formats import DEFAULT_FORMATS +from .forms import ConfirmImportForm, ExportForm, ImportForm, export_action_form_factory +from .resources import modelresource_factory +from .results import RowResult +from .signals import post_export, post_import +from .tmp_storages import TempFolderStorage + +SKIP_ADMIN_LOG = getattr(settings, 'IMPORT_EXPORT_SKIP_ADMIN_LOG', False) +TMP_STORAGE_CLASS = getattr(settings, 'IMPORT_EXPORT_TMP_STORAGE_CLASS', + TempFolderStorage) + + +if isinstance(TMP_STORAGE_CLASS, str): + TMP_STORAGE_CLASS = import_string(TMP_STORAGE_CLASS) + + +class ImportExportMixinBase: + def get_model_info(self): + + +## ... source file abbreviated to get to reverse examples ... + + + + result = self.process_dataset(dataset, confirm_form, request, *args, **kwargs) + + tmp_storage.remove() + + return self.process_result(result, request) + + def process_dataset(self, dataset, confirm_form, request, *args, **kwargs): + + res_kwargs = self.get_import_resource_kwargs(request, form=confirm_form, *args, **kwargs) + resource = self.get_import_resource_class()(**res_kwargs) + + imp_kwargs = self.get_import_data_kwargs(request, form=confirm_form, *args, **kwargs) + return resource.import_data(dataset, + dry_run=False, + raise_errors=True, + file_name=confirm_form.cleaned_data['original_file_name'], + user=request.user, + **imp_kwargs) + + def process_result(self, result, request): + self.generate_log_entries(result, request) + self.add_success_message(result, request) + post_import.send(sender=None, model=self.model) + +~~ url = reverse('admin:%s_%s_changelist' % self.get_model_info(), + current_app=self.admin_site.name) + return HttpResponseRedirect(url) + + def generate_log_entries(self, result, request): + if not self.get_skip_admin_log(): + logentry_map = { + RowResult.IMPORT_TYPE_NEW: ADDITION, + RowResult.IMPORT_TYPE_UPDATE: CHANGE, + RowResult.IMPORT_TYPE_DELETE: DELETION, + } + content_type_id = ContentType.objects.get_for_model(self.model).pk + for row in result: + if row.import_type != row.IMPORT_TYPE_ERROR and row.import_type != row.IMPORT_TYPE_SKIP: + LogEntry.objects.log_action( + user_id=request.user.pk, + content_type_id=content_type_id, + object_id=row.object_id, + object_repr=row.object_repr, + action_flag=logentry_map[row.import_type], + change_message=_("%s through import_export" % row.import_type), + ) + + def add_success_message(self, result, request): + opts = self.model._meta + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 10 from django-inline-actions +[django-inline-actions](https://github.com/escaped/django-inline-actions) +([PyPI package information](https://pypi.org/project/django-inline-actions/)) +is an extension that adds actions to the [Django](/django.html) +Admin InlineModelAdmin and ModelAdmin changelists. The project is open +sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/escaped/django-inline-actions/blob/master/LICENSE). + +[**django-inline-actions / inline_actions / actions.py**](https://github.com/escaped/django-inline-actions/blob/master/inline_actions/./actions.py) + +```python +# actions.py +from django.contrib import messages +from django.shortcuts import redirect +~~from django.urls import reverse +from django.utils.translation import ugettext_lazy as _ + + +class ViewAction: + inline_actions = ['view_action'] + + def view_action(self, request, obj, parent_obj=None): +~~ url = reverse( + 'admin:{}_{}_change'.format( + obj._meta.app_label, + obj._meta.model_name, + ), + args=(obj.pk,) + ) + return redirect(url) + view_action.short_description = _("View") + + +class DeleteAction: + def get_inline_actions(self, request, obj=None): + actions = super().get_inline_actions(request, obj) + if self.has_delete_permission(request, obj): + actions.append('delete_action') + return actions + + def delete_action(self, request, obj, parent_obj=None): + if self.has_delete_permission(request): + obj.delete() + messages.info(request, "`{}` deleted.".format(obj)) + delete_action.short_description = _("Delete") + + + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 11 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / utils.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./utils.py) + +```python +# utils.py +import datetime +import json +from django.template import Context +from django.utils import translation +from jet import settings +from jet.models import PinnedApplication + +try: + from django.apps.registry import apps +except ImportError: + try: + from django.apps import apps # Fix Django 1.7 import issue + except ImportError: + pass +from django.core.serializers.json import DjangoJSONEncoder +from django.http import HttpResponse +try: + from django.core.urlresolvers import reverse, resolve, NoReverseMatch +except ImportError: # Django 1.11 +~~ from django.urls import reverse, resolve, NoReverseMatch + +from django.contrib.admin import AdminSite +from django.utils.encoding import smart_text +from django.utils.text import capfirst +from django.contrib import messages +from django.utils.encoding import force_text +from django.utils.functional import Promise +from django.contrib.admin.options import IncorrectLookupParameters +from django.contrib import admin +from django.utils.translation import ugettext_lazy as _ +from django.utils.text import slugify + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # Python 2.6 + + +class JsonResponse(HttpResponse): + + def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs): + if safe and not isinstance(data, dict): + raise TypeError('In order to allow non-dict objects to be ' + 'serialized set the safe parameter to False') + + +## ... source file abbreviated to get to reverse examples ... + + +def get_app_list(context, order=True): + admin_site = get_admin_site(context) + request = context['request'] + + app_dict = {} + for model, model_admin in admin_site._registry.items(): + app_label = model._meta.app_label + try: + has_module_perms = model_admin.has_module_permission(request) + except AttributeError: + has_module_perms = request.user.has_module_perms(app_label) # Fix Django < 1.8 issue + + if has_module_perms: + perms = model_admin.get_model_perms(request) + + if True in perms.values(): + info = (app_label, model._meta.model_name) + model_dict = { + 'name': capfirst(model._meta.verbose_name_plural), + 'object_name': model._meta.object_name, + 'perms': perms, + 'model_name': model._meta.model_name + } + if perms.get('change', False): + try: +~~ model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=admin_site.name) + except NoReverseMatch: + pass + if perms.get('add', False): + try: +~~ model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=admin_site.name) + except NoReverseMatch: + pass + if app_label in app_dict: + app_dict[app_label]['models'].append(model_dict) + else: + try: + name = apps.get_app_config(app_label).verbose_name + except NameError: + name = app_label.title() + app_dict[app_label] = { + 'name': name, + 'app_label': app_label, +~~ 'app_url': reverse( + 'admin:app_list', + kwargs={'app_label': app_label}, + current_app=admin_site.name, + ), + 'has_module_perms': has_module_perms, + 'models': [model_dict], + } + + app_list = list(app_dict.values()) + + if order: + app_list.sort(key=lambda x: x['name'].lower()) + + for app in app_list: + app['models'].sort(key=lambda x: x['name']) + + return app_list + + +def get_admin_site(context): + try: + current_resolver = resolve(context.get('request').path) + index_resolver = resolve(reverse('%s:index' % current_resolver.namespaces[0])) + + + +## ... source file abbreviated to get to reverse examples ... + + + return instance.related_label() + return smart_text(instance) + + +class SuccessMessageMixin(object): + success_message = '' + + def form_valid(self, form): + response = super(SuccessMessageMixin, self).form_valid(form) + success_message = self.get_success_message(form.cleaned_data) + if success_message: + messages.success(self.request, success_message) + return response + + def get_success_message(self, cleaned_data): + return self.success_message % cleaned_data + + +def get_model_queryset(admin_site, model, request, preserved_filters=None): + model_admin = admin_site._registry.get(model) + + if model_admin is None: + return + + try: +~~ changelist_url = reverse('%s:%s_%s_changelist' % ( + admin_site.name, + model._meta.app_label, + model._meta.model_name + )) + except NoReverseMatch: + return + + changelist_filters = None + + if preserved_filters: + changelist_filters = preserved_filters.get('_changelist_filters') + + if changelist_filters: + changelist_url += '?' + changelist_filters + + if model_admin: + queryset = model_admin.get_queryset(request) + else: + queryset = model.objects + + list_display = model_admin.get_list_display(request) + list_display_links = model_admin.get_list_display_links(request, list_display) + list_filter = model_admin.get_list_filter(request) + search_fields = model_admin.get_search_fields(request) \ + + +## ... source file abbreviated to get to reverse examples ... + + + 'url': model.get('admin_url'), + 'url_blank': False, + 'name': model['model_name'], + 'object_name': model['object_name'], + 'label': model.get('name', model['object_name']), + 'has_perms': any(model.get('perms', {}).values()), + }, app['models'])), + 'pinned': app['app_label'] in pinned_apps, + 'custom': False + }, original_app_list) + + +def get_menu_item_url(url, original_app_list): + if isinstance(url, dict): + url_type = url.get('type') + + if url_type == 'app': + return original_app_list[url['app_label']]['url'] + elif url_type == 'model': + models = dict(map( + lambda x: (x['name'], x['url']), + original_app_list[url['app_label']]['models'] + )) + return models[url['model']] + elif url_type == 'reverse': +~~ return reverse(url['name'], args=url.get('args'), kwargs=url.get('kwargs')) + elif isinstance(url, str): + return url + + +def get_menu_items(context): + pinned_apps = PinnedApplication.objects.filter(user=context['user'].pk).values_list('app_label', flat=True) + original_app_list = OrderedDict(map(lambda app: (app['app_label'], app), get_original_menu_items(context))) + custom_app_list = settings.JET_SIDE_MENU_ITEMS + custom_app_list_deprecated = settings.JET_SIDE_MENU_CUSTOM_APPS + + if custom_app_list not in (None, False): + if isinstance(custom_app_list, dict): + admin_site = get_admin_site(context) + custom_app_list = custom_app_list.get(admin_site.name, []) + + app_list = [] + + def get_menu_item_app_model(app_label, data): + item = {'has_perms': True} + + if 'name' in data: + parts = data['name'].split('.', 2) + + if len(parts) > 1: + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 12 from django-loginas +[django-loginas](https://github.com/skorokithakis/django-loginas) +([PyPI package information](https://pypi.org/project/django-loginas/)) +is [Django](/django.html) code library for admins to log into an application +as another user, typically for debugging purposes. + +django-loginas is open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/skorokithakis/django-loginas/blob/master/LICENSE). + +[**django-loginas / loginas / tests / tests.py**](https://github.com/skorokithakis/django-loginas/blob/master/loginas/tests/tests.py) + +```python +# tests.py +from __future__ import absolute_import, print_function, unicode_literals + +import unittest +from datetime import timedelta + +import django +from django.conf import settings as django_settings +from django.contrib.auth.models import User +from django.contrib.messages.storage.cookie import CookieStorage +from django.core.exceptions import ImproperlyConfigured, PermissionDenied +from django.test import Client, TestCase +from django.test.utils import override_settings as override_settings_orig +from django.utils import timezone +from loginas import settings as la_settings + +try: + from django.core.urlresolvers import reverse +except ImportError: +~~ from django.urls import reverse + +try: + from urllib.parse import urlsplit +except ImportError: + from urlparse import urlsplit # type: ignore + + +try: + import imp + + reload = imp.reload # @ReservedAssignment +except ImportError: + pass + + +class override_settings(override_settings_orig): + + def enable(self): + super(override_settings, self).enable() + from loginas import settings as loginas_settings + + reload(loginas_settings) + + def disable(self): + + +## ... source file abbreviated to get to reverse examples ... + + + raise PermissionDenied("You can't login as target user") + + +class WrongAuthBackend: + + def authenticate(self, *args, **kwargs): + return None + + +class ViewTest(TestCase): + + + def setUp(self): + self.client = Client(enforce_csrf_checks=True) + self.client.get("/") # To get the CSRF token for next request + assert django_settings.CSRF_COOKIE_NAME in self.client.cookies + self.target_user = User.objects.create(username="target") + + def get_csrf_token_payload(self): + return {"csrfmiddlewaretoken": self.client.cookies[django_settings.CSRF_COOKIE_NAME].value} + + def get_target_url(self, target_user=None): + if target_user is None: + target_user = self.target_user + response = self.client.post( +~~ reverse("loginas-user-login", kwargs={"user_id": target_user.id}), data=self.get_csrf_token_payload() + ) + self.assertEqual(response.status_code, 302) + return response + + def assertCurrentUserIs(self, user): + id_ = str(user.id if user is not None else None).encode("utf-8") + r = self.client.post(reverse("current_user"), data=self.get_csrf_token_payload()) + self.assertEqual(r.content, id_) + + def assertLoginError(self, resp, message=None): + self.assertEqual(urlsplit(resp["Location"])[2], "/") + message = message or "You do not have permission to do that." + messages = CookieStorage(resp)._decode(resp.cookies["messages"].value) + self.assertIn((40, message), [(m.level, m.message) for m in messages]) + + def assertLoginSuccess(self, resp, user): + self.assertEqual(urlsplit(resp["Location"])[2], django_settings.LOGIN_REDIRECT_URL) + msg = la_settings.MESSAGE_LOGIN_SWITCH.format(username=user.__dict__[la_settings.USERNAME_FIELD]) + messages = CookieStorage(resp)._decode(resp.cookies["messages"].value) + self.assertIn(msg, "".join([m.message for m in messages])) + + def assertRaisesExact(self, exception, func, *args, **kwargs): + try: + func(*args, **kwargs) + + +## ... source file abbreviated to get to reverse examples ... + + + self.assertCurrentUserIs(user) + + @unittest.skipIf(django.VERSION[:2] < (1, 10), "Django < 1.10 allows to authenticate as inactive user") + def test_auth_backends_user_not_found(self): + superuser = create_user("me", "pass", is_superuser=True, is_staff=True) + self.assertTrue(self.client.login(username="me", password="pass")) + self.assertCurrentUserIs(superuser) + inactive_user = create_user("name", "pass", is_active=False) + with self.settings( + AUTHENTICATION_BACKENDS=("django.contrib.auth.backends.ModelBackend", "tests.WrongAuthBackend") + ): + message = "Could not find an appropriate authentication backend" + self.assertLoginError(self.get_target_url(target_user=inactive_user), message=message) + self.assertCurrentUserIs(superuser) + + @override_settings(CAN_LOGIN_AS=can_login_as_always_raise_permission_denied) + def test_can_login_as_permission_denied(self): + message = "You can't login as target user" + self.assertLoginError(self.get_target_url(), message=message) + + def test_as_anonymous_user(self): + self.assertLoginError(self.get_target_url()) + self.assertCurrentUserIs(None) + + def test_get_405_method_not_allowed(self): +~~ url = reverse("loginas-user-login", kwargs={"user_id": "0"}) + r = self.client.get(url) + self.assertEqual(r.status_code, 405) + + def test_missing_csrf_token_403_forbidden(self): +~~ url = reverse("loginas-user-login", kwargs={"user_id": "0"}) + r = self.client.post(url) + self.assertEqual(r.status_code, 403) + + @override_settings(LOGINAS_REDIRECT_URL="/another-redirect") + def test_loginas_redirect_url(self): + create_user("me", "pass", is_superuser=True, is_staff=True) + self.assertTrue(self.client.login(username="me", password="pass")) + + response = self.client.post( +~~ reverse("loginas-user-login", kwargs={"user_id": self.target_user.id}), data=self.get_csrf_token_payload() + ) + self.assertEqual(response.status_code, 302) + self.assertEqual(urlsplit(response["Location"])[2], "/another-redirect") + + def test_restore_original_user(self): + + original_user = create_user("me", "pass", is_superuser=True, is_staff=True) + self.assertTrue(self.client.login(username="me", password="pass")) + response = self.get_target_url() + self.assertLoginSuccess(response, self.target_user) + +~~ url = reverse("loginas-user-login", kwargs={"user_id": self.target_user.id}) + self.client.get(url) + self.assertCurrentUserIs(self.target_user) + +~~ url = reverse("loginas-logout") + self.client.get(url) + self.assertCurrentUserIs(original_user) + + @override_settings(LOGINAS_LOGOUT_REDIRECT_URL="/another-redirect") + def test_loginas_redirect_url_again(self): + create_user("me", "pass", is_superuser=True, is_staff=True) + self.assertTrue(self.client.login(username="me", password="pass")) + response = self.client.get(reverse("loginas-logout")) + self.assertEqual(response.status_code, 302) + self.assertEqual(urlsplit(response["Location"])[2], "/another-redirect") + + def test_last_login_not_updated(self): + last_login = timezone.now() - timedelta(hours=1) + self.target_user.last_login = last_login + self.target_user.save() + create_user("me", "pass", is_superuser=True, is_staff=True) + self.assertTrue(self.client.login(username="me", password="pass")) + response = self.get_target_url() + self.assertLoginSuccess(response, self.target_user) + self.assertCurrentUserIs(self.target_user) + target_user = User.objects.get(id=self.target_user.id) # refresh from db + self.assertEqual(target_user.last_login, last_login) + + @override_settings(LOGINAS_UPDATE_LAST_LOGIN=True) + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 13 from django-mongonaut +[django-mongonaut](https://github.com/jazzband/django-mongonaut) +([project documentation](https://django-mongonaut.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-mongonaut/)) +provides an introspective interface for working with +[MongoDB](/mongodb.html) via mongoengine. The project has its own new code +to map MongoDB to the [Django](/django.html) Admin interface. + +django-mongonaut's highlighted features include automatic introspection of +mongoengine documents, the ability to constrain who sees what and what +they can do and full control for adding, editing and deleting documents. + +The django-mongonaut project is open sourced under the +[MIT License](https://github.com/jazzband/django-mongonaut/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-mongonaut / mongonaut / views.py**](https://github.com/jazzband/django-mongonaut/blob/master/mongonaut/./views.py) + +```python +# views.py +import math + +from django.contrib import messages +~~from django.urls import reverse +from django.forms import Form +from django.http import HttpResponseForbidden +from django.http import Http404 +from django.utils.functional import cached_property +from django.views.generic.edit import DeletionMixin +from django.views.generic import ListView +from django.views.generic import TemplateView +from django.views.generic.edit import FormView +from mongoengine.fields import EmbeddedDocumentField, ListField + +from mongonaut.forms import MongoModelForm +from mongonaut.mixins import MongonautFormViewMixin +from mongonaut.mixins import MongonautViewMixin +from mongonaut.utils import is_valid_object_id + + +class IndexView(MongonautViewMixin, ListView): + + template_name = "mongonaut/index.html" + queryset = [] + permission = 'has_view_permission' + + def get_queryset(self): + return self.get_mongoadmins() + + +## ... source file abbreviated to get to reverse examples ... + + + context['app_label'] = self.app_label + context['document_name'] = self.document_name + context['keys'] = ['id', ] + context['embedded_documents'] = [] + context['list_fields'] = [] + for key in sorted([x for x in self.document._fields.keys() if x != 'id']): + if isinstance(self.document._fields[key], EmbeddedDocumentField): + context['embedded_documents'].append(key) + continue + if isinstance(self.document._fields[key], ListField): + context['list_fields'].append(key) + continue + context['keys'].append(key) + return context + + +class DocumentEditFormView(MongonautViewMixin, FormView, MongonautFormViewMixin): + + template_name = "mongonaut/document_edit_form.html" + form_class = Form + success_url = '/' + permission = 'has_edit_permission' + + def get_success_url(self): + self.set_mongonaut_base() +~~ return reverse('document_detail_edit_form', kwargs={'app_label': self.app_label, 'document_name': self.document_name, 'id': self.kwargs.get('id')}) + + def get_context_data(self, **kwargs): + context = super(DocumentEditFormView, self).get_context_data(**kwargs) + self.set_mongoadmin() + context = self.set_permissions_in_context(context) + self.document_type = getattr(self.models, self.document_name) + self.ident = self.kwargs.get('id') + self.document = self.document_type.objects.get(pk=self.ident) + + context['document'] = self.document + context['app_label'] = self.app_label + context['document_name'] = self.document_name +~~ context['form_action'] = reverse('document_detail_edit_form', args=[self.kwargs.get('app_label'), + self.kwargs.get('document_name'), + self.kwargs.get('id')]) + + return context + + def get_form(self): #get_form(self, Form) leads to "get_form() missing 1 required positional argument: 'Form'" error." + self.set_mongoadmin() + context = self.set_permissions_in_context({}) + + if not context['has_edit_permission']: + return HttpResponseForbidden("You do not have permissions to edit this content.") + + self.document_type = getattr(self.models, self.document_name) + self.ident = self.kwargs.get('id') + try: + self.document = self.document_type.objects.get(pk=self.ident) + except self.document_type.DoesNotExist: + raise Http404 + self.form = Form() + + if self.request.method == 'POST': + self.form = self.process_post_form('Your changes have been saved.') + else: + self.form = MongoModelForm(model=self.document_type, instance=self.document).get_form() + return self.form + + +class DocumentAddFormView(MongonautViewMixin, FormView, MongonautFormViewMixin): + + template_name = "mongonaut/document_add_form.html" + form_class = Form + success_url = '/' + permission = 'has_add_permission' + + def get_success_url(self): + self.set_mongonaut_base() +~~ return reverse('document_detail', kwargs={'app_label': self.app_label, 'document_name': self.document_name, 'id': str(self.new_document.id)}) + + def get_context_data(self, **kwargs): + context = super(DocumentAddFormView, self).get_context_data(**kwargs) + self.set_mongoadmin() + context = self.set_permissions_in_context(context) + self.document_type = getattr(self.models, self.document_name) + + context['app_label'] = self.app_label + context['document_name'] = self.document_name +~~ context['form_action'] = reverse('document_detail_add_form', args=[self.kwargs.get('app_label'), + self.kwargs.get('document_name')]) + + return context + + def get_form(self): + self.set_mongonaut_base() + self.document_type = getattr(self.models, self.document_name) + self.form = Form() + + if self.request.method == 'POST': + self.form = self.process_post_form('Your new document has been added and saved.') + else: + self.form = MongoModelForm(model=self.document_type).get_form() + return self.form + + +class DocumentDeleteView(DeletionMixin, MongonautViewMixin, TemplateView): + + success_url = "/" + template_name = "mongonaut/document_delete.html" + + def get_success_url(self): + self.set_mongonaut_base() + messages.add_message(self.request, messages.INFO, 'Your document has been deleted.') +~~ return reverse('document_list', kwargs={'app_label': self.app_label, 'document_name': self.document_name}) + + def get_object(self): + self.set_mongoadmin() + self.document_type = getattr(self.models, self.document_name) + self.ident = self.kwargs.get('id') + self.document = self.document_type.objects.get(pk=self.ident) + return self.document + + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 14 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / models.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./models.py) + +```python +# models.py +import logging +from datetime import timedelta +from urllib.parse import parse_qsl, urlparse + +from django.apps import apps +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db import models, transaction +~~from django.urls import reverse +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ + +from .generators import generate_client_id, generate_client_secret +from .scopes import get_scopes_backend +from .settings import oauth2_settings +from .validators import RedirectURIValidator, WildcardSet + + +logger = logging.getLogger(__name__) + + +class AbstractApplication(models.Model): + CLIENT_CONFIDENTIAL = "confidential" + CLIENT_PUBLIC = "public" + CLIENT_TYPES = ( + (CLIENT_CONFIDENTIAL, _("Confidential")), + (CLIENT_PUBLIC, _("Public")), + ) + + GRANT_AUTHORIZATION_CODE = "authorization-code" + GRANT_IMPLICIT = "implicit" + GRANT_PASSWORD = "password" + GRANT_CLIENT_CREDENTIALS = "client-credentials" + + +## ... source file abbreviated to get to reverse examples ... + + + + grant_types = ( + AbstractApplication.GRANT_AUTHORIZATION_CODE, + AbstractApplication.GRANT_IMPLICIT, + ) + + redirect_uris = self.redirect_uris.strip().split() + allowed_schemes = set(s.lower() for s in self.get_allowed_schemes()) + + if redirect_uris: + validator = RedirectURIValidator(WildcardSet()) + for uri in redirect_uris: + validator(uri) + scheme = urlparse(uri).scheme + if scheme not in allowed_schemes: + raise ValidationError(_( + "Unauthorized redirect scheme: {scheme}" + ).format(scheme=scheme)) + + elif self.authorization_grant_type in grant_types: + raise ValidationError(_( + "redirect_uris cannot be empty with grant_type {grant_type}" + ).format(grant_type=self.authorization_grant_type)) + + def get_absolute_url(self): +~~ return reverse("oauth2_provider:detail", args=[str(self.id)]) + + def get_allowed_schemes(self): + return oauth2_settings.ALLOWED_REDIRECT_URI_SCHEMES + + def allows_grant_type(self, *grant_types): + return self.authorization_grant_type in grant_types + + def is_usable(self, request): + return True + + +class ApplicationManager(models.Manager): + def get_by_natural_key(self, client_id): + return self.get(client_id=client_id) + + +class Application(AbstractApplication): + objects = ApplicationManager() + + class Meta(AbstractApplication.Meta): + swappable = "OAUTH2_PROVIDER_APPLICATION_MODEL" + + def natural_key(self): + return (self.client_id,) + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 15 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / reverse.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./reverse.py) + +```python +# reverse.py +from django.urls import NoReverseMatch +~~from django.urls import reverse as django_reverse +from django.utils.functional import lazy + +from rest_framework.settings import api_settings +from rest_framework.utils.urls import replace_query_param + + +def preserve_builtin_query_params(url, request=None): + if request is None: + return url + + overrides = [ + api_settings.URL_FORMAT_OVERRIDE, + ] + + for param in overrides: + if param and (param in request.GET): + value = request.GET[param] + url = replace_query_param(url, param, value) + + return url + + +~~def reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra): + scheme = getattr(request, 'versioning_scheme', None) + if scheme is not None: + try: + url = scheme.reverse(viewname, args, kwargs, request, format, **extra) + except NoReverseMatch: + url = _reverse(viewname, args, kwargs, request, format, **extra) + else: + url = _reverse(viewname, args, kwargs, request, format, **extra) + + return preserve_builtin_query_params(url, request) + + +def _reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra): + if format is not None: + kwargs = kwargs or {} + kwargs['format'] = format + url = django_reverse(viewname, args=args, kwargs=kwargs, **extra) + if request: + return request.build_absolute_uri(url) + return url + + +reverse_lazy = lazy(reverse, str) + + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 16 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / models.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./models.py) + +```python +# models.py +from __future__ import unicode_literals + +import logging +from time import time +import six + +from django.db import models, DatabaseError +try: +~~ from django.urls import reverse +except ImportError: + from django.core.urlresolvers import reverse + +from django.conf import settings + +from explorer import app_settings +from explorer.utils import ( + passes_blacklist, + swap_params, + extract_params, + shared_dict_update, + get_s3_bucket, + get_params_for_url, + get_valid_connection +) + +MSG_FAILED_BLACKLIST = "Query failed the SQL blacklist: %s" + + +logger = logging.getLogger(__name__) + +@six.python_2_unicode_compatible +class Query(models.Model): + title = models.CharField(max_length=255) + + +## ... source file abbreviated to get to reverse examples ... + + + return swap_params(self.sql, self.available_params()) + + def execute_query_only(self): + return QueryResult(self.final_sql(), get_valid_connection(self.connection)) + + def execute_with_logging(self, executing_user): + ql = self.log(executing_user) + ret = self.execute() + ql.duration = ret.duration + ql.save() + return ret, ql + + def execute(self): + ret = self.execute_query_only() + ret.process() + return ret + + def available_params(self): + + p = extract_params(self.sql) + if self.params: + shared_dict_update(p, self.params) + return p + + def get_absolute_url(self): +~~ return reverse("query_detail", kwargs={'query_id': self.id}) + + @property + def params_for_url(self): + return get_params_for_url(self) + + def log(self, user=None): + if user: + try: + is_anonymous = user.is_anonymous() + except TypeError: + is_anonymous = user.is_anonymous + if is_anonymous: + user = None + ql = QueryLog(sql=self.final_sql(), query_id=self.id, run_by_user=user, connection=self.connection) + ql.save() + return ql + + @property + def shared(self): + return self.id in set(sum(app_settings.EXPLORER_GET_USER_QUERY_VIEWS().values(), [])) + + @property + def snapshots(self): + if app_settings.ENABLE_TASKS: + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 17 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / columns / base.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/columns/base.py) + +```python +# base.py +from collections import OrderedDict +from itertools import islice + +from django.core.exceptions import ImproperlyConfigured +~~from django.urls import reverse +from django.utils.html import format_html +from django.utils.safestring import SafeData +from django.utils.text import capfirst + +from ..utils import ( + Accessor, + AttributeDict, + OrderBy, + OrderByTuple, + call_with_appropriate, + computed_values, +) + + +class Library: + + def __init__(self): + self.columns = [] + + def register(self, column): + if not hasattr(column, "from_field"): + raise ImproperlyConfigured( + "{} is not a subclass of Column".format(column.__class__.__name__) + ) + + +## ... source file abbreviated to get to reverse examples ... + + + "for linkify=True, '{}' must have a method get_absolute_url".format( + str(context) + ) + ) + return context.get_absolute_url() + + def call_reverse(self, record): + + def resolve_if_accessor(val): + return val.resolve(record) if isinstance(val, Accessor) else val + + params = self.reverse_args.copy() + + params["viewname"] = resolve_if_accessor(params["viewname"]) + if params.get("urlconf", None): + params["urlconf"] = resolve_if_accessor(params["urlconf"]) + if params.get("args", None): + params["args"] = [resolve_if_accessor(a) for a in params["args"]] + if params.get("kwargs", None): + params["kwargs"] = { + key: resolve_if_accessor(val) for key, val in params["kwargs"].items() + } + if params.get("current_app", None): + params["current_app"] = resolve_if_accessor(params["current_app"]) + +~~ return reverse(**params) + + def get_attrs(self, **kwargs): + attrs = AttributeDict(self.attrs or {}) + attrs["href"] = self.compose_url(**kwargs) + + return attrs + + def __call__(self, content, **kwargs): + attrs = self.get_attrs(**kwargs) + if attrs["href"] is None: + return content + + return format_html("{}", attrs.as_html(), content) + + +@library.register +class Column: + + creation_counter = 0 + empty_values = (None, "") + + link = None + + _explicit = False + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 18 from django-webshell +[django-webshell](https://github.com/onrik/django-webshell) is an extension +for executing arbitrary code in the +[Django admin](https://docs.djangoproject.com/en/stable/ref/contrib/admin/), +similar to how you can run code by using the `django manage.py shell` +command from the terminal. + +The django-webshell project is provided as open source under the +[MIT license](https://github.com/onrik/django-webshell/blob/master/LICENSE). + +[**django-webshell / webshell / tests.py**](https://github.com/onrik/django-webshell/blob/master/webshell/./tests.py) + +```python +# tests.py +from django.test import TestCase +from django.conf import settings +from django.contrib.auth import get_user_model +try: + from django.core.urlresolvers import reverse +except ImportError: +~~ from django.urls import reverse + +from webshell.models import Script + +User = get_user_model() + + +class WebshellTestCase(TestCase): + def setUp(self): + self.user = User.objects.create( + username='user', is_staff=True, is_superuser=True) + self.user.set_password('123456') + self.user.save() +~~ self.url = reverse('execute-script') + self.login_url = '%s?next=%s' % (settings.LOGIN_URL, self.url) + + def login(self): + self.assertTrue(self.client.login( + username=self.user.username, password='123456')) + + def test_wrong_method(self): + response = self.client.get(self.url) + self.assertEqual(response.status_code, 405) + + def test_login_required(self): + response = self.client.post(self.url) + self.assertRedirects(response, self.login_url, 302, 404) + + def test_superuser_required(self): + self.user.is_superuser = False + self.user.save() + self.login() + response = self.client.post(self.url) + self.assertRedirects(response, self.login_url, 302, 404) + + def test_success(self): + self.login() + + response = self.client.post(self.url, data={'source': 'print(1)'}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.content, b'1\n') + + def test_success_exception(self): + self.login() + + response = self.client.post(self.url, data={'source': '[1][1]'}) + self.assertEqual(response.status_code, 200) + self.assertIn(b'IndexError: list index out of range', response.content) + + def test_admin(self): + self.login() + + script = Script.objects.create(name='Test') + + urls = ( +~~ reverse('admin:webshell_script_add'), +~~ reverse('admin:webshell_script_change', args=[script.id]), +~~ reverse('admin:webshell_script_changelist'), + ) + + for url in urls: + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 19 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / decorators.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./decorators.py) + +```python +# decorators.py +from functools import wraps + +from django.http import HttpResponseForbidden +from django.http import HttpResponseNotFound +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.template.loader import render_to_string +~~from django.urls import reverse +from django.utils.http import urlquote +from wiki.conf import settings +from wiki.core.exceptions import NoRootURL + + +def response_forbidden(request, article, urlpath, read_denied=False): + if request.user.is_anonymous: + qs = request.META.get("QUERY_STRING", "") + if qs: + qs = urlquote("?" + qs) + else: + qs = "" + return redirect(settings.LOGIN_URL + "?next=" + request.path + qs) + else: + return HttpResponseForbidden( + render_to_string( + "wiki/permission_denied.html", + context={ + "article": article, + "urlpath": urlpath, + "read_denied": read_denied, + }, + request=request, + ) + + +## ... source file abbreviated to get to reverse examples ... + + + can_write=False, + deleted_contents=False, + not_locked=False, + can_delete=False, + can_moderate=False, + can_create=False, +): + + def wrapper(request, *args, **kwargs): + from . import models + + path = kwargs.pop("path", None) + article_id = kwargs.pop("article_id", None) + + if path is not None: + try: + urlpath = models.URLPath.get_by_path(path, select_related=True) + except NoRootURL: + return redirect("wiki:root_create") + except models.URLPath.DoesNotExist: + try: + pathlist = list(filter(lambda x: x != "", path.split("/"),)) + path = "/".join(pathlist[:-1]) + parent = models.URLPath.get_by_path(path) + return HttpResponseRedirect( +~~ reverse("wiki:create", kwargs={"path": parent.path}) + + "?slug=%s" % pathlist[-1].lower() + ) + except models.URLPath.DoesNotExist: + return HttpResponseNotFound( + render_to_string( + "wiki/error.html", + context={"error_type": "ancestors_missing"}, + request=request, + ) + ) + if urlpath.article: + article = urlpath.article + else: +~~ return_url = reverse("wiki:get", kwargs={"path": urlpath.parent.path}) + urlpath.delete() + return HttpResponseRedirect(return_url) + + elif article_id: + articles = models.Article.objects + + article = get_object_or_404(articles, id=article_id) + try: + urlpath = models.URLPath.objects.get(articles__article=article) + except ( + models.URLPath.DoesNotExist, + models.URLPath.MultipleObjectsReturned, + ): + urlpath = None + + else: + raise TypeError("You should specify either article_id or path") + + if not deleted_contents: + if urlpath: + if urlpath.is_deleted(): # This also checks all ancestors + return redirect("wiki:deleted", path=urlpath.path) + else: + if article.current_revision and article.current_revision.deleted: + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 20 from graphite-web +[Graphite](https://github.com/graphite-project/graphite-web) +([project website](http://graphiteapp.org/), +[documentation](https://graphite.readthedocs.io/en/latest/) and +[PyPI package information](https://pypi.org/project/graphite-web/)) +is a metrics collection and visualization tool, built with both +Python and JavaScript. Metrics are collected by a Node.js application +and displayed using a [Django](/django.html) web application, +called "Graphite-Web", which is one of three core projects under +the Graphite umbrella (the other two are +[Carbon](https://github.com/graphite-project/carbon) and +[Whisper](https://github.com/graphite-project/whisper)). + +Graphite is provided as open sourced under the +[Apache License 2.0](https://github.com/graphite-project/whisper/blob/master/LICENSE). + +[**graphite-web / webapp / tests / test_metrics.py**](https://github.com/graphite-project/graphite-web/blob/master/webapp/tests/test_metrics.py) + +```python +# test_metrics.py +import copy +import os +import shutil +import time + +from mock import patch + +from django.conf import settings +try: +~~ from django.urls import reverse +except ImportError: # Django < 1.10 + from django.core.urlresolvers import reverse +from .base import TestCase + +import whisper + +from graphite.util import unpickle, msgpack, json + + +class MetricsTester(TestCase): + db = os.path.join(settings.WHISPER_DIR, 'test.wsp') + hostcpu = os.path.join(settings.WHISPER_DIR, 'hosts/hostname/cpu.wsp') + + def wipe_whisper(self): + try: + os.remove(self.db) + except OSError: + pass + + def create_whisper_hosts(self, ts=None): + worker1 = self.hostcpu.replace('hostname', 'worker1') + worker2 = self.hostcpu.replace('hostname', 'worker2') + try: + os.makedirs(worker1.replace('cpu.wsp', '')) + os.makedirs(worker2.replace('cpu.wsp', '')) + except OSError: + pass + + whisper.create(worker1, [(1, 60)]) + whisper.create(worker2, [(1, 60)]) + + ts = ts or int(time.time()) + whisper.update(worker1, 1, ts) + whisper.update(worker2, 2, ts) + + def wipe_whisper_hosts(self): + try: + os.remove(self.hostcpu.replace('hostname', 'worker1')) + os.remove(self.hostcpu.replace('hostname', 'worker2')) + shutil.rmtree(self.hostcpu.replace('hostname/cpu.wsp', '')) + except OSError: + pass + + def test_index_json(self): + self.create_whisper_hosts() + self.addCleanup(self.wipe_whisper_hosts) + +~~ url = reverse('metrics_index') + + request = {} + response = self.client.post(url, request) + self.assertEqual(response.status_code, 200) + data = json.loads(response.content) + self.assertEqual(data[0], 'hosts.worker1.cpu') + self.assertEqual(data[1], 'hosts.worker2.cpu') + + + request = {'jsonp': 'callback'} + response = self.client.post(url, request) + self.assertEqual(response.status_code, 200) + data = json.loads(response.content.split(b"(")[1].strip(b")")) + self.assertEqual(data[0], 'hosts.worker1.cpu') + self.assertEqual(data[1], 'hosts.worker2.cpu') + + def mock_STORE_get_index(self, requestContext=None): + raise Exception('test') + + with patch('graphite.metrics.views.STORE.get_index', mock_STORE_get_index): + request = {} + response = self.client.post(url, request) + self.assertEqual(response.status_code, 500) + data = json.loads(response.content) + self.assertEqual(data, []) + + def test_find_view(self): + ts = int(time.time()) + + self.create_whisper_hosts(ts) + self.addCleanup(self.wipe_whisper_hosts) + +~~ url = reverse('metrics_find') + + response = self.client.post(url, {}) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.content, b"Bad Request: Missing required parameter 'query'") + + response = self.client.post(url, { + 'query': '*', + 'from': 'now-1h', + 'until': 'now-2h', + }) + self.assertEqual(response.status_code, 400) + self.assertRegex(response.content, b"^Bad Request: Failed to instantiate find query: Invalid interval start=[0-9]+ end=[0-9]+$") + + response = self.client.post(url, { + 'query': '*', + 'wildcards': '123a', + }) + self.assertEqual(response.status_code, 400) + self.assertRegex(response.content, b"^Bad Request: Invalid int value u?'123a' for param wildcards: invalid literal for int\\(\\) with base 10: u?'123a'$") + + response = self.client.post(url, { + 'query': '*', + 'from': 'now-1mmminute', # "mmminute" is misspelled + }) + + +## ... source file abbreviated to get to reverse examples ... + + + + request['query']='hosts.*.cpu' + content = test_find_view_basics(request) + data = json.loads(content.split(b"(")[1].strip(b")")) + self.assertEqual(len(data), 2) + + self.assertEqual(data[0]['path'], 'hosts.worker1.cpu') + self.assertEqual(data[0]['is_leaf'], True) + self.assertEqual(len(data[0]['intervals']), 1) + self.assertIn(int(data[0]['intervals'][0]['end']), [ts, ts - 1]) + + self.assertEqual(data[1]['path'], 'hosts.worker2.cpu') + self.assertEqual(data[1]['is_leaf'], True) + self.assertEqual(len(data[1]['intervals']), 1) + self.assertIn(int(data[1]['intervals'][0]['end']), [ts, ts - 1]) + + request['query']='other' + content = test_find_view_basics(request) + data = json.loads(content.split(b"(")[1].strip(b")")) + self.assertEqual(data, []) + + def test_expand_view(self): + self.create_whisper_hosts() + self.addCleanup(self.wipe_whisper_hosts) + +~~ url = reverse('metrics_expand') + + request = {'query': '*'} + response = self.client.post(url, request) + self.assertEqual(response.status_code, 200) + data = json.loads(response.content) + self.assertEqual(data['results'], [u'hosts']) + + request = {'query': ''} + response = self.client.post(url, request) + self.assertEqual(response.status_code, 200) + data = json.loads(response.content) + self.assertEqual(data['results'], [u'']) + + def test_get_metadata_view(self): + self.create_whisper_hosts() + self.addCleanup(self.wipe_whisper_hosts) + +~~ url = reverse('metrics_get_metadata') + + request = {'metric': 'hosts.worker1.cpu', 'key': 'a'} + response = self.client.post(url, request) + self.assertEqual(response.status_code, 200) + data = json.loads(response.content) + self.assertEqual(data['hosts.worker1.cpu']['error'], "Unexpected error occurred in CarbonLink.get_metadata(hosts.worker1.cpu, a)") + + def test_set_metadata_view(self): + self.create_whisper_hosts() + self.addCleanup(self.wipe_whisper_hosts) + +~~ url = reverse('metrics_set_metadata') + + request = {'metric': 'hosts.worker1.cpu', 'key': 'a', 'value': 'b'} + response = self.client.get(url, request) + self.assertEqual(response.status_code, 200) + data = json.loads(response.content) + self.assertEqual(data['hosts.worker1.cpu']['error'], "Unexpected error occurred in CarbonLink.set_metadata(hosts.worker1.cpu, a)") + + request = {'operations': '[{ "metric": "hosts.worker1.cpu", "key": "a", "value": "b" }]'} + response = self.client.post(url, request) + self.assertEqual(response.status_code, 200) + data = json.loads(response.content) + self.assertEqual(data['hosts.worker1.cpu']['error'], "Unexpected error occurred in bulk CarbonLink.set_metadata(hosts.worker1.cpu)") + + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 21 from register +[register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is +open source under the +[GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). +This web application makes it easier for people to register as organ donors. +You can see the application live at +[https://register.organize.org/](https://register.organize.org/). + +[**register / registration / views.py**](https://github.com/ORGAN-IZE/register/blob/master/registration/./views.py) + +```python +# views.py +from __future__ import unicode_literals + +import logging +import collections +import datetime +import json +import random + +import dateutil.parser +import django.contrib.messages +~~import django.urls +import django.http +import django.shortcuts +import django.views.generic.edit +import django.forms +import django.utils +from django.core.cache import cache +from django.conf import settings +from formtools.wizard.forms import ManagementForm +from formtools.wizard.storage import get_storage +from formtools.wizard.views import NamedUrlSessionWizardView +from django.utils.translation import ugettext_lazy as _ +from django.utils.safestring import mark_safe + +from axes import utils +import dateutil.parser + +import cobrand.models +import widget.models +import fiftythree.client +import forms + +logger = logging.getLogger(__name__) + +SESSION_REGISTRATION_CONFIGURATION = 'registration_configuration' + + +## ... source file abbreviated to get to reverse examples ... + + + secure=False, httponly=True) + return response + + +class StateLookupView(MinorRestrictedMixin, django.views.generic.edit.FormView): + template_name = 'registration/start.html' + form_class = forms.StateLookupForm + accepts_registration = True + + def get(self, request, *args, **kwargs): + clean_session(request.session) + clean_next_of_kin_email_session(request.session) + setup_external_source_session(request) + if self.request.GET.get('email') and self.request.GET.get('postal_code'): + email = self.request.GET['email'] + postal_code = self.request.GET['postal_code'] + form = self.form_class(data={'email': email, 'postal_code': postal_code}) + if form.is_valid(): + return self.form_valid(form) + else: + return self.form_invalid(form) + return super(StateLookupView, self).get(request, *args, **kwargs) + + def get_success_url(self): + if self.accepts_registration: +~~ return django.urls.reverse( + 'register', kwargs={'step': '1',}) + else: +~~ return django.urls.reverse('unsupported_state') + + def get_initial(self): + initial = self.initial.copy() + if 'email' in self.request.GET: + initial['email'] = self.request.GET['email'] + if 'postal_code' in self.request.GET: + initial['postal_code'] = self.request.GET['postal_code'] + return initial + + def get_context_data(self, **kwargs): + data = super(StateLookupView, self).get_context_data(**kwargs) + data['update'] = self.is_update + if data['update']: + data['page_title'] = _('Update your registration') + else: + data['page_title'] = _('Let’s Begin...') + + return data + + @property + def is_update(self): + return self.kwargs.get('update') is True + + def submit_email(self, data): + + +## ... source file abbreviated to get to reverse examples ... + + +class WaitingListFilmRedirectView(django.views.generic.RedirectView): + def get_redirect_url(self, *args, **kwargs): + return '/?reg_source=waitinglistfilm' + + +class UnsupportedStateView(django.views.generic.TemplateView): + template_name = 'registration/unsupported_state.html' + + def get(self, request, *args, **kwargs): + redirect_url = self.request.session.get(SESSION_REDIRECT_URL) + if not redirect_url: + return django.shortcuts.redirect('start') + context = self.get_context_data(**kwargs) + context['state'] = self.request.session[SESSION_STATE] + context['state_name'] = self.request.session[SESSION_STATE_NAME] + return self.render_to_response(context) + + +class StateRedirectView(django.views.generic.RedirectView): + def get_redirect_url(self, *args, **kwargs): + redirect_url = self.request.session.get(SESSION_REDIRECT_URL) + clean_session(self.request.session) + if redirect_url: + return redirect_url + else: +~~ return django.urls.reverse('start') + + +class RegistrationWizardView(MinorRestrictedMixin, NamedUrlSessionWizardView): + form_list = [forms.StateLookupForm, ] + page_titles = collections.OrderedDict() + page_fieldsets = collections.OrderedDict() + page_explanatory_texts = collections.OrderedDict() + page_count = 0 + configuration = None + api_error_key = 'api_error' + + def check_configuration(self): + if not self.configuration and (SESSION_REGISTRATION_CONFIGURATION not in self.request.session): + return False + else: + return True + + def process_registration_configuration(self): + self.configuration = self.request.session[SESSION_REGISTRATION_CONFIGURATION] + license_id_formats = None + if SESSION_LICENSE_ID_FORMATS in self.request.session: + license_id_formats = self.request.session[SESSION_LICENSE_ID_FORMATS] + + validate_organ_tissue_selection = False + + +## ... source file continues with no further reverse examples... + +``` + + +## Example 22 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / snippets / models.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/snippets/models.py) + +```python +# models.py +from django.contrib.admin.utils import quote +from django.core import checks +~~from django.urls import reverse + +from wagtail.admin.checks import check_panels_in_model +from wagtail.admin.models import get_object_usage + +SNIPPET_MODELS = [] + + +def get_snippet_models(): + return SNIPPET_MODELS + + +def register_snippet(model): + if model not in SNIPPET_MODELS: + model.get_usage = get_object_usage + model.usage_url = get_snippet_usage_url + SNIPPET_MODELS.append(model) + SNIPPET_MODELS.sort(key=lambda x: x._meta.verbose_name) + + @checks.register('panels') + def modeladmin_model_check(app_configs, **kwargs): + errors = check_panels_in_model(model, 'snippets') + return errors + + return model + + +def get_snippet_usage_url(self): +~~ return reverse('wagtailsnippets:usage', args=( + self._meta.app_label, self._meta.model_name, quote(self.pk))) + + + +## ... source file continues with no further reverse examples... + +``` + diff --git a/content/pages/examples/django/django-urls-urlpattern.markdown b/content/pages/examples/django/django-urls-urlpattern.markdown new file mode 100644 index 000000000..267bba914 --- /dev/null +++ b/content/pages/examples/django/django-urls-urlpattern.markdown @@ -0,0 +1,124 @@ +title: django.urls URLPattern Example Code +category: page +slug: django-urls-urlpattern-examples +sortorder: 500011400 +toc: False +sidebartitle: django.urls URLPattern +meta: Python example code for the URLPattern class from the django.urls module of the Django project. + + +URLPattern is a class within the django.urls module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / schemas / generators.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/schemas/generators.py) + +```python +# generators.py +import re +from importlib import import_module + +from django.conf import settings +from django.contrib.admindocs.views import simplify_regex +from django.core.exceptions import PermissionDenied +from django.http import Http404 +~~from django.urls import URLPattern, URLResolver + +from rest_framework import exceptions +from rest_framework.request import clone_request +from rest_framework.settings import api_settings +from rest_framework.utils.model_meta import _get_pk + + +def get_pk_name(model): + meta = model._meta.concrete_model._meta + return _get_pk(meta).name + + +def is_api_view(callback): + from rest_framework.views import APIView + cls = getattr(callback, 'cls', None) + return (cls is not None) and issubclass(cls, APIView) + + +def endpoint_ordering(endpoint): + path, method, callback = endpoint + method_priority = { + 'GET': 0, + 'POST': 1, + 'PUT': 2, + + +## ... source file abbreviated to get to URLPattern examples ... + + +) + + +class EndpointEnumerator: + def __init__(self, patterns=None, urlconf=None): + if patterns is None: + if urlconf is None: + urlconf = settings.ROOT_URLCONF + + if isinstance(urlconf, str): + urls = import_module(urlconf) + else: + urls = urlconf + patterns = urls.urlpatterns + + self.patterns = patterns + + def get_api_endpoints(self, patterns=None, prefix=''): + if patterns is None: + patterns = self.patterns + + api_endpoints = [] + + for pattern in patterns: + path_regex = prefix + str(pattern.pattern) +~~ if isinstance(pattern, URLPattern): + path = self.get_path_from_regex(path_regex) + callback = pattern.callback + if self.should_include_endpoint(path, callback): + for method in self.get_allowed_methods(callback): + endpoint = (path, method, callback) + api_endpoints.append(endpoint) + + elif isinstance(pattern, URLResolver): + nested_endpoints = self.get_api_endpoints( + patterns=pattern.url_patterns, + prefix=path_regex + ) + api_endpoints.extend(nested_endpoints) + + return sorted(api_endpoints, key=endpoint_ordering) + + def get_path_from_regex(self, path_regex): + + path = simplify_regex(path_regex) + + return re.sub(_PATH_PARAMETER_COMPONENT_RE, r'{\g}', path) + + def should_include_endpoint(self, path, callback): + if not is_api_view(callback): + + +## ... source file continues with no further URLPattern examples... + +``` + diff --git a/content/pages/examples/django/django-urls-urlresolver.markdown b/content/pages/examples/django/django-urls-urlresolver.markdown new file mode 100644 index 000000000..cd80c8c3c --- /dev/null +++ b/content/pages/examples/django/django-urls-urlresolver.markdown @@ -0,0 +1,98 @@ +title: django.urls URLResolver Example Code +category: page +slug: django-urls-urlresolver-examples +sortorder: 500011401 +toc: False +sidebartitle: django.urls URLResolver +meta: Python example code for the URLResolver class from the django.urls module of the Django project. + + +URLResolver is a class within the django.urls module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / urlpatterns.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./urlpatterns.py) + +```python +# urlpatterns.py +from django.conf.urls import include, url +~~from django.urls import URLResolver, path, register_converter +from django.urls.resolvers import RoutePattern + +from rest_framework.settings import api_settings + + +def _get_format_path_converter(suffix_kwarg, allowed): + if allowed: + if len(allowed) == 1: + allowed_pattern = allowed[0] + else: + allowed_pattern = '(?:%s)' % '|'.join(allowed) + suffix_pattern = r"\.%s/?" % allowed_pattern + else: + suffix_pattern = r"\.[a-z0-9]+/?" + + class FormatSuffixConverter: + regex = suffix_pattern + + def to_python(self, value): + return value.strip('./') + + def to_url(self, value): + return '.' + value + '/' + + converter_name = 'drf_format_suffix' + if allowed: + converter_name += '_' + '_'.join(allowed) + + return converter_name, FormatSuffixConverter + + +def apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required, suffix_route=None): + ret = [] + for urlpattern in urlpatterns: +~~ if isinstance(urlpattern, URLResolver): + regex = urlpattern.pattern.regex.pattern + namespace = urlpattern.namespace + app_name = urlpattern.app_name + kwargs = urlpattern.default_kwargs + patterns = apply_suffix_patterns(urlpattern.url_patterns, + suffix_pattern, + suffix_required, + suffix_route) + + if isinstance(urlpattern.pattern, RoutePattern): + assert path is not None + route = str(urlpattern.pattern) + new_pattern = path(route, include((patterns, app_name), namespace), kwargs) + else: + new_pattern = url(regex, include((patterns, app_name), namespace), kwargs) + + ret.append(new_pattern) + else: + regex = urlpattern.pattern.regex.pattern.rstrip('$').rstrip('/') + suffix_pattern + view = urlpattern.callback + kwargs = urlpattern.default_args + name = urlpattern.name + if not suffix_required: + ret.append(urlpattern) + + +## ... source file continues with no further URLResolver examples... + +``` + diff --git a/content/pages/examples/django/django-utils-cache-add-never-cache-headers.markdown b/content/pages/examples/django/django-utils-cache-add-never-cache-headers.markdown new file mode 100644 index 000000000..4d2add1ea --- /dev/null +++ b/content/pages/examples/django/django-utils-cache-add-never-cache-headers.markdown @@ -0,0 +1,116 @@ +title: django.utils.cache add_never_cache_headers Example Code +category: page +slug: django-utils-cache-add-never-cache-headers-examples +sortorder: 500011424 +toc: False +sidebartitle: django.utils.cache add_never_cache_headers +meta: Python example code for the add_never_cache_headers callable from the django.utils.cache module of the Django project. + + +add_never_cache_headers is a callable within the django.utils.cache module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / middleware / toolbar.py**](https://github.com/divio/django-cms/blob/develop/cms/middleware/toolbar.py) + +```python +# toolbar.py +from django import forms +from django.contrib.admin.models import LogEntry, ADDITION, CHANGE +from django.core.exceptions import ValidationError +from django.urls import resolve + +from cms.toolbar.toolbar import CMSToolbar +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils.conf import get_cms_setting +from cms.utils.compat.dj import MiddlewareMixin +from cms.utils.request_ip_resolvers import get_request_ip_resolver + + +get_request_ip = get_request_ip_resolver() + + +class ToolbarMiddleware(MiddlewareMixin): + + def is_cms_request(self, request): + toolbar_hide = get_cms_setting('TOOLBAR_HIDE') + internal_ips = get_cms_setting('INTERNAL_IPS') + + if internal_ips: + client_ip = get_request_ip(request) + try: + client_ip = forms.GenericIPAddressField().clean(client_ip) + except ValidationError: + return False + else: + if client_ip not in internal_ips: + return False + + if not toolbar_hide: + return True + + try: + + +## ... source file abbreviated to get to add_never_cache_headers examples ... + + + + if edit_enabled and show_toolbar and not request.session.get('cms_edit'): + request.session['cms_edit'] = True + request.session['cms_preview'] = False + + if edit_disabled or not show_toolbar and request.session.get('cms_edit'): + request.session['cms_edit'] = False + + if 'preview' in request.GET and not request.session.get('cms_preview'): + request.session['cms_preview'] = True + + if request.user.is_staff: + try: + request.cms_latest_entry = LogEntry.objects.filter( + user=request.user, + action_flag__in=(ADDITION, CHANGE) + ).only('pk').order_by('-pk')[0].pk + except IndexError: + request.cms_latest_entry = -1 + request.toolbar = CMSToolbar(request) + + def process_response(self, request, response): + if not self.is_cms_request(request): + return response + +~~ from django.utils.cache import add_never_cache_headers + + toolbar = get_toolbar_from_request(request) + + if toolbar._cache_disabled: +~~ add_never_cache_headers(response) + + if hasattr(request, 'user') and request.user.is_staff and response.status_code != 500: + try: + if hasattr(request, 'cms_latest_entry'): + pk = LogEntry.objects.filter( + user=request.user, + action_flag__in=(ADDITION, CHANGE) + ).only('pk').order_by('-pk')[0].pk + + if request.cms_latest_entry != pk: + request.session['cms_log_latest'] = pk + except IndexError: + pass + return response + + + +## ... source file continues with no further add_never_cache_headers examples... + +``` + diff --git a/content/pages/examples/django/django-utils-cache-cc-delim-re.markdown b/content/pages/examples/django/django-utils-cache-cc-delim-re.markdown new file mode 100644 index 000000000..2620993a8 --- /dev/null +++ b/content/pages/examples/django/django-utils-cache-cc-delim-re.markdown @@ -0,0 +1,122 @@ +title: django.utils.cache cc_delim_re Example Code +category: page +slug: django-utils-cache-cc-delim-re-examples +sortorder: 500011425 +toc: False +sidebartitle: django.utils.cache cc_delim_re +meta: Python example code for the cc_delim_re callable from the django.utils.cache module of the Django project. + + +cc_delim_re is a callable within the django.utils.cache module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / views.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./views.py) + +```python +# views.py +from django.conf import settings +from django.core.exceptions import PermissionDenied +from django.db import connection, models, transaction +from django.http import Http404 +from django.http.response import HttpResponseBase +~~from django.utils.cache import cc_delim_re, patch_vary_headers +from django.utils.encoding import smart_str +from django.views.decorators.csrf import csrf_exempt +from django.views.generic import View + +from rest_framework import exceptions, status +from rest_framework.request import Request +from rest_framework.response import Response +from rest_framework.schemas import DefaultSchema +from rest_framework.settings import api_settings +from rest_framework.utils import formatting + + +def get_view_name(view): + name = getattr(view, 'name', None) + if name is not None: + return name + + name = view.__class__.__name__ + name = formatting.remove_trailing_string(name, 'View') + name = formatting.remove_trailing_string(name, 'ViewSet') + name = formatting.camelcase_to_spaces(name) + + suffix = getattr(view, 'suffix', None) + if suffix: + + +## ... source file abbreviated to get to cc_delim_re examples ... + + + version, scheme = self.determine_version(request, *args, **kwargs) + request.version, request.versioning_scheme = version, scheme + + self.perform_authentication(request) + self.check_permissions(request) + self.check_throttles(request) + + def finalize_response(self, request, response, *args, **kwargs): + assert isinstance(response, HttpResponseBase), ( + 'Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` ' + 'to be returned from the view, but received a `%s`' + % type(response) + ) + + if isinstance(response, Response): + if not getattr(request, 'accepted_renderer', None): + neg = self.perform_content_negotiation(request, force=True) + request.accepted_renderer, request.accepted_media_type = neg + + response.accepted_renderer = request.accepted_renderer + response.accepted_media_type = request.accepted_media_type + response.renderer_context = self.get_renderer_context() + + vary_headers = self.headers.pop('Vary', None) + if vary_headers is not None: +~~ patch_vary_headers(response, cc_delim_re.split(vary_headers)) + + for key, value in self.headers.items(): + response[key] = value + + return response + + def handle_exception(self, exc): + if isinstance(exc, (exceptions.NotAuthenticated, + exceptions.AuthenticationFailed)): + auth_header = self.get_authenticate_header(self.request) + + if auth_header: + exc.auth_header = auth_header + else: + exc.status_code = status.HTTP_403_FORBIDDEN + + exception_handler = self.get_exception_handler() + + context = self.get_exception_handler_context() + response = exception_handler(exc, context) + + if response is None: + self.raise_uncaught_exception(exc) + + + +## ... source file continues with no further cc_delim_re examples... + +``` + diff --git a/content/pages/examples/django/django-utils-cache-patch-cache-control.markdown b/content/pages/examples/django/django-utils-cache-patch-cache-control.markdown new file mode 100644 index 000000000..d88446628 --- /dev/null +++ b/content/pages/examples/django/django-utils-cache-patch-cache-control.markdown @@ -0,0 +1,227 @@ +title: django.utils.cache patch_cache_control Example Code +category: page +slug: django-utils-cache-patch-cache-control-examples +sortorder: 500011426 +toc: False +sidebartitle: django.utils.cache patch_cache_control +meta: Python example code for the patch_cache_control callable from the django.utils.cache module of the Django project. + + +patch_cache_control is a callable within the django.utils.cache module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / views.py**](https://github.com/divio/django-cms/blob/develop/cms/./views.py) + +```python +# views.py + +from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login +from django.contrib.auth.views import redirect_to_login +from django.http import HttpResponse, HttpResponseRedirect +from django.urls import reverse +~~from django.utils.cache import patch_cache_control +from django.utils.http import is_safe_url, urlquote +from django.utils.timezone import now +from django.utils.translation import get_language_from_request +from django.views.decorators.http import require_POST + +from cms.cache.page import get_page_cache +from cms.exceptions import LanguageError +from cms.forms.login import CMSToolbarLoginForm +from cms.models.pagemodel import TreeNode +from cms.page_rendering import _handle_no_page, render_page, render_object_structure, _render_welcome_page +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils import get_current_site +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import (get_fallback_languages, get_public_languages, + get_redirect_on_fallback, get_language_list, + get_default_language_for_site, + is_language_prefix_patterns_used) +from cms.utils.page import get_page_from_request +from cms.utils.page_permissions import user_can_change_page + + +def _clean_redirect_url(redirect_url, language): + if (redirect_url and is_language_prefix_patterns_used() and redirect_url[0] == "/" + and not redirect_url.startswith('/%s/' % language)): + redirect_url = "/%s/%s" % (language, redirect_url.lstrip("/")) + return redirect_url + + +def details(request, slug): + response_timestamp = now() + if get_cms_setting("PAGE_CACHE") and ( + not hasattr(request, 'toolbar') or ( + not request.toolbar.edit_mode_active and + not request.toolbar.show_toolbar and + not request.user.is_authenticated + ) + ): + cache_content = get_page_cache(request) + if cache_content is not None: + content, headers, expires_datetime = cache_content + response = HttpResponse(content) + response.xframe_options_exempt = True + response._headers = headers + max_age = int( + (expires_datetime - response_timestamp).total_seconds() + 0.5) +~~ patch_cache_control(response, max_age=max_age) + return response + + site = get_current_site() + page = get_page_from_request(request, use_path=slug) + toolbar = get_toolbar_from_request(request) + tree_nodes = TreeNode.objects.get_for_site(site) + + if not page and not slug and not tree_nodes.exists(): + return _render_welcome_page(request) + + if not page: + _handle_no_page(request) + + request.current_page = page + + if hasattr(request, 'user') and request.user.is_staff: + user_languages = get_language_list(site_id=site.pk) + else: + user_languages = get_public_languages(site_id=site.pk) + + request_language = get_language_from_request(request, check_path=True) + + if not page.is_home and request_language not in user_languages: + return _handle_no_page(request) + + +## ... source file continues with no further patch_cache_control examples... + +``` + + +## Example 2 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / models.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/models.py) + +```python +# models.py +import json +import logging +from collections import defaultdict +from io import StringIO +from urllib.parse import urlparse + +from django.conf import settings +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core import checks +from django.core.cache import cache +from django.core.exceptions import ValidationError +from django.core.handlers.base import BaseHandler +from django.core.handlers.wsgi import WSGIRequest +from django.db import models, transaction +from django.db.models import Case, Q, Value, When +from django.db.models.functions import Concat, Lower, Substr +from django.http import Http404 +from django.http.request import split_domain_port +from django.template.response import TemplateResponse +from django.urls import NoReverseMatch, reverse +from django.utils import timezone +~~from django.utils.cache import patch_cache_control +from django.utils.functional import cached_property +from django.utils.text import capfirst, slugify +from django.utils.translation import gettext_lazy as _ +from modelcluster.models import ( + ClusterableModel, get_all_child_m2m_relations, get_all_child_relations) +from treebeard.mp_tree import MP_Node + +from wagtail.core.query import PageQuerySet, TreeQuerySet +from wagtail.core.signals import page_published, page_unpublished, post_page_move, pre_page_move +from wagtail.core.sites import get_site_for_hostname +from wagtail.core.url_routing import RouteResult +from wagtail.core.utils import WAGTAIL_APPEND_SLASH, camelcase_to_underscore, resolve_model_string +from wagtail.search import index + + +logger = logging.getLogger('wagtail.core') + +PAGE_TEMPLATE_VAR = 'page' + + +class SiteManager(models.Manager): + def get_queryset(self): + return super(SiteManager, self).get_queryset().order_by(Lower("hostname")) + + + +## ... source file abbreviated to get to patch_cache_control examples ... + + + + def _get_dummy_header_url(self, original_request=None): + return self.full_url + + DEFAULT_PREVIEW_MODES = [('', _('Default'))] + + @property + def preview_modes(self): + return Page.DEFAULT_PREVIEW_MODES + + @property + def default_preview_mode(self): + return self.preview_modes[0][0] + + def is_previewable(self): + page = self + if page.specific_class.preview_modes != type(page).preview_modes: + page = page.specific + + return bool(page.preview_modes) + + def serve_preview(self, request, mode_name): + request.is_preview = True + + response = self.serve(request) +~~ patch_cache_control(response, private=True) + return response + + def get_cached_paths(self): + return ['/'] + + def get_sitemap_urls(self, request=None): + return [ + { + 'location': self.get_full_url(request), + 'lastmod': (self.last_published_at or self.latest_revision_created_at), + } + ] + + def get_static_site_paths(self): + yield '/' + + for child in self.get_children().live(): + for path in child.specific.get_static_site_paths(): + yield '/' + child.slug + path + + def get_ancestors(self, inclusive=False): + return Page.objects.ancestor_of(self, inclusive) + + def get_descendants(self, inclusive=False): + + +## ... source file continues with no further patch_cache_control examples... + +``` + diff --git a/content/pages/examples/django/django-utils-cache-patch-response-headers.markdown b/content/pages/examples/django/django-utils-cache-patch-response-headers.markdown new file mode 100644 index 000000000..ff959e180 --- /dev/null +++ b/content/pages/examples/django/django-utils-cache-patch-response-headers.markdown @@ -0,0 +1,116 @@ +title: django.utils.cache patch_response_headers Example Code +category: page +slug: django-utils-cache-patch-response-headers-examples +sortorder: 500011427 +toc: False +sidebartitle: django.utils.cache patch_response_headers +meta: Python example code for the patch_response_headers callable from the django.utils.cache module of the Django project. + + +patch_response_headers is a callable within the django.utils.cache module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / cache / page.py**](https://github.com/divio/django-cms/blob/develop/cms/cache/page.py) + +```python +# page.py + +import hashlib + +from datetime import timedelta + +from django.conf import settings +~~from django.utils.cache import add_never_cache_headers, patch_response_headers, patch_vary_headers +from django.utils.encoding import iri_to_uri +from django.utils.timezone import now + +from cms.cache import _get_cache_version, _set_cache_version, _get_cache_key +from cms.constants import EXPIRE_NOW, MAX_EXPIRATION_TTL +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils.conf import get_cms_setting +from cms.utils.helpers import get_timezone_name + + +def _page_cache_key(request): + cache_key = "%s:%d:%s" % ( + get_cms_setting("CACHE_PREFIX"), + settings.SITE_ID, + hashlib.sha1(iri_to_uri(request.get_full_path()).encode('utf-8')).hexdigest() + ) + if settings.USE_TZ: + cache_key += '.%s' % get_timezone_name() + return cache_key + + +def set_page_cache(response): + from django.core.cache import cache + + + +## ... source file abbreviated to get to patch_response_headers examples ... + + + + timestamp = now() + + placeholders = toolbar.content_renderer.get_rendered_placeholders() + placeholder_ttl_list = [] + vary_cache_on_set = set() + for ph in placeholders: + ttl = ph.get_cache_expiration(request, timestamp) + vary_cache_on = ph.get_vary_cache_on(request) + + placeholder_ttl_list.append(ttl) + if ttl and vary_cache_on: + vary_cache_on_set |= set(vary_cache_on) + + if EXPIRE_NOW not in placeholder_ttl_list: + if placeholder_ttl_list: + min_placeholder_ttl = min(x for x in placeholder_ttl_list) + else: + min_placeholder_ttl = MAX_EXPIRATION_TTL + ttl = min( + get_cms_setting('CACHE_DURATIONS')['content'], + min_placeholder_ttl + ) + + if ttl > 0: +~~ patch_response_headers(response, cache_timeout=ttl) + patch_vary_headers(response, sorted(vary_cache_on_set)) + + version = _get_cache_version() + expires_datetime = timestamp + timedelta(seconds=ttl) + cache.set( + _page_cache_key(request), + ( + response.content, + response._headers, + expires_datetime, + ), + ttl, + version=version + ) + _set_cache_version(version) + return response + + +def get_page_cache(request): + from django.core.cache import cache + return cache.get(_page_cache_key(request), version=_get_cache_version()) + + +def get_xframe_cache(page): + + +## ... source file continues with no further patch_response_headers examples... + +``` + diff --git a/content/pages/examples/django/django-utils-cache-patch-vary-headers.markdown b/content/pages/examples/django/django-utils-cache-patch-vary-headers.markdown new file mode 100644 index 000000000..7e54d16b8 --- /dev/null +++ b/content/pages/examples/django/django-utils-cache-patch-vary-headers.markdown @@ -0,0 +1,373 @@ +title: django.utils.cache patch_vary_headers Example Code +category: page +slug: django-utils-cache-patch-vary-headers-examples +sortorder: 500011428 +toc: False +sidebartitle: django.utils.cache patch_vary_headers +meta: Python example code for the patch_vary_headers callable from the django.utils.cache module of the Django project. + + +patch_vary_headers is a callable within the django.utils.cache module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / cache / page.py**](https://github.com/divio/django-cms/blob/develop/cms/cache/page.py) + +```python +# page.py + +import hashlib + +from datetime import timedelta + +from django.conf import settings +~~from django.utils.cache import add_never_cache_headers, patch_response_headers, patch_vary_headers +from django.utils.encoding import iri_to_uri +from django.utils.timezone import now + +from cms.cache import _get_cache_version, _set_cache_version, _get_cache_key +from cms.constants import EXPIRE_NOW, MAX_EXPIRATION_TTL +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils.conf import get_cms_setting +from cms.utils.helpers import get_timezone_name + + +def _page_cache_key(request): + cache_key = "%s:%d:%s" % ( + get_cms_setting("CACHE_PREFIX"), + settings.SITE_ID, + hashlib.sha1(iri_to_uri(request.get_full_path()).encode('utf-8')).hexdigest() + ) + if settings.USE_TZ: + cache_key += '.%s' % get_timezone_name() + return cache_key + + +def set_page_cache(response): + from django.core.cache import cache + + + +## ... source file abbreviated to get to patch_vary_headers examples ... + + + timestamp = now() + + placeholders = toolbar.content_renderer.get_rendered_placeholders() + placeholder_ttl_list = [] + vary_cache_on_set = set() + for ph in placeholders: + ttl = ph.get_cache_expiration(request, timestamp) + vary_cache_on = ph.get_vary_cache_on(request) + + placeholder_ttl_list.append(ttl) + if ttl and vary_cache_on: + vary_cache_on_set |= set(vary_cache_on) + + if EXPIRE_NOW not in placeholder_ttl_list: + if placeholder_ttl_list: + min_placeholder_ttl = min(x for x in placeholder_ttl_list) + else: + min_placeholder_ttl = MAX_EXPIRATION_TTL + ttl = min( + get_cms_setting('CACHE_DURATIONS')['content'], + min_placeholder_ttl + ) + + if ttl > 0: + patch_response_headers(response, cache_timeout=ttl) +~~ patch_vary_headers(response, sorted(vary_cache_on_set)) + + version = _get_cache_version() + expires_datetime = timestamp + timedelta(seconds=ttl) + cache.set( + _page_cache_key(request), + ( + response.content, + response._headers, + expires_datetime, + ), + ttl, + version=version + ) + _set_cache_version(version) + return response + + +def get_page_cache(request): + from django.core.cache import cache + return cache.get(_page_cache_key(request), version=_get_cache_version()) + + +def get_xframe_cache(page): + from django.core.cache import cache + + +## ... source file continues with no further patch_vary_headers examples... + +``` + + +## Example 2 from django-cors-headers +[django-cors-headers](https://github.com/ottoyiu/django-cors-headers) +is an +[open source](https://github.com/ottoyiu/django-cors-headers/blob/master/LICENSE) +library for enabling +[Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) +handling in your [Django](/django.html) web applications and appropriately +dealing with HTTP headers for CORS requests. + +[**django-cors-headers / src/corsheaders / middleware.py**](https://github.com/ottoyiu/django-cors-headers/blob/master/src/corsheaders/./middleware.py) + +```python +# middleware.py +import re +from urllib.parse import urlparse + +from django import http +~~from django.utils.cache import patch_vary_headers +from django.utils.deprecation import MiddlewareMixin + +from corsheaders.conf import conf +from corsheaders.signals import check_request_enabled + +ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin" +ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers" +ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials" +ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers" +ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods" +ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age" + + +class CorsPostCsrfMiddleware(MiddlewareMixin): + def _https_referer_replace_reverse(self, request): + if conf.CORS_REPLACE_HTTPS_REFERER and "ORIGINAL_HTTP_REFERER" in request.META: + http_referer = request.META["ORIGINAL_HTTP_REFERER"] + request.META["HTTP_REFERER"] = http_referer + del request.META["ORIGINAL_HTTP_REFERER"] + + def process_request(self, request): + self._https_referer_replace_reverse(request) + return None + + + +## ... source file abbreviated to get to patch_vary_headers examples ... + + + if request._cors_enabled: + if conf.CORS_REPLACE_HTTPS_REFERER: + self._https_referer_replace(request) + + if ( + request.method == "OPTIONS" + and "HTTP_ACCESS_CONTROL_REQUEST_METHOD" in request.META + ): + response = http.HttpResponse() + response["Content-Length"] = "0" + return response + + def process_view(self, request, callback, callback_args, callback_kwargs): + if request._cors_enabled and conf.CORS_REPLACE_HTTPS_REFERER: + self._https_referer_replace(request) + return None + + def process_response(self, request, response): + enabled = getattr(request, "_cors_enabled", None) + if enabled is None: + enabled = self.is_enabled(request) + + if not enabled: + return response + +~~ patch_vary_headers(response, ["Origin"]) + + origin = request.META.get("HTTP_ORIGIN") + if not origin: + return response + + url = urlparse(origin) + + if conf.CORS_ALLOW_CREDENTIALS: + response[ACCESS_CONTROL_ALLOW_CREDENTIALS] = "true" + + if ( + not conf.CORS_ORIGIN_ALLOW_ALL + and not self.origin_found_in_white_lists(origin, url) + and not self.check_signal(request) + ): + return response + + if conf.CORS_ORIGIN_ALLOW_ALL and not conf.CORS_ALLOW_CREDENTIALS: + response[ACCESS_CONTROL_ALLOW_ORIGIN] = "*" + else: + response[ACCESS_CONTROL_ALLOW_ORIGIN] = origin + + if len(conf.CORS_EXPOSE_HEADERS): + response[ACCESS_CONTROL_EXPOSE_HEADERS] = ", ".join( + + +## ... source file continues with no further patch_vary_headers examples... + +``` + + +## Example 3 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / middleware.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./middleware.py) + +```python +# middleware.py +from django.contrib.auth import authenticate +~~from django.utils.cache import patch_vary_headers +from django.utils.deprecation import MiddlewareMixin + + +class OAuth2TokenMiddleware(MiddlewareMixin): + + def process_request(self, request): + if request.META.get("HTTP_AUTHORIZATION", "").startswith("Bearer"): + if not hasattr(request, "user") or request.user.is_anonymous: + user = authenticate(request=request) + if user: + request.user = request._cached_user = user + + def process_response(self, request, response): +~~ patch_vary_headers(response, ("Authorization",)) + return response + + + +## ... source file continues with no further patch_vary_headers examples... + +``` + + +## Example 4 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / views.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./views.py) + +```python +# views.py +from django.conf import settings +from django.core.exceptions import PermissionDenied +from django.db import connection, models, transaction +from django.http import Http404 +from django.http.response import HttpResponseBase +~~from django.utils.cache import cc_delim_re, patch_vary_headers +from django.utils.encoding import smart_str +from django.views.decorators.csrf import csrf_exempt +from django.views.generic import View + +from rest_framework import exceptions, status +from rest_framework.request import Request +from rest_framework.response import Response +from rest_framework.schemas import DefaultSchema +from rest_framework.settings import api_settings +from rest_framework.utils import formatting + + +def get_view_name(view): + name = getattr(view, 'name', None) + if name is not None: + return name + + name = view.__class__.__name__ + name = formatting.remove_trailing_string(name, 'View') + name = formatting.remove_trailing_string(name, 'ViewSet') + name = formatting.camelcase_to_spaces(name) + + suffix = getattr(view, 'suffix', None) + if suffix: + + +## ... source file abbreviated to get to patch_vary_headers examples ... + + + version, scheme = self.determine_version(request, *args, **kwargs) + request.version, request.versioning_scheme = version, scheme + + self.perform_authentication(request) + self.check_permissions(request) + self.check_throttles(request) + + def finalize_response(self, request, response, *args, **kwargs): + assert isinstance(response, HttpResponseBase), ( + 'Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` ' + 'to be returned from the view, but received a `%s`' + % type(response) + ) + + if isinstance(response, Response): + if not getattr(request, 'accepted_renderer', None): + neg = self.perform_content_negotiation(request, force=True) + request.accepted_renderer, request.accepted_media_type = neg + + response.accepted_renderer = request.accepted_renderer + response.accepted_media_type = request.accepted_media_type + response.renderer_context = self.get_renderer_context() + + vary_headers = self.headers.pop('Vary', None) + if vary_headers is not None: +~~ patch_vary_headers(response, cc_delim_re.split(vary_headers)) + + for key, value in self.headers.items(): + response[key] = value + + return response + + def handle_exception(self, exc): + if isinstance(exc, (exceptions.NotAuthenticated, + exceptions.AuthenticationFailed)): + auth_header = self.get_authenticate_header(self.request) + + if auth_header: + exc.auth_header = auth_header + else: + exc.status_code = status.HTTP_403_FORBIDDEN + + exception_handler = self.get_exception_handler() + + context = self.get_exception_handler_context() + response = exception_handler(exc, context) + + if response is None: + self.raise_uncaught_exception(exc) + + + +## ... source file continues with no further patch_vary_headers examples... + +``` + diff --git a/content/pages/examples/django/django-utils-crypto-constant-time-compare.markdown b/content/pages/examples/django/django-utils-crypto-constant-time-compare.markdown new file mode 100644 index 000000000..0aa125c7f --- /dev/null +++ b/content/pages/examples/django/django-utils-crypto-constant-time-compare.markdown @@ -0,0 +1,50 @@ +title: django.utils.crypto constant_time_compare Example Code +category: page +slug: django-utils-crypto-constant-time-compare-examples +sortorder: 500011429 +toc: False +sidebartitle: django.utils.crypto constant_time_compare +meta: Python example code for the constant_time_compare callable from the django.utils.crypto module of the Django project. + + +constant_time_compare is a callable within the django.utils.crypto module of the Django project. + + +## Example 1 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / forms.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/forms.py) + +```python +# forms.py +from django import forms +~~from django.utils.crypto import constant_time_compare +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy + + +class PasswordViewRestrictionForm(forms.Form): + password = forms.CharField(label=gettext_lazy("Password"), widget=forms.PasswordInput) + return_url = forms.CharField(widget=forms.HiddenInput) + + def __init__(self, *args, **kwargs): + self.restriction = kwargs.pop('instance') + super().__init__(*args, **kwargs) + + def clean_password(self): + data = self.cleaned_data['password'] +~~ if not constant_time_compare(data, self.restriction.password): + raise forms.ValidationError(_("The password you have entered is not correct. Please try again.")) + + return data + + + +## ... source file continues with no further constant_time_compare examples... + +``` + diff --git a/content/pages/examples/django/django-utils-crypto-get-random-string.markdown b/content/pages/examples/django/django-utils-crypto-get-random-string.markdown new file mode 100644 index 000000000..915d495ef --- /dev/null +++ b/content/pages/examples/django/django-utils-crypto-get-random-string.markdown @@ -0,0 +1,112 @@ +title: django.utils.crypto get_random_string Example Code +category: page +slug: django-utils-crypto-get-random-string-examples +sortorder: 500011430 +toc: False +sidebartitle: django.utils.crypto get_random_string +meta: Python example code for the get_random_string callable from the django.utils.crypto module of the Django project. + + +get_random_string is a callable within the django.utils.crypto module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / socialaccount / models.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/models.py) + +```python +# models.py +from __future__ import absolute_import + +from django.contrib.auth import authenticate +from django.contrib.sites.models import Site +from django.contrib.sites.shortcuts import get_current_site +from django.core.exceptions import PermissionDenied +from django.db import models +~~from django.utils.crypto import get_random_string +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +import allauth.app_settings +from allauth.account.models import EmailAddress +from allauth.account.utils import get_next_redirect_url, setup_user_email +from allauth.utils import get_user_model + +from ..utils import get_request_param +from . import app_settings, providers +from .adapter import get_adapter +from .fields import JSONField + + +class SocialAppManager(models.Manager): + def get_current(self, provider, request=None): + cache = {} + if request: + cache = getattr(request, '_socialapp_cache', {}) + request._socialapp_cache = cache + app = cache.get(provider) + if not app: + site = get_current_site(request) + app = self.get( + + +## ... source file abbreviated to get to get_random_string examples ... + + + self.token = t + except SocialToken.DoesNotExist: + self.token.account = a + self.token.save() + except SocialAccount.DoesNotExist: + pass + + def get_redirect_url(self, request): + url = self.state.get('next') + return url + + @classmethod + def state_from_request(cls, request): + state = {} + next_url = get_next_redirect_url(request) + if next_url: + state['next'] = next_url + state['process'] = get_request_param(request, 'process', 'login') + state['scope'] = get_request_param(request, 'scope', '') + state['auth_params'] = get_request_param(request, 'auth_params', '') + return state + + @classmethod + def stash_state(cls, request): + state = cls.state_from_request(request) +~~ verifier = get_random_string() + request.session['socialaccount_state'] = (state, verifier) + return verifier + + @classmethod + def unstash_state(cls, request): + if 'socialaccount_state' not in request.session: + raise PermissionDenied() + state, verifier = request.session.pop('socialaccount_state') + return state + + @classmethod + def verify_and_unstash_state(cls, request, verifier): + if 'socialaccount_state' not in request.session: + raise PermissionDenied() + state, verifier2 = request.session.pop('socialaccount_state') + if verifier != verifier2: + raise PermissionDenied() + return state + + + +## ... source file continues with no further get_random_string examples... + +``` + diff --git a/content/pages/examples/django/django-utils-datastructures-multivaluedict.markdown b/content/pages/examples/django/django-utils-datastructures-multivaluedict.markdown new file mode 100644 index 000000000..625d9fbf8 --- /dev/null +++ b/content/pages/examples/django/django-utils-datastructures-multivaluedict.markdown @@ -0,0 +1,296 @@ +title: django.utils.datastructures MultiValueDict Example Code +category: page +slug: django-utils-datastructures-multivaluedict-examples +sortorder: 500011431 +toc: False +sidebartitle: django.utils.datastructures MultiValueDict +meta: Python example code for the MultiValueDict class from the django.utils.datastructures module of the Django project. + + +MultiValueDict is a class within the django.utils.datastructures module of the Django project. + + +## Example 1 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / widgets.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./widgets.py) + +```python +# widgets.py +from collections.abc import Iterable +from copy import deepcopy +from itertools import chain +from re import search, sub + +from django import forms +from django.db.models.fields import BLANK_CHOICE_DASH +from django.forms.utils import flatatt +~~from django.utils.datastructures import MultiValueDict +from django.utils.encoding import force_str +from django.utils.http import urlencode +from django.utils.safestring import mark_safe +from django.utils.translation import gettext as _ + + +class LinkWidget(forms.Widget): + def __init__(self, attrs=None, choices=()): + super().__init__(attrs) + + self.choices = choices + + def value_from_datadict(self, data, files, name): + value = super().value_from_datadict(data, files, name) + self.data = data + return value + + def render(self, name, value, attrs=None, choices=(), renderer=None): + if not hasattr(self, 'data'): + self.data = {} + if value is None: + value = '' + final_attrs = self.build_attrs(self.attrs, extra_attrs=attrs) + output = ['' % flatatt(final_attrs)] + + +## ... source file abbreviated to get to MultiValueDict examples ... + + + if len(value) <= 1: + value = value[0] if value else '' + return super().render(name, value, attrs, renderer=renderer) + + value = [force_str(self.surrogate.format_value(v)) for v in value] + value = ','.join(list(value)) + + return self.surrogate.render(name, value, attrs, renderer=renderer) + + +class CSVWidget(BaseCSVWidget, forms.TextInput): + def __init__(self, *args, attrs=None, **kwargs): + super().__init__(*args, attrs, **kwargs) + + if attrs is not None: + self.surrogate.attrs.update(attrs) + + +class QueryArrayWidget(BaseCSVWidget, forms.TextInput): + + def value_from_datadict(self, data, files, name): +~~ if not isinstance(data, MultiValueDict): + for key, value in data.items(): + if isinstance(value, str): + data[key] = [x.strip() for x in value.rstrip(',').split(',') if x] +~~ data = MultiValueDict(data) + + values_list = data.getlist(name, data.getlist('%s[]' % name)) or [] + + if len(values_list) > 0: + ret = [x for x in values_list if x] + else: + ret = [] + + return list(set(ret)) + + def render(self, name, value, attrs=None, renderer=None): + if not self._isiterable(value): + value = [value] + + + +## ... source file continues with no further MultiValueDict examples... + +``` + + +## Example 2 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / compat.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./compat.py) + +```python +# compat.py +from contextlib import contextmanager + +import django +from django.template import Context +~~from django.utils.datastructures import MultiValueDict + +MULTIVALUE_DICT_TYPES = (MultiValueDict,) + + +REQUIRED_CONTEXT_ATTRIBTUES = ( + '_form_config', + '_form_render', +) + + +class DictContext(dict): + pass + + +if django.VERSION < (1, 8): + def get_template(context, template_name): + from django.template.loader import get_template + return get_template(template_name) + + def get_context(context): + if not isinstance(context, Context): + context = Context(context) + return context + + + +## ... source file continues with no further MultiValueDict examples... + +``` + + +## Example 3 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / request.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./request.py) + +```python +# request.py +import io +import sys +from contextlib import contextmanager + +from django.conf import settings +from django.http import HttpRequest, QueryDict +from django.http.multipartparser import parse_header +from django.http.request import RawPostDataException +~~from django.utils.datastructures import MultiValueDict + +from rest_framework import HTTP_HEADER_ENCODING, exceptions +from rest_framework.settings import api_settings + + +def is_form_media_type(media_type): + base_media_type, params = parse_header(media_type.encode(HTTP_HEADER_ENCODING)) + return (base_media_type == 'application/x-www-form-urlencoded' or + base_media_type == 'multipart/form-data') + + +class override_method: + + def __init__(self, view, request, method): + self.view = view + self.request = request + self.method = method + self.action = getattr(view, 'action', None) + + def __enter__(self): + self.view.request = clone_request(self.request, self.method) + action_map = getattr(self.view, 'action_map', {}) + self.view.action = action_map.get(self.method.lower()) + return self.view.request + + +## ... source file abbreviated to get to MultiValueDict examples ... + + + self._stream = io.BytesIO(self.body) + + def _supports_form_parsing(self): + form_media = ( + 'application/x-www-form-urlencoded', + 'multipart/form-data' + ) + return any([parser.media_type in form_media for parser in self.parsers]) + + def _parse(self): + media_type = self.content_type + try: + stream = self.stream + except RawPostDataException: + if not hasattr(self._request, '_post'): + raise + if self._supports_form_parsing(): + return (self._request.POST, self._request.FILES) + stream = None + + if stream is None or media_type is None: + if media_type and is_form_media_type(media_type): + empty_data = QueryDict('', encoding=self._request._encoding) + else: + empty_data = {} +~~ empty_files = MultiValueDict() + return (empty_data, empty_files) + + parser = self.negotiator.select_parser(self, self.parsers) + + if not parser: + raise exceptions.UnsupportedMediaType(media_type) + + try: + parsed = parser.parse(stream, media_type, self.parser_context) + except Exception: + self._data = QueryDict('', encoding=self._request._encoding) +~~ self._files = MultiValueDict() + self._full_data = self._data + raise + + try: + return (parsed.data, parsed.files) + except AttributeError: +~~ empty_files = MultiValueDict() + return (parsed, empty_files) + + def _authenticate(self): + for authenticator in self.authenticators: + try: + user_auth_tuple = authenticator.authenticate(self) + except exceptions.APIException: + self._not_authenticated() + raise + + if user_auth_tuple is not None: + self._authenticator = authenticator + self.user, self.auth = user_auth_tuple + return + + self._not_authenticated() + + def _not_authenticated(self): + self._authenticator = None + + if api_settings.UNAUTHENTICATED_USER: + self.user = api_settings.UNAUTHENTICATED_USER() + else: + self.user = None + + +## ... source file continues with no further MultiValueDict examples... + +``` + diff --git a/content/pages/examples/django/django-utils-dateformat.markdown b/content/pages/examples/django/django-utils-dateformat.markdown new file mode 100644 index 000000000..fd397aed3 --- /dev/null +++ b/content/pages/examples/django/django-utils-dateformat.markdown @@ -0,0 +1,176 @@ +title: django.utils dateformat Example Code +category: page +slug: django-utils-dateformat-examples +sortorder: 500011415 +toc: False +sidebartitle: django.utils dateformat +meta: Python example code for the dateformat callable from the django.utils module of the Django project. + + +dateformat is a callable within the django.utils module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog_tests / tests.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog_tests/tests.py) + +```python +# tests.py +import datetime +import django +from django.conf import settings +from django.contrib import auth +from django.contrib.auth.models import User, AnonymousUser +from django.core.exceptions import ValidationError +from django.db.models.signals import pre_save +from django.http import HttpResponse +from django.test import TestCase, RequestFactory +~~from django.utils import dateformat, formats, timezone +from dateutil.tz import gettz + +from auditlog.middleware import AuditlogMiddleware +from auditlog.models import LogEntry +from auditlog.registry import auditlog +from auditlog_tests.models import SimpleModel, AltPrimaryKeyModel, UUIDPrimaryKeyModel, \ + ProxyModel, SimpleIncludeModel, SimpleExcludeModel, SimpleMappingModel, RelatedModel, \ + ManyRelatedModel, AdditionalDataIncludedModel, DateTimeFieldModel, ChoicesFieldModel, \ + CharfieldTextfieldModel, PostgresArrayFieldModel, NoDeleteHistoryModel +from auditlog import compat + + +class SimpleModelTest(TestCase): + def setUp(self): + self.obj = SimpleModel.objects.create(text='I am not difficult.') + + def test_create(self): + obj = self.obj + + self.assertTrue(obj.history.count() == 1, msg="There is one log entry") + + try: + history = obj.history.get() + except obj.history.DoesNotExist: + + +## ... source file abbreviated to get to dateformat examples ... + + + + self.assertTrue(dtm.history.count() == 2, msg="There are two log entries") + + def test_model_with_different_time_and_timezone(self): + timestamp = datetime.datetime(2017, 1, 10, 12, 0, tzinfo=timezone.utc) + date = datetime.date(2017, 1, 10) + time = datetime.time(12, 0) + dtm = DateTimeFieldModel(label='DateTimeField model', timestamp=timestamp, date=date, time=time, naive_dt=self.now) + dtm.save() + self.assertTrue(dtm.history.count() == 1, msg="There is one log entry") + + timestamp = datetime.datetime(2017, 1, 10, 14, 0, tzinfo=self.utc_plus_one) + dtm.timestamp = timestamp + dtm.save() + + self.assertTrue(dtm.history.count() == 2, msg="There are two log entries") + + def test_changes_display_dict_datetime(self): + timestamp = datetime.datetime(2017, 1, 10, 15, 0, tzinfo=timezone.utc) + date = datetime.date(2017, 1, 10) + time = datetime.time(12, 0) + dtm = DateTimeFieldModel(label='DateTimeField model', timestamp=timestamp, date=date, time=time, naive_dt=self.now) + dtm.save() + localized_timestamp = timestamp.astimezone(gettz(settings.TIME_ZONE)) + self.assertTrue(dtm.history.latest().changes_display_dict["timestamp"][1] == \ +~~ dateformat.format(localized_timestamp, settings.DATETIME_FORMAT), + msg=("The datetime should be formatted according to Django's settings for" + " DATETIME_FORMAT")) + timestamp = timezone.now() + dtm.timestamp = timestamp + dtm.save() + localized_timestamp = timestamp.astimezone(gettz(settings.TIME_ZONE)) + self.assertTrue(dtm.history.latest().changes_display_dict["timestamp"][1] == \ +~~ dateformat.format(localized_timestamp, settings.DATETIME_FORMAT), + msg=("The datetime should be formatted according to Django's settings for" + " DATETIME_FORMAT")) + + with self.settings(USE_L10N=True, LANGUAGE_CODE='en-GB'): + self.assertTrue(dtm.history.latest().changes_display_dict["timestamp"][1] == \ + formats.localize(localized_timestamp), + msg=("The datetime should be formatted according to Django's settings for" + " USE_L10N is True with a different LANGUAGE_CODE.")) + + + def test_changes_display_dict_date(self): + timestamp = datetime.datetime(2017, 1, 10, 15, 0, tzinfo=timezone.utc) + date = datetime.date(2017, 1, 10) + time = datetime.time(12, 0) + dtm = DateTimeFieldModel(label='DateTimeField model', timestamp=timestamp, date=date, time=time, naive_dt=self.now) + dtm.save() + self.assertTrue(dtm.history.latest().changes_display_dict["date"][1] == \ +~~ dateformat.format(date, settings.DATE_FORMAT), + msg=("The date should be formatted according to Django's settings for" + " DATE_FORMAT unless USE_L10N is True.")) + date = datetime.date(2017, 1, 11) + dtm.date = date + dtm.save() + self.assertTrue(dtm.history.latest().changes_display_dict["date"][1] == \ +~~ dateformat.format(date, settings.DATE_FORMAT), + msg=("The date should be formatted according to Django's settings for" + " DATE_FORMAT unless USE_L10N is True.")) + + with self.settings(USE_L10N=True, LANGUAGE_CODE='en-GB'): + self.assertTrue(dtm.history.latest().changes_display_dict["date"][1] == \ + formats.localize(date), + msg=("The date should be formatted according to Django's settings for" + " USE_L10N is True with a different LANGUAGE_CODE.")) + + def test_changes_display_dict_time(self): + timestamp = datetime.datetime(2017, 1, 10, 15, 0, tzinfo=timezone.utc) + date = datetime.date(2017, 1, 10) + time = datetime.time(12, 0) + dtm = DateTimeFieldModel(label='DateTimeField model', timestamp=timestamp, date=date, time=time, naive_dt=self.now) + dtm.save() + self.assertTrue(dtm.history.latest().changes_display_dict["time"][1] == \ +~~ dateformat.format(time, settings.TIME_FORMAT), + msg=("The time should be formatted according to Django's settings for" + " TIME_FORMAT unless USE_L10N is True.")) + time = datetime.time(6, 0) + dtm.time = time + dtm.save() + self.assertTrue(dtm.history.latest().changes_display_dict["time"][1] == \ +~~ dateformat.format(time, settings.TIME_FORMAT), + msg=("The time should be formatted according to Django's settings for" + " TIME_FORMAT unless USE_L10N is True.")) + + with self.settings(USE_L10N=True, LANGUAGE_CODE='en-GB'): + self.assertTrue(dtm.history.latest().changes_display_dict["time"][1] == \ + formats.localize(time), + msg=("The time should be formatted according to Django's settings for" + " USE_L10N is True with a different LANGUAGE_CODE.")) + + def test_update_naive_dt(self): + timestamp = datetime.datetime(2017, 1, 10, 15, 0, tzinfo=timezone.utc) + date = datetime.date(2017, 1, 10) + time = datetime.time(12, 0) + dtm = DateTimeFieldModel(label='DateTimeField model', timestamp=timestamp, date=date, time=time, naive_dt=self.now) + dtm.save() + + dtm.naive_dt = timezone.make_naive(timezone.now(), timezone=timezone.utc) + dtm.save() + + +class UnregisterTest(TestCase): + def setUp(self): + auditlog.unregister(SimpleModel) + self.obj = SimpleModel.objects.create(text='No history') + + +## ... source file continues with no further dateformat examples... + +``` + diff --git a/content/pages/examples/django/django-utils-dateparse-parse-datetime.markdown b/content/pages/examples/django/django-utils-dateparse-parse-datetime.markdown new file mode 100644 index 000000000..c78d152f1 --- /dev/null +++ b/content/pages/examples/django/django-utils-dateparse-parse-datetime.markdown @@ -0,0 +1,116 @@ +title: django.utils.dateparse parse_datetime Example Code +category: page +slug: django-utils-dateparse-parse-datetime-examples +sortorder: 500011432 +toc: False +sidebartitle: django.utils.dateparse parse_datetime +meta: Python example code for the parse_datetime callable from the django.utils.dateparse module of the Django project. + + +parse_datetime is a callable within the django.utils.dateparse module of the Django project. + + +## Example 1 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / fields.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./fields.py) + +```python +# fields.py +from collections import namedtuple +from datetime import datetime, time + +from django import forms +~~from django.utils.dateparse import parse_datetime +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +from .conf import settings +from .constants import EMPTY_VALUES +from .utils import handle_timezone +from .widgets import ( + BaseCSVWidget, + CSVWidget, + DateRangeWidget, + LookupChoiceWidget, + RangeWidget +) + + +class RangeField(forms.MultiValueField): + widget = RangeWidget + + def __init__(self, fields=None, *args, **kwargs): + if fields is None: + fields = ( + forms.DecimalField(), + forms.DecimalField()) + super().__init__(fields, *args, **kwargs) + + +## ... source file abbreviated to get to parse_datetime examples ... + + + kwargs['widget'] = widget + kwargs['help_text'] = field.help_text + super().__init__(fields, *args, **kwargs) + + def compress(self, data_list): + if len(data_list) == 2: + value, lookup_expr = data_list + if value not in EMPTY_VALUES: + if lookup_expr not in EMPTY_VALUES: + return Lookup(value=value, lookup_expr=lookup_expr) + else: + raise forms.ValidationError( + self.error_messages['lookup_required'], + code='lookup_required') + return None + + +class IsoDateTimeField(forms.DateTimeField): + ISO_8601 = 'iso-8601' + input_formats = [ISO_8601] + + def strptime(self, value, format): + value = force_str(value) + + if format == self.ISO_8601: +~~ parsed = parse_datetime(value) + if parsed is None: # Continue with other formats if doesn't match + raise ValueError + return handle_timezone(parsed) + return super().strptime(value, format) + + +class BaseCSVField(forms.Field): + base_widget_class = BaseCSVWidget + + def __init__(self, *args, **kwargs): + widget = kwargs.get('widget') or self.widget + kwargs['widget'] = self._get_widget_class(widget) + + super().__init__(*args, **kwargs) + + def _get_widget_class(self, widget): + if isinstance(widget, BaseCSVWidget) or ( + isinstance(widget, type) and + issubclass(widget, BaseCSVWidget)): + return widget + + assert isinstance(widget, type), \ + "'%s.widget' must be a widget class, not %s." \ + % (self.__class__.__name__, repr(widget)) + + +## ... source file continues with no further parse_datetime examples... + +``` + diff --git a/content/pages/examples/django/django-utils-dateparse-parse-duration.markdown b/content/pages/examples/django/django-utils-dateparse-parse-duration.markdown new file mode 100644 index 000000000..0a959cff7 --- /dev/null +++ b/content/pages/examples/django/django-utils-dateparse-parse-duration.markdown @@ -0,0 +1,118 @@ +title: django.utils.dateparse parse_duration Example Code +category: page +slug: django-utils-dateparse-parse-duration-examples +sortorder: 500011433 +toc: False +sidebartitle: django.utils.dateparse parse_duration +meta: Python example code for the parse_duration callable from the django.utils.dateparse module of the Django project. + + +parse_duration is a callable within the django.utils.dateparse module of the Django project. + + +## Example 1 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / widgets.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./widgets.py) + +```python +# widgets.py +import json +from datetime import date, datetime +from decimal import Decimal + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.utils import datetime_safe, timezone +~~from django.utils.dateparse import parse_duration +from django.utils.encoding import force_str, smart_str + + +class Widget: + def clean(self, value, row=None, *args, **kwargs): + return value + + def render(self, value, obj=None): + return force_str(value) + + +class NumberWidget(Widget): + + def is_empty(self, value): + if isinstance(value, str): + value = value.strip() + return value is None or value == "" + + def render(self, value, obj=None): + return value + + +class FloatWidget(NumberWidget): + + + +## ... source file abbreviated to get to parse_duration examples ... + + + self.formats = formats + + def clean(self, value, row=None, *args, **kwargs): + if not value: + return None + for format in self.formats: + try: + return datetime.strptime(value, format).time() + except (ValueError, TypeError): + continue + raise ValueError("Enter a valid time.") + + def render(self, value, obj=None): + if not value: + return "" + return value.strftime(self.formats[0]) + + +class DurationWidget(Widget): + + def clean(self, value, row=None, *args, **kwargs): + if not value: + return None + + try: +~~ return parse_duration(value) + except (ValueError, TypeError): + raise ValueError("Enter a valid duration.") + + def render(self, value, obj=None): + if value is None: + return "" + return str(value) + + +class SimpleArrayWidget(Widget): + + def __init__(self, separator=None): + if separator is None: + separator = ',' + self.separator = separator + super().__init__() + + def clean(self, value, row=None, *args, **kwargs): + return value.split(self.separator) if value else [] + + def render(self, value, obj=None): + return self.separator.join(str(v) for v in value) + + + + +## ... source file continues with no further parse_duration examples... + +``` + diff --git a/content/pages/examples/django/django-utils-dateparse.markdown b/content/pages/examples/django/django-utils-dateparse.markdown new file mode 100644 index 000000000..2ff8075a8 --- /dev/null +++ b/content/pages/examples/django/django-utils-dateparse.markdown @@ -0,0 +1,138 @@ +title: django.utils dateparse Example Code +category: page +slug: django-utils-dateparse-examples +sortorder: 500011416 +toc: False +sidebartitle: django.utils dateparse +meta: Python example code for the dateparse callable from the django.utils module of the Django project. + + +dateparse is a callable within the django.utils module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / utils.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/./utils.py) + +```python +# utils.py +import base64 +import importlib +import json +import random +import re +import string +import unicodedata +from collections import OrderedDict +from urllib.parse import urlsplit + +import django +from django.contrib.auth import get_user_model +from django.contrib.sites.models import Site +from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured +from django.core.serializers.json import DjangoJSONEncoder +from django.core.validators import ValidationError, validate_email +from django.db.models import FileField +from django.db.models.fields import ( + BinaryField, + DateField, + DateTimeField, + EmailField, + TimeField, +) +~~from django.utils import dateparse +from django.utils.encoding import force_bytes, force_str + + +MAX_USERNAME_SUFFIX_LENGTH = 7 +USERNAME_SUFFIX_CHARS = ( + [string.digits] * 4 + + [string.ascii_letters] * (MAX_USERNAME_SUFFIX_LENGTH - 4)) + + +def _generate_unique_username_base(txts, regex=None): + from .account.adapter import get_adapter + adapter = get_adapter() + username = None + regex = regex or r'[^\w\s@+.-]' + for txt in txts: + if not txt: + continue + username = unicodedata.normalize('NFKD', force_str(txt)) + username = username.encode('ascii', 'ignore').decode('ascii') + username = force_str(re.sub(regex, '', username).lower()) + username = username.split('@')[0] + username = username.strip() + username = re.sub(r'\s+', '_', username) + try: + + +## ... source file abbreviated to get to dateparse examples ... + + + elif isinstance(field, FileField): + if v and not isinstance(v, str): + v = v.name + try: + json.dumps(v, cls=DjangoJSONEncoder) + except TypeError: + v = field.get_prep_value(v) + k = SERIALIZED_DB_FIELD_PREFIX + k + except FieldDoesNotExist: + pass + data[k] = v + return json.loads(json.dumps(data, cls=DjangoJSONEncoder)) + + +def deserialize_instance(model, data): + ret = model() + for k, v in data.items(): + is_db_value = False + if k.startswith(SERIALIZED_DB_FIELD_PREFIX): + k = k[len(SERIALIZED_DB_FIELD_PREFIX):] + is_db_value = True + if v is not None: + try: + f = model._meta.get_field(k) + if isinstance(f, DateTimeField): +~~ v = dateparse.parse_datetime(v) + elif isinstance(f, TimeField): +~~ v = dateparse.parse_time(v) + elif isinstance(f, DateField): +~~ v = dateparse.parse_date(v) + elif isinstance(f, BinaryField): + v = force_bytes( + base64.b64decode( + force_bytes(v))) + elif is_db_value: + try: + if django.VERSION < (3, 0): + v = f.from_db_value(v, None, None, None) + else: + v = f.from_db_value(v, None, None) + except Exception: + raise ImproperlyConfigured( + "Unable to auto serialize field '{}', custom" + " serialization override required".format(k) + ) + except FieldDoesNotExist: + pass + setattr(ret, k, v) + return ret + + +def set_form_field_order(form, field_order): + if field_order is None: + return + + +## ... source file continues with no further dateparse examples... + +``` + diff --git a/content/pages/examples/django/django-utils-dates-months.markdown b/content/pages/examples/django/django-utils-dates-months.markdown new file mode 100644 index 000000000..17838edb0 --- /dev/null +++ b/content/pages/examples/django/django-utils-dates-months.markdown @@ -0,0 +1,70 @@ +title: django.utils.dates MONTHS Example Code +category: page +slug: django-utils-dates-months-examples +sortorder: 500011434 +toc: False +sidebartitle: django.utils.dates MONTHS +meta: Python example code for the MONTHS constant from the django.utils.dates module of the Django project. + + +MONTHS is a constant within the django.utils.dates module of the Django project. + + +## Example 1 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / widgets.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./widgets.py) + +```python +# widgets.py +import datetime +import re +from itertools import chain + +import django +from django import forms +from django.conf import settings +from django.forms.widgets import FILE_INPUT_CONTRADICTION +from django.template import loader +from django.utils import datetime_safe, formats +~~from django.utils.dates import MONTHS +from django.utils.encoding import force_str +from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + +from .compat import MULTIVALUE_DICT_TYPES, flatten_contexts + + +from django.forms.utils import to_current_timezone + + +RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$') + + +__all__ = ( + 'TextInput', 'PasswordInput', 'HiddenInput', 'ClearableFileInput', + 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', + 'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple', + 'RadioSelect', 'CheckboxSelectMultiple', 'SearchInput', 'RangeInput', + 'ColorInput', 'EmailInput', 'URLInput', 'PhoneNumberInput', 'NumberInput', + 'IPAddressInput', 'MultiWidget', 'Widget', 'SplitDateTimeWidget', + 'SplitHiddenDateTimeWidget', 'MultipleHiddenInput', 'SelectDateWidget', + 'SlugInput', +) + + +## ... source file continues with no further MONTHS examples... + +``` + diff --git a/content/pages/examples/django/django-utils-datetime-safe-datetime.markdown b/content/pages/examples/django/django-utils-datetime-safe-datetime.markdown new file mode 100644 index 000000000..36d4799a0 --- /dev/null +++ b/content/pages/examples/django/django-utils-datetime-safe-datetime.markdown @@ -0,0 +1,154 @@ +title: django.utils.datetime_safe datetime Example Code +category: page +slug: django-utils-datetime-safe-datetime-examples +sortorder: 500011435 +toc: False +sidebartitle: django.utils.datetime_safe datetime +meta: Python example code for the datetime callable from the django.utils.datetime_safe module of the Django project. + + +datetime is a callable within the django.utils.datetime_safe module of the Django project. + + +## Example 1 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / backends / whoosh_backend.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/backends/whoosh_backend.py) + +```python +# whoosh_backend.py +import json +import os +import re +import shutil +import threading +import warnings + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +~~from django.utils.datetime_safe import datetime +from django.utils.encoding import force_str + +from haystack.backends import ( + BaseEngine, + BaseSearchBackend, + BaseSearchQuery, + EmptyResults, + log_query, +) +from haystack.constants import ( + DJANGO_CT, + DJANGO_ID, + FUZZY_WHOOSH_MAX_EDITS, + FUZZY_WHOOSH_MIN_PREFIX, + ID, +) +from haystack.exceptions import MissingDependency, SearchBackendError, SkipDocument +from haystack.inputs import Clean, Exact, PythonData, Raw +from haystack.models import SearchResult +from haystack.utils import get_identifier, get_model_ct +from haystack.utils import log as logging +from haystack.utils.app_loading import haystack_get_model + +try: + + +## ... source file abbreviated to get to datetime examples ... + + + + if not query_string: + return spelling_suggestion + + for rev_word in self.RESERVED_WORDS: + cleaned_query = cleaned_query.replace(rev_word, "") + + for rev_char in self.RESERVED_CHARACTERS: + cleaned_query = cleaned_query.replace(rev_char, "") + + query_words = cleaned_query.split() + suggested_words = [] + + for word in query_words: + suggestions = corrector.suggest(word, limit=1) + + if len(suggestions) > 0: + suggested_words.append(suggestions[0]) + + spelling_suggestion = " ".join(suggested_words) + return spelling_suggestion + + def _from_python(self, value): + if hasattr(value, "strftime"): + if not hasattr(value, "hour"): +~~ value = datetime(value.year, value.month, value.day, 0, 0, 0) + elif isinstance(value, bool): + if value: + value = "true" + else: + value = "false" + elif isinstance(value, (list, tuple)): + value = ",".join([force_str(v) for v in value]) + elif isinstance(value, (int, float)): + pass + else: + value = force_str(value) + return value + + def _to_python(self, value): + if value == "true": + return True + elif value == "false": + return False + + if value and isinstance(value, str): + possible_datetime = DATETIME_REGEX.search(value) + + if possible_datetime: + date_values = possible_datetime.groupdict() + + for dk, dv in date_values.items(): + date_values[dk] = int(dv) + +~~ return datetime( + date_values["year"], + date_values["month"], + date_values["day"], + date_values["hour"], + date_values["minute"], + date_values["second"], + ) + + try: + converted_value = json.loads(value) + + if isinstance( + converted_value, + (list, tuple, set, dict, int, float, complex), + ): + return converted_value + except: + pass + + return value + + +class WhooshSearchQuery(BaseSearchQuery): + def _convert_datetime(self, date): + + +## ... source file continues with no further datetime examples... + +``` + diff --git a/content/pages/examples/django/django-utils-datetime-safe.markdown b/content/pages/examples/django/django-utils-datetime-safe.markdown new file mode 100644 index 000000000..2ba481e1e --- /dev/null +++ b/content/pages/examples/django/django-utils-datetime-safe.markdown @@ -0,0 +1,440 @@ +title: django.utils datetime_safe Example Code +category: page +slug: django-utils-datetime-safe-examples +sortorder: 500011417 +toc: False +sidebartitle: django.utils datetime_safe +meta: Python example code for the datetime_safe callable from the django.utils module of the Django project. + + +datetime_safe is a callable within the django.utils module of the Django project. + + +## Example 1 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / widgets.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./widgets.py) + +```python +# widgets.py +import datetime +import re +from itertools import chain + +import django +from django import forms +from django.conf import settings +from django.forms.widgets import FILE_INPUT_CONTRADICTION +from django.template import loader +~~from django.utils import datetime_safe, formats +from django.utils.dates import MONTHS +from django.utils.encoding import force_str +from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + +from .compat import MULTIVALUE_DICT_TYPES, flatten_contexts + + +from django.forms.utils import to_current_timezone + + +RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$') + + +__all__ = ( + 'TextInput', 'PasswordInput', 'HiddenInput', 'ClearableFileInput', + 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', + 'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple', + 'RadioSelect', 'CheckboxSelectMultiple', 'SearchInput', 'RangeInput', + 'ColorInput', 'EmailInput', 'URLInput', 'PhoneNumberInput', 'NumberInput', + 'IPAddressInput', 'MultiWidget', 'Widget', 'SplitDateTimeWidget', + 'SplitHiddenDateTimeWidget', 'MultipleHiddenInput', 'SelectDateWidget', + 'SlugInput', + + +## ... source file abbreviated to get to datetime_safe examples ... + + + template_name = 'floppyforms/textarea.html' + rows = 10 + cols = 40 + + def __init__(self, attrs=None): + default_attrs = {'cols': self.cols, 'rows': self.rows} + if attrs: + default_attrs.update(attrs) + super(Textarea, self).__init__(default_attrs) + + def format_value(self, value): + return conditional_escape(force_str(value)) + + +class DateInput(Input): + template_name = 'floppyforms/date.html' + input_type = 'date' + supports_microseconds = False + + def __init__(self, attrs=None, format=None): + super(DateInput, self).__init__(attrs) + self.format = '%Y-%m-%d' + + def format_value(self, value): + if hasattr(value, 'strftime'): +~~ value = datetime_safe.new_date(value) + return value.strftime(self.format) + return value + + if django.VERSION < (1, 6): + def _has_changed(self, initial, data): + try: + input_format = formats.get_format('DATE_INPUT_FORMATS')[0] + initial = datetime.datetime.strptime(initial, input_format).date() + except (TypeError, ValueError): + pass + return super(DateInput, self)._has_changed( + self._format_value(initial), data + ) + + +class DateTimeInput(Input): + template_name = 'floppyforms/datetime.html' + input_type = 'datetime' + supports_microseconds = False + + def __init__(self, attrs=None, format=None): + super(DateTimeInput, self).__init__(attrs) + if format: + self.format = format + self.manual_format = True + else: + self.format = formats.get_format('DATETIME_INPUT_FORMATS')[0] + self.manual_format = False + + def format_value(self, value): + if hasattr(value, 'strftime'): +~~ value = datetime_safe.new_datetime(value) + return value.strftime(self.format) + return value + + if django.VERSION < (1, 6): + def _has_changed(self, initial, data): + try: + input_format = formats.get_format('DATETIME_INPUT_FORMATS')[0] + initial = datetime.datetime.strptime(initial, input_format) + except (TypeError, ValueError): + pass + return super(DateTimeInput, self)._has_changed( + self._format_value(initial), data + ) + + +class TimeInput(Input): + template_name = 'floppyforms/time.html' + input_type = 'time' + supports_microseconds = False + + def __init__(self, attrs=None, format=None): + super(TimeInput, self).__init__(attrs) + if format: + self.format = format + + +## ... source file abbreviated to get to datetime_safe examples ... + + + context['day_choices'] = [(i, i) for i in range(1, 32)] + context['day_val'] = day_val + + + if self.required is False: + context['year_choices'].insert(0, self.none_value) + context['month_choices'].insert(0, self.none_value) + context['day_choices'].insert(0, self.none_value) + + return loader.render_to_string(self.template_name, context) + + def value_from_datadict(self, data, files, name): + y = data.get(self.year_field % name) + m = data.get(self.month_field % name) + d = data.get(self.day_field % name) + if y == m == d == "0": + return None + if y and m and d: + if settings.USE_L10N: + input_format = formats.get_format('DATE_INPUT_FORMATS')[0] + try: + date_value = datetime.date(int(y), int(m), int(d)) + except ValueError: + return '%s-%s-%s' % (y, m, d) + else: +~~ date_value = datetime_safe.new_date(date_value) + return date_value.strftime(input_format) + else: + return '%s-%s-%s' % (y, m, d) + return data.get(name, None) + + + +## ... source file continues with no further datetime_safe examples... + +``` + + +## Example 2 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / fields.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./fields.py) + +```python +# fields.py +import re +from inspect import ismethod + +from django.template import loader +~~from django.utils import datetime_safe + +from haystack.exceptions import SearchFieldError +from haystack.utils import get_model_ct_tuple + + +class NOT_PROVIDED: + pass + + +DATE_REGEX = re.compile( + r"^(?P\d{4})-(?P\d{2})-(?P\d{2})(?:|T00:00:00Z?)$" +) +DATETIME_REGEX = re.compile( + r"^(?P\d{4})-(?P\d{2})-(?P\d{2})(T|\s+)(?P\d{2}):(?P\d{2}):(?P\d{2}).*?$" +) + + + + +class SearchField(object): + + field_type = None + + def __init__( + + +## ... source file abbreviated to get to datetime_safe examples ... + + + + return bool(value) + + +class DateField(SearchField): + field_type = "date" + + def __init__(self, **kwargs): + if kwargs.get("facet_class") is None: + kwargs["facet_class"] = FacetDateField + + super(DateField, self).__init__(**kwargs) + + def prepare(self, obj): + return self.convert(super(DateField, self).prepare(obj)) + + def convert(self, value): + if value is None: + return None + + if isinstance(value, str): + match = DATE_REGEX.search(value) + + if match: + data = match.groupdict() +~~ return datetime_safe.date( + int(data["year"]), int(data["month"]), int(data["day"]) + ) + else: + raise SearchFieldError( + "Date provided to '%s' field doesn't appear to be a valid date string: '%s'" + % (self.instance_name, value) + ) + + return value + + +class DateTimeField(SearchField): + field_type = "datetime" + + def __init__(self, **kwargs): + if kwargs.get("facet_class") is None: + kwargs["facet_class"] = FacetDateTimeField + + super(DateTimeField, self).__init__(**kwargs) + + def prepare(self, obj): + return self.convert(super(DateTimeField, self).prepare(obj)) + + def convert(self, value): + if value is None: + return None + + if isinstance(value, str): + match = DATETIME_REGEX.search(value) + + if match: + data = match.groupdict() +~~ return datetime_safe.datetime( + int(data["year"]), + int(data["month"]), + int(data["day"]), + int(data["hour"]), + int(data["minute"]), + int(data["second"]), + ) + else: + raise SearchFieldError( + "Datetime provided to '%s' field doesn't appear to be a valid datetime string: '%s'" + % (self.instance_name, value) + ) + + return value + + +class MultiValueField(SearchField): + field_type = "string" + + def __init__(self, **kwargs): + if kwargs.get("facet_class") is None: + kwargs["facet_class"] = FacetMultiValueField + + if kwargs.get("use_template") is True: + + +## ... source file continues with no further datetime_safe examples... + +``` + + +## Example 3 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / widgets.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./widgets.py) + +```python +# widgets.py +import json +from datetime import date, datetime +from decimal import Decimal + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +~~from django.utils import datetime_safe, timezone +from django.utils.dateparse import parse_duration +from django.utils.encoding import force_str, smart_str + + +class Widget: + def clean(self, value, row=None, *args, **kwargs): + return value + + def render(self, value, obj=None): + return force_str(value) + + +class NumberWidget(Widget): + + def is_empty(self, value): + if isinstance(value, str): + value = value.strip() + return value is None or value == "" + + def render(self, value, obj=None): + return value + + +class FloatWidget(NumberWidget): + + +## ... source file abbreviated to get to datetime_safe examples ... + + + formats = ("%Y-%m-%d",) + else: + formats = settings.DATE_INPUT_FORMATS + else: + formats = (format,) + self.formats = formats + + def clean(self, value, row=None, *args, **kwargs): + if not value: + return None + if isinstance(value, date): + return value + for format in self.formats: + try: + return datetime.strptime(value, format).date() + except (ValueError, TypeError): + continue + raise ValueError("Enter a valid date.") + + def render(self, value, obj=None): + if not value: + return "" + try: + return value.strftime(self.formats[0]) + except: +~~ return datetime_safe.new_date(value).strftime(self.formats[0]) + + +class DateTimeWidget(Widget): + + def __init__(self, format=None): + if format is None: + if not settings.DATETIME_INPUT_FORMATS: + formats = ("%Y-%m-%d %H:%M:%S",) + else: + formats = settings.DATETIME_INPUT_FORMATS + else: + formats = (format,) + self.formats = formats + + def clean(self, value, row=None, *args, **kwargs): + if not value: + return None + if isinstance(value, datetime): + return value + for format in self.formats: + try: + dt = datetime.strptime(value, format) + if settings.USE_TZ: + dt = timezone.make_aware(dt, + + +## ... source file continues with no further datetime_safe examples... + +``` + diff --git a/content/pages/examples/django/django-utils-decorators-method-decorator.markdown b/content/pages/examples/django/django-utils-decorators-method-decorator.markdown new file mode 100644 index 000000000..fe75a221e --- /dev/null +++ b/content/pages/examples/django/django-utils-decorators-method-decorator.markdown @@ -0,0 +1,1193 @@ +title: django.utils.decorators method_decorator Example Code +category: page +slug: django-utils-decorators-method-decorator-examples +sortorder: 500011436 +toc: False +sidebartitle: django.utils.decorators method_decorator +meta: Python example code for the method_decorator callable from the django.utils.decorators module of the Django project. + + +method_decorator is a callable within the django.utils.decorators module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / views.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py) + +```python +# views.py +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.sites.shortcuts import get_current_site +from django.http import ( + Http404, + HttpResponsePermanentRedirect, + HttpResponseRedirect, +) +from django.shortcuts import redirect +from django.urls import reverse, reverse_lazy +~~from django.utils.decorators import method_decorator +from django.views.decorators.debug import sensitive_post_parameters +from django.views.generic.base import TemplateResponseMixin, TemplateView, View +from django.views.generic.edit import FormView + +from ..exceptions import ImmediateHttpResponse +from ..utils import get_form_class, get_request_param +from . import app_settings, signals +from .adapter import get_adapter +from .forms import ( + AddEmailForm, + ChangePasswordForm, + LoginForm, + ResetPasswordForm, + ResetPasswordKeyForm, + SetPasswordForm, + SignupForm, + UserTokenForm, +) +from .models import EmailAddress, EmailConfirmation, EmailConfirmationHMAC +from .utils import ( + complete_signup, + get_login_redirect_url, + get_next_redirect_url, + logout_on_password_change, + passthrough_next_redirect_url, + perform_login, + sync_user_email_addresses, + url_str_to_user_pk, +) + + +INTERNAL_RESET_URL_KEY = "set-password" +INTERNAL_RESET_SESSION_KEY = "_password_reset_key" + + +~~sensitive_post_parameters_m = method_decorator( + sensitive_post_parameters( + 'oldpassword', 'password', 'password1', 'password2')) + + +def _ajax_response(request, response, form=None, data=None): + adapter = get_adapter(request) + if adapter.is_ajax(request): + if (isinstance(response, HttpResponseRedirect) or isinstance( + response, HttpResponsePermanentRedirect)): + redirect_to = response['Location'] + else: + redirect_to = None + response = adapter.ajax_response( + request, + response, + form=form, + data=data, + redirect_to=redirect_to) + return response + + +class RedirectAuthenticatedUserMixin(object): + + def dispatch(self, request, *args, **kwargs): + + +## ... source file continues with no further method_decorator examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / admin / placeholderadmin.py**](https://github.com/divio/django-cms/blob/develop/cms/admin/placeholderadmin.py) + +```python +# placeholderadmin.py +import uuid +import warnings + +from django.conf.urls import url +from django.contrib.admin.helpers import AdminForm +from django.contrib.admin.utils import get_deleted_objects +from django.core.exceptions import PermissionDenied +from django.db import router, transaction +from django.http import ( + HttpResponse, + HttpResponseBadRequest, + HttpResponseForbidden, + HttpResponseNotFound, + HttpResponseRedirect, +) +from django.shortcuts import get_list_or_404, get_object_or_404, render +from django.template.response import TemplateResponse +~~from django.utils.decorators import method_decorator +from django.utils.encoding import force_text +from django.utils import translation +from django.utils.translation import ugettext as _ +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.decorators.http import require_POST + +from six.moves.urllib.parse import parse_qsl, urlparse + +from six import get_unbound_function, get_method_function + +from cms import operations +from cms.admin.forms import PluginAddValidationForm +from cms.constants import SLUG_REGEXP +from cms.exceptions import PluginLimitReached +from cms.models.placeholdermodel import Placeholder +from cms.models.placeholderpluginmodel import PlaceholderReference +from cms.models.pluginmodel import CMSPlugin +from cms.plugin_pool import plugin_pool +from cms.signals import pre_placeholder_operation, post_placeholder_operation +from cms.toolbar.utils import get_plugin_tree_as_json +from cms.utils import copy_plugins, get_current_site +from cms.utils.compat import DJANGO_2_0 +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import get_language_code, get_language_list + + +## ... source file abbreviated to get to method_decorator examples ... + + + 'placeholder': plugin_data['placeholder_id'], + 'parent': plugin_data.get('plugin_parent', None), + 'plugin_type': plugin_data['plugin_type'], + 'position': plugin_data['position'], + } + + response = plugin_instance.add_view(request) + + plugin = getattr(plugin_instance, 'saved_object', None) + + if plugin: + plugin.placeholder.mark_as_dirty(plugin.language, clear_cache=False) + + if plugin_instance._operation_token: + tree_order = placeholder.get_plugin_tree_order(plugin.parent_id) + self._send_post_placeholder_operation( + request, + operation=operations.ADD_PLUGIN, + token=plugin_instance._operation_token, + plugin=plugin, + placeholder=plugin.placeholder, + tree_order=tree_order, + ) + return response + +~~ @method_decorator(require_POST) + @xframe_options_sameorigin + @transaction.atomic + def copy_plugins(self, request): + source_placeholder_id = request.POST['source_placeholder_id'] + target_language = request.POST['target_language'] + target_placeholder_id = request.POST['target_placeholder_id'] + source_placeholder = get_object_or_404(Placeholder, pk=source_placeholder_id) + target_placeholder = get_object_or_404(Placeholder, pk=target_placeholder_id) + + if not target_language or not target_language in get_language_list(): + return HttpResponseBadRequest(force_text(_("Language must be set to a supported language!"))) + + copy_to_clipboard = target_placeholder.pk == request.toolbar.clipboard.pk + source_plugin_id = request.POST.get('source_plugin_id', None) + + if copy_to_clipboard and source_plugin_id: + new_plugin = self._copy_plugin_to_clipboard( + request, + source_placeholder, + target_placeholder, + ) + new_plugins = [new_plugin] + elif copy_to_clipboard: + new_plugin = self._copy_placeholder_to_clipboard( + + +## ... source file abbreviated to get to method_decorator examples ... + + + obj = self._get_plugin_from_id(plugin_id) + + plugin_instance = obj.get_plugin_class_instance(admin=self.admin_site) + + if not self.has_change_plugin_permission(request, obj): + return HttpResponseForbidden(force_text(_("You do not have permission to edit this plugin"))) + + response = plugin_instance.change_view(request, str(plugin_id)) + + plugin = getattr(plugin_instance, 'saved_object', None) + + if plugin: + plugin.placeholder.mark_as_dirty(plugin.language, clear_cache=False) + + if plugin_instance._operation_token: + self._send_post_placeholder_operation( + request, + operation=operations.CHANGE_PLUGIN, + token=plugin_instance._operation_token, + old_plugin=obj, + new_plugin=plugin, + placeholder=plugin.placeholder, + ) + return response + +~~ @method_decorator(require_POST) + @xframe_options_sameorigin + @transaction.atomic + def move_plugin(self, request): + try: + plugin_id = get_int(request.POST.get('plugin_id')) + except TypeError: + raise RuntimeError("'plugin_id' is a required parameter.") + + plugin = self._get_plugin_from_id(plugin_id) + + try: + placeholder_id = get_int(request.POST.get('placeholder_id')) + except TypeError: + raise RuntimeError("'placeholder_id' is a required parameter.") + except ValueError: + raise RuntimeError("'placeholder_id' must be an integer string.") + + placeholder = Placeholder.objects.get(pk=placeholder_id) + + parent_id = get_int(request.POST.get('plugin_parent', ""), None) + target_language = request.POST['target_language'] + move_a_copy = request.POST.get('move_a_copy') + move_a_copy = (move_a_copy and move_a_copy != "0" and + move_a_copy.lower() != "false") + + +## ... source file continues with no further method_decorator examples... + +``` + + +## Example 3 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / admin.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./admin.py) + +```python +# admin.py +from datetime import datetime + +import django +from django import forms +from django.conf import settings +from django.conf.urls import url +from django.contrib import admin, messages +from django.contrib.admin.models import ADDITION, CHANGE, DELETION, LogEntry +from django.contrib.auth import get_permission_codename +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import PermissionDenied +from django.http import HttpResponse, HttpResponseRedirect +from django.template.response import TemplateResponse +from django.urls import reverse +~~from django.utils.decorators import method_decorator +from django.utils.encoding import force_str +from django.utils.module_loading import import_string +from django.utils.translation import gettext_lazy as _ +from django.views.decorators.http import require_POST + +from .formats.base_formats import DEFAULT_FORMATS +from .forms import ConfirmImportForm, ExportForm, ImportForm, export_action_form_factory +from .resources import modelresource_factory +from .results import RowResult +from .signals import post_export, post_import +from .tmp_storages import TempFolderStorage + +SKIP_ADMIN_LOG = getattr(settings, 'IMPORT_EXPORT_SKIP_ADMIN_LOG', False) +TMP_STORAGE_CLASS = getattr(settings, 'IMPORT_EXPORT_TMP_STORAGE_CLASS', + TempFolderStorage) + + +if isinstance(TMP_STORAGE_CLASS, str): + TMP_STORAGE_CLASS = import_string(TMP_STORAGE_CLASS) + + +class ImportExportMixinBase: + def get_model_info(self): + app_label = self.model._meta.app_label + + +## ... source file abbreviated to get to method_decorator examples ... + + + name='%s_%s_process_import' % info), + url(r'^import/$', + self.admin_site.admin_view(self.import_action), + name='%s_%s_import' % info), + ] + return my_urls + urls + + def get_resource_kwargs(self, request, *args, **kwargs): + return {} + + def get_import_resource_kwargs(self, request, *args, **kwargs): + return self.get_resource_kwargs(request, *args, **kwargs) + + def get_resource_class(self): + if not self.resource_class: + return modelresource_factory(self.model) + else: + return self.resource_class + + def get_import_resource_class(self): + return self.get_resource_class() + + def get_import_formats(self): + return [f for f in self.formats if f().can_import()] + +~~ @method_decorator(require_POST) + def process_import(self, request, *args, **kwargs): + if not self.has_import_permission(request): + raise PermissionDenied + + form_type = self.get_confirm_import_form() + confirm_form = form_type(request.POST) + if confirm_form.is_valid(): + import_formats = self.get_import_formats() + input_format = import_formats[ + int(confirm_form.cleaned_data['input_format']) + ]() + tmp_storage = self.get_tmp_storage_class()(name=confirm_form.cleaned_data['import_file_name']) + data = tmp_storage.read(input_format.get_read_mode()) + if not input_format.is_binary() and self.from_encoding: + data = force_str(data, self.from_encoding) + dataset = input_format.create_dataset(data) + + result = self.process_dataset(dataset, confirm_form, request, *args, **kwargs) + + tmp_storage.remove() + + return self.process_result(result, request) + + def process_dataset(self, dataset, confirm_form, request, *args, **kwargs): + + +## ... source file continues with no further method_decorator examples... + +``` + + +## Example 4 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / views / introspect.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/views/introspect.py) + +```python +# introspect.py +import calendar +import json + +from django.core.exceptions import ObjectDoesNotExist +from django.http import HttpResponse +~~from django.utils.decorators import method_decorator +from django.views.decorators.csrf import csrf_exempt + +from oauth2_provider.models import get_access_token_model +from oauth2_provider.views import ClientProtectedScopedResourceView + + +~~@method_decorator(csrf_exempt, name="dispatch") +class IntrospectTokenView(ClientProtectedScopedResourceView): + required_scopes = ["introspection"] + + @staticmethod + def get_token_response(token_value=None): + try: + token = get_access_token_model().objects.select_related( + "user", "application" + ).get(token=token_value) + except ObjectDoesNotExist: + return HttpResponse( + content=json.dumps({"active": False}), + status=401, + content_type="application/json" + ) + else: + if token.is_valid(): + data = { + "active": True, + "scope": token.scope, + "exp": int(calendar.timegm(token.expires.timetuple())), + } + if token.application: + data["client_id"] = token.application.client_id + + +## ... source file continues with no further method_decorator examples... + +``` + + +## Example 5 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / views.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./views.py) + +```python +# views.py +import re +import six +from collections import Counter + +try: + from django.urls import reverse_lazy +except ImportError: + from django.core.urlresolvers import reverse_lazy + +import django +from django.db import DatabaseError +from django.db.models import Count +from django.forms.models import model_to_dict +from django.http import HttpResponse, JsonResponse, HttpResponseRedirect, Http404 +from django.shortcuts import get_object_or_404, render +from django.views.decorators.http import require_POST +~~from django.utils.decorators import method_decorator +from django.views.generic import ListView +from django.views.generic.base import View +from django.views.generic.edit import CreateView, DeleteView +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.core.exceptions import ImproperlyConfigured +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.auth.views import LoginView + +from explorer import app_settings +from explorer.connections import connections +from explorer.exporters import get_exporter_class +from explorer.forms import QueryForm +from explorer.models import Query, QueryLog, MSG_FAILED_BLACKLIST +from explorer.tasks import execute_query +from explorer.utils import ( + url_get_rows, + url_get_query_id, + url_get_log_id, + url_get_params, + safe_login_prompt, + fmt_sql, + allowed_query_pks, + url_get_show, + url_get_fullscreen + + +## ... source file abbreviated to get to method_decorator examples ... + + +class StreamQueryView(PermissionRequiredMixin, View): + + permission_required = 'view_permission' + + def get(self, request, query_id, *args, **kwargs): + query = get_object_or_404(Query, pk=query_id) + return _export(request, query, download=False) + + +class EmailCsvQueryView(PermissionRequiredMixin, View): + + permission_required = 'view_permission' + + def post(self, request, query_id, *args, **kwargs): + if request.is_ajax(): + email = request.POST.get('email', None) + if email: + execute_query.delay(query_id, email) + return JsonResponse({'message': 'message was sent successfully'}) + return JsonResponse({}, status=403) + + +class SchemaView(PermissionRequiredMixin, View): + permission_required = 'change_permission' + +~~ @method_decorator(xframe_options_sameorigin) + def dispatch(self, *args, **kwargs): + return super(SchemaView, self).dispatch(*args, **kwargs) + + def get(self, request, *args, **kwargs): + connection = kwargs.get('connection') + if connection not in connections: + raise Http404 + schema = schema_info(connection) + if schema: + return render(None, 'explorer/schema.html', + {'schema': schema_info(connection)}) + else: + return render(None, 'explorer/schema_building.html') + + +@require_POST +def format_sql(request): + sql = request.POST.get('sql', '') + formatted = fmt_sql(sql) + return JsonResponse({"formatted": formatted}) + + +class ListQueryView(PermissionRequiredMixin, ExplorerContextMixin, ListView): + + + +## ... source file continues with no further method_decorator examples... + +``` + + +## Example 6 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / article.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/article.py) + +```python +# article.py +import difflib +import logging +from urllib.parse import urljoin + +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.db import transaction +from django.db.models import Q +from django.http import Http404 +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.shortcuts import render +from django.urls import reverse +~~from django.utils.decorators import method_decorator +from django.utils.translation import gettext as _ +from django.utils.translation import ngettext +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.generic import DetailView +from django.views.generic import FormView +from django.views.generic import ListView +from django.views.generic import RedirectView +from django.views.generic import TemplateView +from django.views.generic import View +from wiki import editors +from wiki import forms +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.exceptions import NoRootURL +from wiki.core.paginator import WikiPaginator +from wiki.core.plugins import registry as plugin_registry +from wiki.core.utils import object_to_json_response +from wiki.decorators import get_article +from wiki.views.mixins import ArticleMixin + +log = logging.getLogger(__name__) + + +class ArticleView(ArticleMixin, TemplateView): + + template_name = "wiki/view.html" + +~~ @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + def get_context_data(self, **kwargs): + kwargs["selected_tab"] = "view" + return ArticleMixin.get_context_data(self, **kwargs) + + +class Create(FormView, ArticleMixin): + form_class = forms.CreateForm + template_name = "wiki/create.html" + +~~ @method_decorator(get_article(can_write=True, can_create=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + def get_form(self, form_class=None): + if form_class is None: + form_class = self.get_form_class() + kwargs = self.get_form_kwargs() + initial = kwargs.get("initial", {}) + initial["slug"] = self.request.GET.get("slug", None) + kwargs["initial"] = initial + form = form_class(self.request, self.urlpath, **kwargs) + form.fields["slug"].widget = forms.TextInputPrepend( + prepend="/" + self.urlpath.path, + attrs={ + "pattern": "[a-z0-9_-]+" + if not settings.URL_CASE_SENSITIVE + else "[a-zA-Z0-9_-]+", + "title": "Lowercase letters, numbers, hyphens and underscores" + if not settings.URL_CASE_SENSITIVE + else "Letters, numbers, hyphens and underscores", + }, + ) + return form + + + +## ... source file abbreviated to get to method_decorator examples ... + + + messages.error( + self.request, _("There was an error creating this article.") + ) + return redirect("wiki:get", "") + + return self.get_success_url() + + def get_success_url(self): + return redirect("wiki:get", self.newpath.path) + + def get_context_data(self, **kwargs): + c = ArticleMixin.get_context_data(self, **kwargs) + c["form"] = self.get_form() + c["parent_urlpath"] = self.urlpath + c["parent_article"] = self.article + c["create_form"] = c.pop("form", None) + c["editor"] = editors.getEditor() + return c + + +class Delete(FormView, ArticleMixin): + + form_class = forms.DeleteForm + template_name = "wiki/delete.html" + +~~ @method_decorator(get_article(can_write=True, not_locked=True, can_delete=True)) + def dispatch(self, request, article, *args, **kwargs): + return self.dispatch1(request, article, *args, **kwargs) + + def dispatch1(self, request, article, *args, **kwargs): + urlpath = kwargs.get("urlpath", None) + self.next = "" + self.cannot_delete_root = False + if urlpath and urlpath.parent: + self.next = reverse("wiki:get", kwargs={"path": urlpath.parent.path}) + elif urlpath: + self.cannot_delete_root = True + else: + for art_obj in article.articleforobject_set.filter(is_mptt=True): + if art_obj.content_object.parent: + self.next = reverse( + "wiki:get", + kwargs={"article_id": art_obj.content_object.parent.article.id}, + ) + else: + self.cannot_delete_root = True + + return super().dispatch(request, article, *args, **kwargs) + + def get_initial(self): + + +## ... source file abbreviated to get to method_decorator examples ... + + + return self.get_success_url() + + def get_success_url(self): + return redirect(self.next) + + def get_context_data(self, **kwargs): + cannot_delete_children = False + if self.children_slice and not self.article.can_moderate(self.request.user): + cannot_delete_children = True + + kwargs["delete_form"] = self.get_form() + kwargs["form"] = kwargs["delete_form"] + kwargs["cannot_delete_root"] = self.cannot_delete_root + kwargs["delete_children"] = self.children_slice[:20] + kwargs["delete_children_more"] = len(self.children_slice) > 20 + kwargs["cannot_delete_children"] = cannot_delete_children + return super().get_context_data(**kwargs) + + +class Edit(ArticleMixin, FormView): + + + form_class = forms.EditForm + template_name = "wiki/edit.html" + +~~ @method_decorator(get_article(can_write=True, not_locked=True)) + def dispatch(self, request, article, *args, **kwargs): + self.orig_content = kwargs.pop("content", None) + self.sidebar_plugins = plugin_registry.get_sidebar() + self.sidebar = [] + return super().dispatch(request, article, *args, **kwargs) + + def get_initial(self): + initial = FormView.get_initial(self) + + for field_name in ["title", "content"]: + session_key = "unsaved_article_%s_%d" % (field_name, self.article.id) + if session_key in self.request.session: + content = self.request.session[session_key] + initial[field_name] = content + del self.request.session[session_key] + return initial + + def get_form(self, form_class=None): + if form_class is None: + form_class = self.get_form_class() + kwargs = self.get_form_kwargs() + if ( + self.request.POST.get("save", "") != "1" + and self.request.POST.get("preview") != "1" + + +## ... source file abbreviated to get to method_decorator examples ... + + + self.article.add_revision(revision) + messages.success( + self.request, _("A new revision of the article was successfully added.") + ) + return self.get_success_url() + + def get_success_url(self): + if self.urlpath: + return redirect("wiki:get", path=self.urlpath.path) + return redirect("wiki:get", article_id=self.article.id) + + def get_context_data(self, **kwargs): + kwargs["form"] = self.get_form() + kwargs["edit_form"] = kwargs["form"] + kwargs["editor"] = editors.getEditor() + kwargs["selected_tab"] = "edit" + kwargs["sidebar"] = self.sidebar + return super().get_context_data(**kwargs) + + +class Move(ArticleMixin, FormView): + + form_class = forms.MoveForm + template_name = "wiki/move.html" + +~~ @method_decorator(login_required) +~~ @method_decorator(get_article(can_write=True, not_locked=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + def get_form(self, form_class=None): + if form_class is None: + form_class = self.get_form_class() + kwargs = self.get_form_kwargs() + return form_class(**kwargs) + + def get_context_data(self, **kwargs): + kwargs["form"] = self.get_form() + kwargs["root_path"] = models.URLPath.root() + return super().get_context_data(**kwargs) + + @transaction.atomic + def form_valid(self, form): + if not self.urlpath.parent: + messages.error( + self.request, + _("This article cannot be moved because it is a root article."), + ) + return redirect("wiki:get", article_id=self.article.id) + + dest_path = get_object_or_404( + + +## ... source file abbreviated to get to method_decorator examples ... + + + _("Created redirect (auto)"), + ) + urlpath_new.moved_to = descendant + urlpath_new.save() + + messages.success( + self.request, + ngettext( + "Article successfully moved! Created {n} redirect.", + "Article successfully moved! Created {n} redirects.", + len(descendants), + ).format(n=len(descendants)), + ) + + else: + messages.success(self.request, _("Article successfully moved!")) + return redirect("wiki:get", path=self.urlpath.path) + + +class Deleted(Delete): + + + template_name = "wiki/deleted.html" + form_class = forms.DeleteForm + +~~ @method_decorator(get_article(can_read=True, deleted_contents=True)) + def dispatch(self, request, article, *args, **kwargs): + + self.urlpath = kwargs.get("urlpath", None) + self.article = article + + if self.urlpath: + deleted_ancestor = self.urlpath.first_deleted_ancestor() + if deleted_ancestor is None: + return redirect("wiki:get", path=self.urlpath.path) + elif deleted_ancestor != self.urlpath: + return redirect("wiki:deleted", path=deleted_ancestor.path) + + else: + if not article.current_revision.deleted: + return redirect("wiki:get", article_id=article.id) + + if request.GET.get("restore", False): + can_restore = not article.current_revision.locked and article.can_delete( + request.user + ) + can_restore = can_restore or article.can_moderate(request.user) + + if can_restore: + revision = models.ArticleRevision() + + +## ... source file abbreviated to get to method_decorator examples ... + + + _('The article "%s" and its children are now restored.') + % revision.title, + ) + if self.urlpath: + return redirect("wiki:get", path=self.urlpath.path) + else: + return redirect("wiki:get", article_id=article.id) + + return super().dispatch1(request, article, *args, **kwargs) + + def get_initial(self): + return { + "revision": self.article.current_revision, + "purge": True, + } + + def get_context_data(self, **kwargs): + kwargs["purge_form"] = self.get_form() + kwargs["form"] = kwargs["purge_form"] + return super().get_context_data(**kwargs) + + +class Source(ArticleMixin, TemplateView): + template_name = "wiki/source.html" + +~~ @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + def get_context_data(self, **kwargs): + kwargs["selected_tab"] = "source" + return super().get_context_data(**kwargs) + + +class History(ListView, ArticleMixin): + + template_name = "wiki/history.html" + allow_empty = True + context_object_name = "revisions" + paginator_class = WikiPaginator + paginate_by = 10 + + def get_queryset(self): + return models.ArticleRevision.objects.filter(article=self.article).order_by( + "-created" + ) + + def get_context_data(self, **kwargs): + kwargs_article = ArticleMixin.get_context_data(self, **kwargs) + kwargs_listview = ListView.get_context_data(self, **kwargs) + kwargs.update(kwargs_article) + kwargs.update(kwargs_listview) + kwargs["selected_tab"] = "history" + return kwargs + +~~ @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + +class Dir(ListView, ArticleMixin): + + template_name = "wiki/dir.html" + allow_empty = True + context_object_name = "directory" + model = models.URLPath + paginator_class = WikiPaginator + paginate_by = 30 + +~~ @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + self.filter_form = forms.DirFilterForm(request.GET) + if self.filter_form.is_valid(): + self.query = self.filter_form.cleaned_data["query"] + else: + self.query = None + return super().dispatch(request, article, *args, **kwargs) + + def get_queryset(self): + children = self.urlpath.get_children().can_read(self.request.user) + if self.query: + children = children.filter( + Q(article__current_revision__title__icontains=self.query) + | Q(slug__icontains=self.query) + ) + if not self.article.can_moderate(self.request.user): + children = children.active() + children = children.select_related_common().order_by( + "article__current_revision__title" + ) + return children + + def get_context_data(self, **kwargs): + kwargs_article = ArticleMixin.get_context_data(self, **kwargs) + + +## ... source file abbreviated to get to method_decorator examples ... + + + articles = articles.active().can_read(self.request.user) + return articles.order_by("-current_revision__created") + + def get_context_data(self, **kwargs): + kwargs = super().get_context_data(**kwargs) + kwargs["search_form"] = self.search_form + kwargs["search_query"] = self.query + kwargs["urlpath"] = self.urlpath + return kwargs + + +class Plugin(View): + def dispatch(self, request, path=None, slug=None, **kwargs): + kwargs["path"] = path + for plugin in list(plugin_registry.get_plugins().values()): + if getattr(plugin, "slug", None) == slug: + return plugin.article_view(request, **kwargs) + raise Http404() + + +class Settings(ArticleMixin, TemplateView): + + permission_form_class = forms.PermissionsForm + template_name = "wiki/settings.html" + +~~ @method_decorator(login_required) +~~ @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + def get_form_classes(self): + settings_forms = [] + if permissions.can_change_permissions(self.article, self.request.user): + settings_forms.append(self.permission_form_class) + plugin_forms = [F for F in plugin_registry.get_settings_forms()] + plugin_forms.sort(key=lambda form: form.settings_order) + settings_forms += plugin_forms + for i in range(len(settings_forms)): + setattr(settings_forms[i], "action", "form%d" % i) + + return settings_forms + + def post(self, *args, **kwargs): + self.forms = [] + for form_class in self.get_form_classes(): + if form_class.action == self.request.GET.get("f", None): + form = form_class(self.article, self.request, self.request.POST) + if form.is_valid(): + form.save() + usermessage = form.get_usermessage() + if usermessage: + + +## ... source file abbreviated to get to method_decorator examples ... + + + def get(self, *args, **kwargs): + self.forms = [] + + new_article = models.Article.objects.get(id=self.article.id) + + for Form in self.get_form_classes(): + self.forms.append(Form(new_article, self.request)) + + return super().get(*args, **kwargs) + + def get_success_url(self): + if self.urlpath: + return redirect("wiki:settings", path=self.urlpath.path) + return redirect("wiki:settings", article_id=self.article.id) + + def get_context_data(self, **kwargs): + kwargs["selected_tab"] = "settings" + kwargs["forms"] = self.forms + return super().get_context_data(**kwargs) + + +class ChangeRevisionView(RedirectView): + + permanent = False + +~~ @method_decorator(get_article(can_write=True, not_locked=True)) + def dispatch(self, request, article, *args, **kwargs): + self.article = article + self.urlpath = kwargs.pop("kwargs", False) + self.change_revision() + + return super().dispatch(request, *args, **kwargs) + + def get_redirect_url(self, **kwargs): + if self.urlpath: + return reverse("wiki:history", kwargs={"path": self.urlpath.path}) + else: + return reverse("wiki:history", kwargs={"article_id": self.article.id}) + + def change_revision(self): + revision = get_object_or_404( + models.ArticleRevision, article=self.article, id=self.kwargs["revision_id"] + ) + self.article.current_revision = revision + self.article.save() + messages.success( + self.request, + _( + "The article %(title)s is now set to display revision #%(revision_number)d" + ) + % {"title": revision.title, "revision_number": revision.revision_number}, + ) + + +class Preview(ArticleMixin, TemplateView): + + template_name = "wiki/preview_inline.html" + +~~ @method_decorator(xframe_options_sameorigin) +~~ @method_decorator(get_article(can_read=True, deleted_contents=True)) + def dispatch(self, request, article, *args, **kwargs): + revision_id = request.GET.get("r", None) + self.title = None + self.content = None + self.preview = False + if revision_id: + try: + revision_id = int(revision_id) + except ValueError: + raise Http404() + self.revision = get_object_or_404( + models.ArticleRevision, article=article, id=revision_id + ) + else: + self.revision = None + return super().dispatch(request, article, *args, **kwargs) + + def post(self, request, *args, **kwargs): + edit_form = forms.EditForm( + request, self.article.current_revision, request.POST, preview=True + ) + if edit_form.is_valid(): + self.title = edit_form.cleaned_data["title"] + self.content = edit_form.cleaned_data["content"] + + +## ... source file abbreviated to get to method_decorator examples ... + + + other_revision = revision.previous_revision + + baseText = other_revision.content if other_revision is not None else "" + newText = revision.content + + differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) + diff = differ.compare( + baseText.splitlines(keepends=True), newText.splitlines(keepends=True) + ) + other_changes = [] + + if not other_revision or other_revision.title != revision.title: + other_changes.append((_("New title"), revision.title)) + + return object_to_json_response( + {"diff": list(diff), "other_changes": other_changes} + ) + + +class MergeView(View): + preview = False + template_name = "wiki/preview_inline.html" + template_error_name = "wiki/error.html" + urlpath = None + +~~ @method_decorator(get_article(can_write=True)) + def dispatch(self, request, article, revision_id, *args, **kwargs): + return super().dispatch(request, article, revision_id, *args, **kwargs) + + def get(self, request, article, revision_id, *args, **kwargs): + revision = get_object_or_404( + models.ArticleRevision, article=article, id=revision_id + ) + + current_text = ( + article.current_revision.content if article.current_revision else "" + ) + new_text = revision.content + + content = simple_merge(current_text, new_text) + + if not self.preview: + old_revision = article.current_revision + + if revision.deleted: + c = { + "error_msg": _("You cannot merge with a deleted revision"), + "article": article, + "urlpath": self.urlpath, + } + + +## ... source file continues with no further method_decorator examples... + +``` + diff --git a/content/pages/examples/django/django-utils-deprecation-middlewaremixin.markdown b/content/pages/examples/django/django-utils-deprecation-middlewaremixin.markdown new file mode 100644 index 000000000..e721b1bdb --- /dev/null +++ b/content/pages/examples/django/django-utils-deprecation-middlewaremixin.markdown @@ -0,0 +1,628 @@ +title: django.utils.deprecation MiddlewareMixin Example Code +category: page +slug: django-utils-deprecation-middlewaremixin-examples +sortorder: 500011437 +toc: False +sidebartitle: django.utils.deprecation MiddlewareMixin +meta: Python example code for the MiddlewareMixin class from the django.utils.deprecation module of the Django project. + + +MiddlewareMixin is a class within the django.utils.deprecation module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog / middleware.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog/middleware.py) + +```python +# middleware.py +from __future__ import unicode_literals + +import threading +import time + +from django.conf import settings +from django.db.models.signals import pre_save +from django.utils.functional import curry +from django.apps import apps +from auditlog.models import LogEntry +from auditlog.compat import is_authenticated + +try: +~~ from django.utils.deprecation import MiddlewareMixin +except ImportError: + MiddlewareMixin = object + + +threadlocal = threading.local() + + +~~class AuditlogMiddleware(MiddlewareMixin): + + def process_request(self, request): + threadlocal.auditlog = { + 'signal_duid': (self.__class__, time.time()), + 'remote_addr': request.META.get('REMOTE_ADDR'), + } + + if request.META.get('HTTP_X_FORWARDED_FOR'): + threadlocal.auditlog['remote_addr'] = request.META.get('HTTP_X_FORWARDED_FOR').split(',')[0] + + if hasattr(request, 'user') and is_authenticated(request.user): + set_actor = curry(self.set_actor, user=request.user, signal_duid=threadlocal.auditlog['signal_duid']) + pre_save.connect(set_actor, sender=LogEntry, dispatch_uid=threadlocal.auditlog['signal_duid'], weak=False) + + def process_response(self, request, response): + if hasattr(threadlocal, 'auditlog'): + pre_save.disconnect(sender=LogEntry, dispatch_uid=threadlocal.auditlog['signal_duid']) + + return response + + def process_exception(self, request, exception): + if hasattr(threadlocal, 'auditlog'): + pre_save.disconnect(sender=LogEntry, dispatch_uid=threadlocal.auditlog['signal_duid']) + + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + + +## Example 2 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / middleware.py**](https://github.com/jrief/django-angular/blob/master/djng/./middleware.py) + +```python +# middleware.py +from django import http +from django.urls import reverse +from django.utils.http import unquote +try: +~~ from django.utils.deprecation import MiddlewareMixin +except ImportError: + MiddlewareMixin = object + + +~~class AngularUrlMiddleware(MiddlewareMixin): + ANGULAR_REVERSE = '/angular/reverse/' + + def process_request(self, request): + if request.path == self.ANGULAR_REVERSE: + url_name = request.GET.get('djng_url_name') + url_args = request.GET.getlist('djng_url_args', []) + url_kwargs = {} + + url_args = filter(lambda x: x, url_args) + + for param in request.GET: + if param.startswith('djng_url_kwarg_'): + if request.GET[param]: + url_kwargs[param[15:]] = request.GET[param] # [15:] to remove 'djng_url_kwarg' prefix + + url = unquote(reverse(url_name, args=url_args, kwargs=url_kwargs)) + assert not url.startswith(self.ANGULAR_REVERSE), "Prevent recursive requests" + + request.path = request.path_info = url + request.environ['PATH_INFO'] = url + query = request.GET.copy() + for key in request.GET: + if key.startswith('djng_url'): + query.pop(key, None) + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + + +## Example 3 from django-cors-headers +[django-cors-headers](https://github.com/ottoyiu/django-cors-headers) +is an +[open source](https://github.com/ottoyiu/django-cors-headers/blob/master/LICENSE) +library for enabling +[Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) +handling in your [Django](/django.html) web applications and appropriately +dealing with HTTP headers for CORS requests. + +[**django-cors-headers / src/corsheaders / middleware.py**](https://github.com/ottoyiu/django-cors-headers/blob/master/src/corsheaders/./middleware.py) + +```python +# middleware.py +import re +from urllib.parse import urlparse + +from django import http +from django.utils.cache import patch_vary_headers +~~from django.utils.deprecation import MiddlewareMixin + +from corsheaders.conf import conf +from corsheaders.signals import check_request_enabled + +ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin" +ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers" +ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials" +ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers" +ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods" +ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age" + + +~~class CorsPostCsrfMiddleware(MiddlewareMixin): + def _https_referer_replace_reverse(self, request): + if conf.CORS_REPLACE_HTTPS_REFERER and "ORIGINAL_HTTP_REFERER" in request.META: + http_referer = request.META["ORIGINAL_HTTP_REFERER"] + request.META["HTTP_REFERER"] = http_referer + del request.META["ORIGINAL_HTTP_REFERER"] + + def process_request(self, request): + self._https_referer_replace_reverse(request) + return None + + def process_view(self, request, callback, callback_args, callback_kwargs): + self._https_referer_replace_reverse(request) + return None + + +~~class CorsMiddleware(MiddlewareMixin): + def _https_referer_replace(self, request): + origin = request.META.get("HTTP_ORIGIN") + + if ( + request.is_secure() + and origin + and "ORIGINAL_HTTP_REFERER" not in request.META + ): + + url = urlparse(origin) + if not conf.CORS_ORIGIN_ALLOW_ALL and not self.origin_found_in_white_lists( + origin, url + ): + return + + try: + http_referer = request.META["HTTP_REFERER"] + http_host = "https://%s/" % request.META["HTTP_HOST"] + request.META = request.META.copy() + request.META["ORIGINAL_HTTP_REFERER"] = http_referer + request.META["HTTP_REFERER"] = http_host + except KeyError: + pass + + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + + +## Example 4 from django-downloadview +[django-downloadview](https://github.com/benoitbryon/django-downloadview) +([project documentation](https://django-downloadview.readthedocs.io/en/1.9/) +and +[PyPI package information](https://pypi.org/project/django-downloadview/)) +is a [Django](/django.html) extension for serving downloads through your +web application. While typically you would use a web server to handle +[static content](/static-content.html), sometimes you need to control +file access, such as requiring a user to register before downloading a +PDF. In that situations, django-downloadview is a handy library to avoid +boilerplate code for common scenarios. + +[**django-downloadview / django_downloadview / middlewares.py**](https://github.com/benoitbryon/django-downloadview/blob/master/django_downloadview/./middlewares.py) + +```python +# middlewares.py +import collections +import copy +import os + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured + +from django_downloadview.response import DownloadResponse +from django_downloadview.utils import import_member + +try: +~~ from django.utils.deprecation import MiddlewareMixin +except ImportError: + +~~ class MiddlewareMixin(object): + def __init__(self, get_response=None): +~~ super(MiddlewareMixin, self).__init__() + + +AUTO_CONFIGURE = object() + + +def is_download_response(response): + return isinstance(response, DownloadResponse) + + +~~class BaseDownloadMiddleware(MiddlewareMixin): + + def is_download_response(self, response): + return is_download_response(response) + + def process_response(self, request, response): + if self.is_download_response(response): + return self.process_download_response(request, response) + return response + + def process_download_response(self, request, response): + raise NotImplementedError() + + +class RealDownloadMiddleware(BaseDownloadMiddleware): + + def is_download_response(self, response): + if super(RealDownloadMiddleware, self).is_download_response(response): + try: + return response.file.url or response.file.name + except AttributeError: + return False + else: + return True + return False + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + + +## Example 5 from django-easy-timezones +[django-easy-timezones](https://github.com/Miserlou/django-easy-timezones) +([project website](https://www.gun.io/blog/django-easy-timezones)) +is a Django +[middleware](https://docs.djangoproject.com/en/2.2/topics/http/middleware/) +[code library](https://pypi.org/project/django-easy-timezones/) +to simplify handling time data in your applications using +users' geolocation data. + +[**django-easy-timezones / easy_timezones / middleware.py**](https://github.com/Miserlou/django-easy-timezones/blob/master/easy_timezones/./middleware.py) + +```python +# middleware.py + if not GEOIPV6_DATABASE: + raise ImproperlyConfigured("GEOIPV6_DATABASE setting has not been properly defined.") + + if not os.path.exists(GEOIPV6_DATABASE): + raise ImproperlyConfigured("GEOIPV6_DATABASE setting is defined, but file does not exist.") + + return (GEOIP_DATABASE, GEOIPV6_DATABASE) + +load_db_settings() + +def load_db(): + + GEOIP_DATABASE, GEOIPV6_DATABASE = load_db_settings() + + global db + db = pygeoip.GeoIP(GEOIP_DATABASE, pygeoip.MEMORY_CACHE) + + global db_v6 + db_v6 = pygeoip.GeoIP(GEOIPV6_DATABASE, pygeoip.MEMORY_CACHE) + + global db_loaded + db_loaded = True + + +if django.VERSION >= (1, 10): +~~ from django.utils.deprecation import MiddlewareMixin + middleware_base_class = MiddlewareMixin +else: + middleware_base_class = object + + +class EasyTimezoneMiddleware(middleware_base_class): + def process_request(self, request): + + if not request: + return + + if not db_loaded: + load_db() + + tz = request.session.get('django_timezone') + + if not tz: + tz = timezone.get_default_timezone() + + client_ip = get_ip_address_from_request(request) + ip_addrs = client_ip.split(',') + for ip in ip_addrs: + if is_valid_ip(ip) and not is_local_ip(ip): + if ':' in ip: + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + + +## Example 6 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / middleware.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./middleware.py) + +```python +# middleware.py +from django.contrib.auth import authenticate +from django.utils.cache import patch_vary_headers +~~from django.utils.deprecation import MiddlewareMixin + + +~~class OAuth2TokenMiddleware(MiddlewareMixin): + + def process_request(self, request): + if request.META.get("HTTP_AUTHORIZATION", "").startswith("Bearer"): + if not hasattr(request, "user") or request.user.is_anonymous: + user = authenticate(request=request) + if user: + request.user = request._cached_user = user + + def process_response(self, request, response): + patch_vary_headers(response, ("Authorization",)) + return response + + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + + +## Example 7 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / middleware.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./middleware.py) + +```python +# middleware.py +from django.core.exceptions import MiddlewareNotUsed +from django.utils.encoding import DjangoUnicodeDecodeError +from django.utils.html import strip_spaces_between_tags as minify_html + +from pipeline.conf import settings + +~~from django.utils.deprecation import MiddlewareMixin + + +~~class MinifyHTMLMiddleware(MiddlewareMixin): + def __init__(self, *args, **kwargs): + super(MinifyHTMLMiddleware, self).__init__(*args, **kwargs) + if not settings.PIPELINE_ENABLED: + raise MiddlewareNotUsed + + def process_response(self, request, response): + if response.has_header('Content-Type') and 'text/html' in response['Content-Type']: + try: + response.content = minify_html(response.content.decode('utf-8').strip()) + response['Content-Length'] = str(len(response.content)) + except DjangoUnicodeDecodeError: + pass + return response + + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + + +## Example 8 from django-webtest +[django-webtest](https://github.com/django-webtest/django-webtest) +([PyPI package information](https://pypi.org/project/django-webtest/)) +is a [Django](/django.html) extension that makes it easier to use +[WebTest](http://docs.pylonsproject.org/projects/webtest/) with +your projects. + +The project is open sourced under the +[MIT license](https://github.com/django-webtest/django-webtest/blob/master/LICENSE.txt). + +[**django-webtest / django_webtest / middleware.py**](https://github.com/django-webtest/django-webtest/blob/master/django_webtest/./middleware.py) + +```python +# middleware.py +import django +from django.contrib.auth.middleware import RemoteUserMiddleware +from django.core.exceptions import ImproperlyConfigured +from django.contrib import auth +if django.VERSION >= (1, 10): +~~ from django.utils.deprecation import MiddlewareMixin +else: + MiddlewareMixin = object + +from django_webtest.compat import is_authenticated + + +class WebtestUserMiddleware(RemoteUserMiddleware): + + header = "WEBTEST_USER" + + def process_request(self, request): + if not hasattr(request, 'user'): + raise ImproperlyConfigured( + "The django-webtest auth middleware requires the " + "'django.contrib.auth.middleware.AuthenticationMiddleware' " + "to be installed. Add it to your MIDDLEWARE setting " + "or disable django-webtest auth support by setting " + "'setup_auth' property of your WebTest subclass to False." + ) + try: + username = request.META[self.header] + except KeyError: + return + if is_authenticated(request.user): + if hasattr(request.user, "get_username"): + authenticated_username = request.user.get_username() + else: + authenticated_username = request.user.username + clean_username = self.clean_username(username, request) + if authenticated_username == clean_username: + return + user = auth.authenticate(django_webtest_user=username) + if user: + request.user = user + auth.login(request, user) + + +~~class DisableCSRFCheckMiddleware(MiddlewareMixin): + def process_request(self, request): + request._dont_enforce_csrf_checks = True + + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + + +## Example 9 from graphite-web +[Graphite](https://github.com/graphite-project/graphite-web) +([project website](http://graphiteapp.org/), +[documentation](https://graphite.readthedocs.io/en/latest/) and +[PyPI package information](https://pypi.org/project/graphite-web/)) +is a metrics collection and visualization tool, built with both +Python and JavaScript. Metrics are collected by a Node.js application +and displayed using a [Django](/django.html) web application, +called "Graphite-Web", which is one of three core projects under +the Graphite umbrella (the other two are +[Carbon](https://github.com/graphite-project/carbon) and +[Whisper](https://github.com/graphite-project/whisper)). + +Graphite is provided as open sourced under the +[Apache License 2.0](https://github.com/graphite-project/whisper/blob/master/LICENSE). + +[**graphite-web / webapp / graphite / middleware.py**](https://github.com/graphite-project/graphite-web/blob/master/webapp/graphite/middleware.py) + +```python +# middleware.py +from graphite.logger import log +try: +~~ from django.utils.deprecation import MiddlewareMixin +except ImportError: # Django < 1.10 + MiddlewareMixin = object + + +~~class LogExceptionsMiddleware(MiddlewareMixin): + def process_exception(self, request, exception): + log.exception('Exception encountered in <{0} {1}>'.format(request.method, request.build_absolute_uri())) + return None + + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + + +## Example 10 from register +[register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is +open source under the +[GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). +This web application makes it easier for people to register as organ donors. +You can see the application live at +[https://register.organize.org/](https://register.organize.org/). + +[**register / registration / middleware.py**](https://github.com/ORGAN-IZE/register/blob/master/registration/./middleware.py) + +```python +# middleware.py +import django.middleware.locale +import django.shortcuts +from django.utils import translation +~~from django.utils.deprecation import MiddlewareMixin + + +~~class RequestLocaleMiddleware(MiddlewareMixin): + def process_view(self, request, view_func, view_args, view_kwargs): + if request.method == 'GET': + language = request.GET.get('lang') + if language: + translation.activate(language) + request.session[translation.LANGUAGE_SESSION_KEY] = translation.get_language() + query = request.GET.copy() + del query['lang'] + path = '?'.join([request.path, query.urlencode()]) + return django.shortcuts.redirect(path) + + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + + +## Example 11 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / middleware.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/middleware.py) + +```python +# middleware.py +import warnings + +~~from django.utils.deprecation import MiddlewareMixin +from wagtail.core.models import Site +from wagtail.utils.deprecation import RemovedInWagtail211Warning + + +warnings.warn( + 'wagtail.core.middleware.SiteMiddleware and the use of request.site is deprecated. ' + 'Please update your code to use Site.find_for_request(request) in place of request.site, ' + 'and remove wagtail.core.middleware.SiteMiddleware from MIDDLEWARES', + RemovedInWagtail211Warning +) + + +~~class SiteMiddleware(MiddlewareMixin): + def process_request(self, request): + try: + request.site = Site.find_for_request(request) + except Site.DoesNotExist: + request.site = None + + + +## ... source file continues with no further MiddlewareMixin examples... + +``` + diff --git a/content/pages/examples/django/django-utils-deprecation-renamemethodsbase.markdown b/content/pages/examples/django/django-utils-deprecation-renamemethodsbase.markdown new file mode 100644 index 000000000..ebf9b13b3 --- /dev/null +++ b/content/pages/examples/django/django-utils-deprecation-renamemethodsbase.markdown @@ -0,0 +1,66 @@ +title: django.utils.deprecation RenameMethodsBase Example Code +category: page +slug: django-utils-deprecation-renamemethodsbase-examples +sortorder: 500011438 +toc: False +sidebartitle: django.utils.deprecation RenameMethodsBase +meta: Python example code for the RenameMethodsBase class from the django.utils.deprecation module of the Django project. + + +RenameMethodsBase is a class within the django.utils.deprecation module of the Django project. + + +## Example 1 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / rest_framework / backends.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/rest_framework/backends.py) + +```python +# backends.py +import warnings + +from django.template import loader +~~from django.utils.deprecation import RenameMethodsBase + +from .. import compat, utils +from . import filters, filterset + + +~~class RenameAttributes(utils.RenameAttributesBase, RenameMethodsBase): + renamed_attributes = ( + ('default_filter_set', 'filterset_base', utils.MigrationNotice), + ) + renamed_methods = ( + ('get_filter_class', 'get_filterset_class', utils.MigrationNotice), + ) + + +class DjangoFilterBackend(metaclass=RenameAttributes): + filterset_base = filterset.FilterSet + raise_exception = True + + @property + def template(self): + if compat.is_crispy(): + return 'django_filters/rest_framework/crispy_form.html' + return 'django_filters/rest_framework/form.html' + + def get_filterset(self, request, queryset, view): + filterset_class = self.get_filterset_class(view, queryset) + if filterset_class is None: + return None + + kwargs = self.get_filterset_kwargs(request, queryset, view) + + +## ... source file continues with no further RenameMethodsBase examples... + +``` + diff --git a/content/pages/examples/django/django-utils-duration-duration-string.markdown b/content/pages/examples/django/django-utils-duration-duration-string.markdown new file mode 100644 index 000000000..2bc244c18 --- /dev/null +++ b/content/pages/examples/django/django-utils-duration-duration-string.markdown @@ -0,0 +1,142 @@ +title: django.utils.duration duration_string Example Code +category: page +slug: django-utils-duration-duration-string-examples +sortorder: 500011439 +toc: False +sidebartitle: django.utils.duration duration_string +meta: Python example code for the duration_string callable from the django.utils.duration module of the Django project. + + +duration_string is a callable within the django.utils.duration module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / fields.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./fields.py) + +```python +# fields.py +import copy +import datetime +import decimal +import functools +import inspect +import re +import uuid +import warnings +from collections import OrderedDict +from collections.abc import Mapping + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import ( + EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator, + MinValueValidator, ProhibitNullCharactersValidator, RegexValidator, + URLValidator, ip_address_validators +) +from django.forms import FilePathField as DjangoFilePathField +from django.forms import ImageField as DjangoImageField +from django.utils import timezone +from django.utils.dateparse import ( + parse_date, parse_datetime, parse_duration, parse_time +) +~~from django.utils.duration import duration_string +from django.utils.encoding import is_protected_type, smart_str +from django.utils.formats import localize_input, sanitize_separators +from django.utils.ipv6 import clean_ipv6_address +from django.utils.timezone import utc +from django.utils.translation import gettext_lazy as _ +from pytz.exceptions import InvalidTimeError + +from rest_framework import ( + ISO_8601, RemovedInDRF313Warning, RemovedInDRF314Warning +) +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.settings import api_settings +from rest_framework.utils import html, humanize_datetime, json, representation +from rest_framework.utils.formatting import lazy_format +from rest_framework.validators import ProhibitSurrogateCharactersValidator + + +class empty: + pass + + +class BuiltinSignatureError(Exception): + pass + + + +## ... source file abbreviated to get to duration_string examples ... + + + 'min_value': _('Ensure this value is greater than or equal to {min_value}.'), + } + + def __init__(self, **kwargs): + self.max_value = kwargs.pop('max_value', None) + self.min_value = kwargs.pop('min_value', None) + super().__init__(**kwargs) + if self.max_value is not None: + message = lazy_format(self.error_messages['max_value'], max_value=self.max_value) + self.validators.append( + MaxValueValidator(self.max_value, message=message)) + if self.min_value is not None: + message = lazy_format(self.error_messages['min_value'], min_value=self.min_value) + self.validators.append( + MinValueValidator(self.min_value, message=message)) + + def to_internal_value(self, value): + if isinstance(value, datetime.timedelta): + return value + parsed = parse_duration(str(value)) + if parsed is not None: + return parsed + self.fail('invalid', format='[DD] [HH:[MM:]]ss[.uuuuuu]') + + def to_representation(self, value): +~~ return duration_string(value) + + + +class ChoiceField(Field): + default_error_messages = { + 'invalid_choice': _('"{input}" is not a valid choice.') + } + html_cutoff = None + html_cutoff_text = _('More than {count} items...') + + def __init__(self, choices, **kwargs): + self.choices = choices + self.html_cutoff = kwargs.pop('html_cutoff', self.html_cutoff) + self.html_cutoff_text = kwargs.pop('html_cutoff_text', self.html_cutoff_text) + + self.allow_blank = kwargs.pop('allow_blank', False) + + super().__init__(**kwargs) + + def to_internal_value(self, data): + if data == '' and self.allow_blank: + return '' + + try: + + +## ... source file continues with no further duration_string examples... + +``` + diff --git a/content/pages/examples/django/django-utils-encoding-djangounicodedecodeerror.markdown b/content/pages/examples/django/django-utils-encoding-djangounicodedecodeerror.markdown new file mode 100644 index 000000000..7b06f5a36 --- /dev/null +++ b/content/pages/examples/django/django-utils-encoding-djangounicodedecodeerror.markdown @@ -0,0 +1,60 @@ +title: django.utils.encoding DjangoUnicodeDecodeError Example Code +category: page +slug: django-utils-encoding-djangounicodedecodeerror-examples +sortorder: 500011440 +toc: False +sidebartitle: django.utils.encoding DjangoUnicodeDecodeError +meta: Python example code for the DjangoUnicodeDecodeError class from the django.utils.encoding module of the Django project. + + +DjangoUnicodeDecodeError is a class within the django.utils.encoding module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / middleware.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./middleware.py) + +```python +# middleware.py +from django.core.exceptions import MiddlewareNotUsed +~~from django.utils.encoding import DjangoUnicodeDecodeError +from django.utils.html import strip_spaces_between_tags as minify_html + +from pipeline.conf import settings + +from django.utils.deprecation import MiddlewareMixin + + +class MinifyHTMLMiddleware(MiddlewareMixin): + def __init__(self, *args, **kwargs): + super(MinifyHTMLMiddleware, self).__init__(*args, **kwargs) + if not settings.PIPELINE_ENABLED: + raise MiddlewareNotUsed + + def process_response(self, request, response): + if response.has_header('Content-Type') and 'text/html' in response['Content-Type']: + try: + response.content = minify_html(response.content.decode('utf-8').strip()) + response['Content-Length'] = str(len(response.content)) +~~ except DjangoUnicodeDecodeError: + pass + return response + + + +## ... source file continues with no further DjangoUnicodeDecodeError examples... + +``` + diff --git a/content/pages/examples/django/django-utils-encoding-filepath-to-uri.markdown b/content/pages/examples/django/django-utils-encoding-filepath-to-uri.markdown new file mode 100644 index 000000000..f71de16da --- /dev/null +++ b/content/pages/examples/django/django-utils-encoding-filepath-to-uri.markdown @@ -0,0 +1,93 @@ +title: django.utils.encoding filepath_to_uri Example Code +category: page +slug: django-utils-encoding-filepath-to-uri-examples +sortorder: 500011441 +toc: False +sidebartitle: django.utils.encoding filepath_to_uri +meta: Python example code for the filepath_to_uri callable from the django.utils.encoding module of the Django project. + + +filepath_to_uri is a callable within the django.utils.encoding module of the Django project. + + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / core / http.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/core/http.py) + +```python +# http.py +import mimetypes +import os +from datetime import datetime + +from django.http import HttpResponse +from django.utils import dateformat +~~from django.utils.encoding import filepath_to_uri +from django.utils.http import http_date +from wiki.conf import settings + + +def django_sendfile_response(request, filepath): + from sendfile import sendfile + + return sendfile(request, filepath) + + +def send_file(request, filepath, last_modified=None, filename=None): + fullpath = filepath + statobj = os.stat(fullpath) + if filename: + mimetype, encoding = mimetypes.guess_type(filename) + else: + mimetype, encoding = mimetypes.guess_type(fullpath) + + mimetype = mimetype or "application/octet-stream" + + if settings.USE_SENDFILE: + response = django_sendfile_response(request, filepath) + else: + response = HttpResponse(open(fullpath, "rb").read(), content_type=mimetype) + + if not last_modified: + response["Last-Modified"] = http_date(statobj.st_mtime) + else: + if isinstance(last_modified, datetime): + last_modified = float(dateformat.format(last_modified, "U")) + response["Last-Modified"] = http_date(epoch_seconds=last_modified) + + response["Content-Length"] = statobj.st_size + + if encoding: + response["Content-Encoding"] = encoding + + if filename: +~~ filename_escaped = filepath_to_uri(filename) + if "pdf" in mimetype.lower(): + response["Content-Disposition"] = "inline; filename=%s" % filename_escaped + else: + response["Content-Disposition"] = ( + "attachment; filename=%s" % filename_escaped + ) + + return response + + + +## ... source file continues with no further filepath_to_uri examples... + +``` + diff --git a/content/pages/examples/django/django-utils-encoding-force-bytes.markdown b/content/pages/examples/django/django-utils-encoding-force-bytes.markdown new file mode 100644 index 000000000..74420d227 --- /dev/null +++ b/content/pages/examples/django/django-utils-encoding-force-bytes.markdown @@ -0,0 +1,389 @@ +title: django.utils.encoding force_bytes Example Code +category: page +slug: django-utils-encoding-force-bytes-examples +sortorder: 500011442 +toc: False +sidebartitle: django.utils.encoding force_bytes +meta: Python example code for the force_bytes callable from the django.utils.encoding module of the Django project. + + +force_bytes is a callable within the django.utils.encoding module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / utils.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/./utils.py) + +```python +# utils.py +import base64 +import importlib +import json +import random +import re +import string +import unicodedata +from collections import OrderedDict +from urllib.parse import urlsplit + +import django +from django.contrib.auth import get_user_model +from django.contrib.sites.models import Site +from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured +from django.core.serializers.json import DjangoJSONEncoder +from django.core.validators import ValidationError, validate_email +from django.db.models import FileField +from django.db.models.fields import ( + BinaryField, + DateField, + DateTimeField, + EmailField, + TimeField, +) +from django.utils import dateparse +~~from django.utils.encoding import force_bytes, force_str + + +MAX_USERNAME_SUFFIX_LENGTH = 7 +USERNAME_SUFFIX_CHARS = ( + [string.digits] * 4 + + [string.ascii_letters] * (MAX_USERNAME_SUFFIX_LENGTH - 4)) + + +def _generate_unique_username_base(txts, regex=None): + from .account.adapter import get_adapter + adapter = get_adapter() + username = None + regex = regex or r'[^\w\s@+.-]' + for txt in txts: + if not txt: + continue + username = unicodedata.normalize('NFKD', force_str(txt)) + username = username.encode('ascii', 'ignore').decode('ascii') + username = force_str(re.sub(regex, '', username).lower()) + username = username.split('@')[0] + username = username.strip() + username = re.sub(r'\s+', '_', username) + try: + username = adapter.clean_username(username, shallow=True) + + +## ... source file abbreviated to get to force_bytes examples ... + + + v = field.get_prep_value(v) + k = SERIALIZED_DB_FIELD_PREFIX + k + except FieldDoesNotExist: + pass + data[k] = v + return json.loads(json.dumps(data, cls=DjangoJSONEncoder)) + + +def deserialize_instance(model, data): + ret = model() + for k, v in data.items(): + is_db_value = False + if k.startswith(SERIALIZED_DB_FIELD_PREFIX): + k = k[len(SERIALIZED_DB_FIELD_PREFIX):] + is_db_value = True + if v is not None: + try: + f = model._meta.get_field(k) + if isinstance(f, DateTimeField): + v = dateparse.parse_datetime(v) + elif isinstance(f, TimeField): + v = dateparse.parse_time(v) + elif isinstance(f, DateField): + v = dateparse.parse_date(v) + elif isinstance(f, BinaryField): +~~ v = force_bytes( + base64.b64decode( +~~ force_bytes(v))) + elif is_db_value: + try: + if django.VERSION < (3, 0): + v = f.from_db_value(v, None, None, None) + else: + v = f.from_db_value(v, None, None) + except Exception: + raise ImproperlyConfigured( + "Unable to auto serialize field '{}', custom" + " serialization override required".format(k) + ) + except FieldDoesNotExist: + pass + setattr(ret, k, v) + return ret + + +def set_form_field_order(form, field_order): + if field_order is None: + return + fields = OrderedDict() + for key in field_order: + try: + fields[key] = form.fields.pop(key) + + +## ... source file continues with no further force_bytes examples... + +``` + + +## Example 2 from django-downloadview +[django-downloadview](https://github.com/benoitbryon/django-downloadview) +([project documentation](https://django-downloadview.readthedocs.io/en/1.9/) +and +[PyPI package information](https://pypi.org/project/django-downloadview/)) +is a [Django](/django.html) extension for serving downloads through your +web application. While typically you would use a web server to handle +[static content](/static-content.html), sometimes you need to control +file access, such as requiring a user to register before downloading a +PDF. In that situations, django-downloadview is a handy library to avoid +boilerplate code for common scenarios. + +[**django-downloadview / django_downloadview / io.py**](https://github.com/benoitbryon/django-downloadview/blob/master/django_downloadview/./io.py) + +```python +# io.py +import io + +~~from django.utils.encoding import force_bytes, force_text + + +class TextIteratorIO(io.TextIOBase): + + def __init__(self, iterator): + self._iter = iterator + + self._left = "" + + def readable(self): + return True + + def _read1(self, n=None): + while not self._left: + try: + self._left = next(self._iter) + except StopIteration: + break + else: + self._left = force_text(self._left) + ret = self._left[:n] + self._left = self._left[len(ret) :] + return ret + + + +## ... source file abbreviated to get to force_bytes examples ... + + + break + else: + chunks.append(self._left[: i + 1]) + self._left = self._left[i + 1 :] + break + return "".join(chunks) + + +class BytesIteratorIO(io.BytesIO): + + def __init__(self, iterator): + self._iter = iterator + + self._left = b"" + + def readable(self): + return True + + def _read1(self, n=None): + while not self._left: + try: + self._left = next(self._iter) + except StopIteration: + break + else: +~~ self._left = force_bytes(self._left) + ret = self._left[:n] + self._left = self._left[len(ret) :] + return ret + + def read(self, n=None): + chunks = [] + if n is None or n < 0: + while True: + m = self._read1() + if not m: + break + chunks.append(m) + else: + while n > 0: + m = self._read1(n) + if not m: + break + n -= len(m) + chunks.append(m) + return b"".join(chunks) + + def readline(self): + chunks = [] + while True: + + +## ... source file continues with no further force_bytes examples... + +``` + + +## Example 3 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / test.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./test.py) + +```python +# test.py +import io +from importlib import import_module + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.core.handlers.wsgi import WSGIHandler +from django.test import override_settings, testcases +from django.test.client import Client as DjangoClient +from django.test.client import ClientHandler +from django.test.client import RequestFactory as DjangoRequestFactory +~~from django.utils.encoding import force_bytes +from django.utils.http import urlencode + +from rest_framework.compat import coreapi, requests +from rest_framework.settings import api_settings + + +def force_authenticate(request, user=None, token=None): + request._force_auth_user = user + request._force_auth_token = token + + +if requests is not None: + class HeaderDict(requests.packages.urllib3._collections.HTTPHeaderDict): + def get_all(self, key, default): + return self.getheaders(key) + + class MockOriginalResponse: + def __init__(self, headers): + self.msg = HeaderDict(headers) + self.closed = False + + def isclosed(self): + return self.closed + + + +## ... source file abbreviated to get to force_bytes examples ... + + + def CoreAPIClient(*args, **kwargs): + raise ImproperlyConfigured('coreapi must be installed in order to use CoreAPIClient.') + + +class APIRequestFactory(DjangoRequestFactory): + renderer_classes_list = api_settings.TEST_REQUEST_RENDERER_CLASSES + default_format = api_settings.TEST_REQUEST_DEFAULT_FORMAT + + def __init__(self, enforce_csrf_checks=False, **defaults): + self.enforce_csrf_checks = enforce_csrf_checks + self.renderer_classes = {} + for cls in self.renderer_classes_list: + self.renderer_classes[cls.format] = cls + super().__init__(**defaults) + + def _encode_data(self, data, format=None, content_type=None): + + if data is None: + return ('', content_type) + + assert format is None or content_type is None, ( + 'You may not set both `format` and `content_type`.' + ) + + if content_type: +~~ ret = force_bytes(data, settings.DEFAULT_CHARSET) + + else: + format = format or self.default_format + + assert format in self.renderer_classes, ( + "Invalid format '{}'. Available formats are {}. " + "Set TEST_REQUEST_RENDERER_CLASSES to enable " + "extra request formats.".format( + format, + ', '.join(["'" + fmt + "'" for fmt in self.renderer_classes]) + ) + ) + + renderer = self.renderer_classes[format]() + ret = renderer.render(data) + + content_type = "{}; charset={}".format( + renderer.media_type, renderer.charset + ) + + if isinstance(ret, str): + ret = ret.encode(renderer.charset) + + return ret, content_type + + def get(self, path, data=None, **extra): + r = { + 'QUERY_STRING': urlencode(data or {}, doseq=True), + } + if not data and '?' in path: +~~ query_string = force_bytes(path.split('?')[1]) + query_string = query_string.decode('iso-8859-1') + r['QUERY_STRING'] = query_string + r.update(extra) + return self.generic('GET', path, **r) + + def post(self, path, data=None, format=None, content_type=None, **extra): + data, content_type = self._encode_data(data, format, content_type) + return self.generic('POST', path, data, content_type, **extra) + + def put(self, path, data=None, format=None, content_type=None, **extra): + data, content_type = self._encode_data(data, format, content_type) + return self.generic('PUT', path, data, content_type, **extra) + + def patch(self, path, data=None, format=None, content_type=None, **extra): + data, content_type = self._encode_data(data, format, content_type) + return self.generic('PATCH', path, data, content_type, **extra) + + def delete(self, path, data=None, format=None, content_type=None, **extra): + data, content_type = self._encode_data(data, format, content_type) + return self.generic('DELETE', path, data, content_type, **extra) + + def options(self, path, data=None, format=None, content_type=None, **extra): + data, content_type = self._encode_data(data, format, content_type) + return self.generic('OPTIONS', path, data, content_type, **extra) + + +## ... source file continues with no further force_bytes examples... + +``` + diff --git a/content/pages/examples/django/django-utils-encoding-force-str.markdown b/content/pages/examples/django/django-utils-encoding-force-str.markdown new file mode 100644 index 000000000..3a097e807 --- /dev/null +++ b/content/pages/examples/django/django-utils-encoding-force-str.markdown @@ -0,0 +1,1558 @@ +title: django.utils.encoding force_str Example Code +category: page +slug: django-utils-encoding-force-str-examples +sortorder: 500011443 +toc: False +sidebartitle: django.utils.encoding force_str +meta: Python example code for the force_str callable from the django.utils.encoding module of the Django project. + + +force_str is a callable within the django.utils.encoding module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / utils.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/./utils.py) + +```python +# utils.py +import base64 +import importlib +import json +import random +import re +import string +import unicodedata +from collections import OrderedDict +from urllib.parse import urlsplit + +import django +from django.contrib.auth import get_user_model +from django.contrib.sites.models import Site +from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured +from django.core.serializers.json import DjangoJSONEncoder +from django.core.validators import ValidationError, validate_email +from django.db.models import FileField +from django.db.models.fields import ( + BinaryField, + DateField, + DateTimeField, + EmailField, + TimeField, +) +from django.utils import dateparse +~~from django.utils.encoding import force_bytes, force_str + + +MAX_USERNAME_SUFFIX_LENGTH = 7 +USERNAME_SUFFIX_CHARS = ( + [string.digits] * 4 + + [string.ascii_letters] * (MAX_USERNAME_SUFFIX_LENGTH - 4)) + + +def _generate_unique_username_base(txts, regex=None): + from .account.adapter import get_adapter + adapter = get_adapter() + username = None + regex = regex or r'[^\w\s@+.-]' + for txt in txts: + if not txt: + continue +~~ username = unicodedata.normalize('NFKD', force_str(txt)) + username = username.encode('ascii', 'ignore').decode('ascii') +~~ username = force_str(re.sub(regex, '', username).lower()) + username = username.split('@')[0] + username = username.strip() + username = re.sub(r'\s+', '_', username) + try: + username = adapter.clean_username(username, shallow=True) + break + except ValidationError: + pass + return username or 'user' + + +def get_username_max_length(): + from .account.app_settings import USER_MODEL_USERNAME_FIELD + if USER_MODEL_USERNAME_FIELD is not None: + User = get_user_model() + max_length = User._meta.get_field(USER_MODEL_USERNAME_FIELD).max_length + else: + max_length = 0 + return max_length + + +def generate_username_candidate(basename, suffix_length): + max_length = get_username_max_length() + suffix = ''.join( + + +## ... source file abbreviated to get to force_str examples ... + + + assert isinstance(path, str) + pkg, attr = path.rsplit('.', 1) + ret = getattr(importlib.import_module(pkg), attr) + return ret + + +def import_callable(path_or_callable): + if not hasattr(path_or_callable, '__call__'): + ret = import_attribute(path_or_callable) + else: + ret = path_or_callable + return ret + + +SERIALIZED_DB_FIELD_PREFIX = '_db_' + + +def serialize_instance(instance): + data = {} + for k, v in instance.__dict__.items(): + if k.startswith('_') or callable(v): + continue + try: + field = instance._meta.get_field(k) + if isinstance(field, BinaryField): +~~ v = force_str(base64.b64encode(v)) + elif isinstance(field, FileField): + if v and not isinstance(v, str): + v = v.name + try: + json.dumps(v, cls=DjangoJSONEncoder) + except TypeError: + v = field.get_prep_value(v) + k = SERIALIZED_DB_FIELD_PREFIX + k + except FieldDoesNotExist: + pass + data[k] = v + return json.loads(json.dumps(data, cls=DjangoJSONEncoder)) + + +def deserialize_instance(model, data): + ret = model() + for k, v in data.items(): + is_db_value = False + if k.startswith(SERIALIZED_DB_FIELD_PREFIX): + k = k[len(SERIALIZED_DB_FIELD_PREFIX):] + is_db_value = True + if v is not None: + try: + f = model._meta.get_field(k) + + +## ... source file continues with no further force_str examples... + +``` + + +## Example 2 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / validators.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/./validators.py) + +```python +# validators.py +import unicodedata +import binascii + + +from django.core.exceptions import ValidationError +from django.utils.deconstruct import deconstructible +~~from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + + +@deconstructible +class NoControlCharactersValidator: + message = _("Control Characters like new lines or tabs are not allowed.") + code = "no_control_characters" + whitelist = None + + def __init__(self, message=None, code=None, whitelist=None): + if message: + self.message = message + if code: + self.code = code + if whitelist: + self.whitelist = whitelist + + def __call__(self, value): +~~ value = force_str(value) + whitelist = self.whitelist + category = unicodedata.category + for character in value: + if whitelist and character in whitelist: + continue + if category(character)[0] == "C": + params = {'value': value, 'whitelist': whitelist} + raise ValidationError(self.message, code=self.code, params=params) + + def __eq__(self, other): + return ( + isinstance(other, NoControlCharactersValidator) and + (self.whitelist == other.whitelist) and + (self.message == other.message) and + (self.code == other.code) + ) + + +@deconstructible +class NoWhitespaceValidator: + message = _("Leading and Trailing whitespaces are not allowed.") + code = "no_whitespace" + + def __init__(self, message=None, code=None, whitelist=None): + if message: + self.message = message + if code: + self.code = code + + def __call__(self, value): +~~ value = force_str(value) + if value != value.strip(): + params = {'value': value} + raise ValidationError(self.message, code=self.code, params=params) + + def __eq__(self, other): + return ( + isinstance(other, NoWhitespaceValidator) and + (self.message == other.message) and + (self.code == other.code) + ) + + +@deconstructible +class HexValidator: + messages = { + 'invalid': _("Only a hex string is allowed."), + 'length': _("Invalid length. Must be %(length)d characters."), + 'min_length': _("Ensure that there are more than %(min)s characters."), + 'max_length': _("Ensure that there are no more than %(max)s characters."), + } + code = "hex_only" + + def __init__(self, length=None, min_length=None, max_length=None, message=None, code=None): + self.length = length + self.min_length = min_length + self.max_length = max_length + if message: + self.message = message + if code: + self.code = code + + def __call__(self, value): +~~ value = force_str(value) + if self.length and len(value) != self.length: + raise ValidationError(self.messages['length'], code='hex_only_length', params={'length': self.length}) + if self.min_length and len(value) < self.min_length: + raise ValidationError(self.messages['min_length'], code='hex_only_min_length', params={'min': self.min_length}) + if self.max_length and len(value) < self.max_length: + raise ValidationError(self.messages['max_length'], code='hex_only_max_length', params={'max': self.max_length}) + + try: + binascii.unhexlify(value) + except (TypeError, binascii.Error): + raise ValidationError(self.messages['invalid'], code='hex_only') + + def __eq__(self, other): + return ( + isinstance(other, HexValidator) and + (self.message == other.message) and + (self.code == other.code) + ) + + + +## ... source file continues with no further force_str examples... + +``` + + +## Example 3 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / fields.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./fields.py) + +```python +# fields.py +from collections import namedtuple +from datetime import datetime, time + +from django import forms +from django.utils.dateparse import parse_datetime +~~from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +from .conf import settings +from .constants import EMPTY_VALUES +from .utils import handle_timezone +from .widgets import ( + BaseCSVWidget, + CSVWidget, + DateRangeWidget, + LookupChoiceWidget, + RangeWidget +) + + +class RangeField(forms.MultiValueField): + widget = RangeWidget + + def __init__(self, fields=None, *args, **kwargs): + if fields is None: + fields = ( + forms.DecimalField(), + forms.DecimalField()) + super().__init__(fields, *args, **kwargs) + + + +## ... source file abbreviated to get to force_str examples ... + + + empty_label = kwargs.pop('empty_label', settings.EMPTY_CHOICE_LABEL) + fields = (field, ChoiceField(choices=lookup_choices, empty_label=empty_label)) + widget = LookupChoiceWidget(widgets=[f.widget for f in fields]) + kwargs['widget'] = widget + kwargs['help_text'] = field.help_text + super().__init__(fields, *args, **kwargs) + + def compress(self, data_list): + if len(data_list) == 2: + value, lookup_expr = data_list + if value not in EMPTY_VALUES: + if lookup_expr not in EMPTY_VALUES: + return Lookup(value=value, lookup_expr=lookup_expr) + else: + raise forms.ValidationError( + self.error_messages['lookup_required'], + code='lookup_required') + return None + + +class IsoDateTimeField(forms.DateTimeField): + ISO_8601 = 'iso-8601' + input_formats = [ISO_8601] + + def strptime(self, value, format): +~~ value = force_str(value) + + if format == self.ISO_8601: + parsed = parse_datetime(value) + if parsed is None: # Continue with other formats if doesn't match + raise ValueError + return handle_timezone(parsed) + return super().strptime(value, format) + + +class BaseCSVField(forms.Field): + base_widget_class = BaseCSVWidget + + def __init__(self, *args, **kwargs): + widget = kwargs.get('widget') or self.widget + kwargs['widget'] = self._get_widget_class(widget) + + super().__init__(*args, **kwargs) + + def _get_widget_class(self, widget): + if isinstance(widget, BaseCSVWidget) or ( + isinstance(widget, type) and + issubclass(widget, BaseCSVWidget)): + return widget + + + +## ... source file continues with no further force_str examples... + +``` + + +## Example 4 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / widgets.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./widgets.py) + +```python +# widgets.py +import datetime +import re +from itertools import chain + +import django +from django import forms +from django.conf import settings +from django.forms.widgets import FILE_INPUT_CONTRADICTION +from django.template import loader +from django.utils import datetime_safe, formats +from django.utils.dates import MONTHS +~~from django.utils.encoding import force_str +from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + +from .compat import MULTIVALUE_DICT_TYPES, flatten_contexts + + +from django.forms.utils import to_current_timezone + + +RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$') + + +__all__ = ( + 'TextInput', 'PasswordInput', 'HiddenInput', 'ClearableFileInput', + 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', + 'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple', + 'RadioSelect', 'CheckboxSelectMultiple', 'SearchInput', 'RangeInput', + 'ColorInput', 'EmailInput', 'URLInput', 'PhoneNumberInput', 'NumberInput', + 'IPAddressInput', 'MultiWidget', 'Widget', 'SplitDateTimeWidget', + 'SplitHiddenDateTimeWidget', 'MultipleHiddenInput', 'SelectDateWidget', + 'SlugInput', +) + + + +## ... source file abbreviated to get to force_str examples ... + + + def format_value(self, value): + return self._format_value(value) + + +class Input(Widget): + template_name = 'floppyforms/input.html' + input_type = None + datalist = None + + def __init__(self, *args, **kwargs): + datalist = kwargs.pop('datalist', None) + if datalist is not None: + self.datalist = datalist + template_name = kwargs.pop('template_name', None) + if template_name is not None: + self.template_name = template_name + super(Input, self).__init__(*args, **kwargs) + self.context_instance = None + + def get_context_data(self): + return {} + + def format_value(self, value): + if self.is_localized: + value = formats.localize_input(value) +~~ return force_str(value) + + def get_context(self, name, value, attrs=None): + context = { + 'widget': self, + 'type': self.input_type, + 'name': name, + 'hidden': self.is_hidden, + 'required': self.is_required, + 'True': True, + } + + if self.is_hidden: + context['hidden'] = True + + if value is None: + value = '' + + if value != '': + context['value'] = self.format_value(value) + + context.update(self.get_context_data()) + context['attrs'] = self.build_attrs(attrs) + + for key, attr in context['attrs'].items(): + + +## ... source file abbreviated to get to force_str examples ... + + + + +class HiddenInput(Input): + template_name = 'floppyforms/hidden.html' + input_type = 'hidden' + + +class MultipleHiddenInput(HiddenInput): + def __init__(self, attrs=None, choices=()): + super(MultipleHiddenInput, self).__init__(attrs) + self.choices = choices + + def render(self, name, value, attrs=None, choices=(), renderer=None): + if value is None: + value = [] + + final_attrs = self.build_attrs(attrs) + id_ = final_attrs.get('id', None) + inputs = [] + for i, v in enumerate(value): + input_attrs = final_attrs.copy() + if id_: + input_attrs['id'] = '%s_%s' % (id_, i) + input_ = HiddenInput() + input_.is_required = self.is_required +~~ inputs.append(input_.render(name, force_str(v), input_attrs, renderer=renderer)) + return mark_safe("\n".join(inputs)) + + def value_from_datadict(self, data, files, name): + if isinstance(data, MULTIVALUE_DICT_TYPES): + return data.getlist(name) + return data.get(name, None) + + +class SlugInput(TextInput): + template_name = 'floppyforms/slug.html' + + def get_context(self, name, value, attrs): + context = super(SlugInput, self).get_context(name, value, attrs) + context['attrs']['pattern'] = r"[-\w]+" + return context + + +class IPAddressInput(TextInput): + template_name = 'floppyforms/ipaddress.html' + + ip_pattern = (r"(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25" + r"[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}") + + def get_context(self, name, value, attrs): + + +## ... source file abbreviated to get to force_str examples ... + + + + +def boolean_check(v): + return not (v is False or v is None or v == '') + + +class CheckboxInput(Input, forms.CheckboxInput): + template_name = 'floppyforms/checkbox.html' + input_type = 'checkbox' + + def __init__(self, attrs=None, check_test=None): + super(CheckboxInput, self).__init__(attrs) + self.check_test = boolean_check if check_test is None else check_test + + def get_context(self, name, value, attrs): + result = self.check_test(value) + context = super(CheckboxInput, self).get_context(name, value, attrs) + if result: + context['attrs']['checked'] = True + return context + + def format_value(self, value): + if value in ('', True, False, None): + value = None + else: +~~ value = force_str(value) + return value + + def value_from_datadict(self, data, files, name): + return forms.CheckboxInput.value_from_datadict(self, data, files, name) + + if django.VERSION < (1, 6): + def _has_changed(self, initial, data): + if initial == 'False': + initial = False + return bool(initial) != bool(data) + + +class Select(Input): + allow_multiple_selected = False + template_name = 'floppyforms/select.html' + + def __init__(self, attrs=None, choices=()): + super(Select, self).__init__(attrs) + self.choices = list(choices) + + def get_context(self, name, value, attrs=None, choices=()): + if not hasattr(value, '__iter__') or isinstance(value, + str): + value = [value] + context = super(Select, self).get_context(name, value, attrs) + + if self.allow_multiple_selected: + context['attrs']['multiple'] = "multiple" + + groups = [] + for option_value, option_label in chain(self.choices, choices): + if isinstance(option_label, (list, tuple)): + group = [] + for val, lab in option_label: + group.append((force_str(val), lab)) + groups.append((option_value, group)) + else: +~~ option_value = force_str(option_value) + if groups and groups[-1][0] is None: + groups[-1][1].append((option_value, option_label)) + else: + groups.append((None, [(option_value, option_label)])) + context["optgroups"] = groups + return context + + def format_value(self, value): + if len(value) == 1 and value[0] is None: + return [] + return set(force_str(v) for v in value) + + +class NullBooleanSelect(Select): + def __init__(self, attrs=None): + choices = (('1', _('Unknown')), + ('2', _('Yes')), + ('3', _('No'))) + super(NullBooleanSelect, self).__init__(attrs, choices) + + def format_value(self, value): + value = value[0] + try: + value = {True: '2', False: '3', '2': '2', '3': '3'}[value] + + +## ... source file abbreviated to get to force_str examples ... + + + template_name = 'floppyforms/radio.html' + + +class CheckboxSelectMultiple(SelectMultiple): + template_name = 'floppyforms/checkbox_select.html' + + +class MultiWidget(forms.MultiWidget): + @property + def is_hidden(self): + return all(w.is_hidden for w in self.widgets) + + def build_attrs(self, base_attrs, extra_attrs=None, **kwargs): + attrs = dict(self.attrs, **kwargs) + attrs.update(base_attrs) + if extra_attrs: + attrs.update(extra_attrs) + return attrs + + if django.VERSION < (1, 11): + def format_value(self, value): + if value == '' or value is None: + return None + if self.is_localized: + return formats.localize_input(value) +~~ return force_str(value) + + def get_context(self, name, value, attrs): + context = {} + context['widget'] = { + 'name': name, + 'is_hidden': self.is_hidden, + 'required': self.is_required, + 'value': self.format_value(value), + 'attrs': self.build_attrs(self.attrs, attrs), + 'template_name': self.template_name, + } + if self.is_localized: + for widget in self.widgets: + widget.is_localized = self.is_localized + if not isinstance(value, list): + value = self.decompress(value) + + final_attrs = context['widget']['attrs'] + input_type = final_attrs.pop('type', None) + id_ = final_attrs.get('id') + subwidgets = [] + for i, widget in enumerate(self.widgets): + if input_type is not None: + widget.input_type = input_type + + +## ... source file continues with no further force_str examples... + +``` + + +## Example 5 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / core.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./core.py) + +```python +# core.py +from itertools import chain + +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Permission +from django.db.models.query import QuerySet +~~from django.utils.encoding import force_str + +from guardian.conf import settings as guardian_settings +from guardian.ctypes import get_content_type +from guardian.utils import get_group_obj_perms_model, get_identity, get_user_obj_perms_model + + +def _get_pks_model_and_ctype(objects): + + if isinstance(objects, QuerySet): + model = objects.model + pks = [force_str(pk) for pk in objects.values_list('pk', flat=True)] + ctype = get_content_type(model) + else: + pks = [] + for idx, obj in enumerate(objects): + if not idx: + model = type(obj) + ctype = get_content_type(model) + pks.append(force_str(obj.pk)) + + return pks, model, ctype + + +class ObjectPermissionChecker: + + +## ... source file abbreviated to get to force_str examples ... + + + return [] + + if guardian_settings.AUTO_PREFETCH: + self._prefetch_cache() + + ctype = get_content_type(obj) + key = self.get_local_cache_key(obj) + if key not in self._obj_perms_cache: + if guardian_settings.AUTO_PREFETCH: + return [] + if self.user and self.user.is_superuser: + perms = list(chain(*Permission.objects + .filter(content_type=ctype) + .values_list("codename"))) + elif self.user: + user_perms = self.get_user_perms(obj) + group_perms = self.get_group_perms(obj) + perms = list(set(chain(user_perms, group_perms))) + else: + perms = list(set(self.get_group_perms(obj))) + self._obj_perms_cache[key] = perms + return self._obj_perms_cache[key] + + def get_local_cache_key(self, obj): + ctype = get_content_type(obj) +~~ return (ctype.id, force_str(obj.pk)) + + def prefetch_perms(self, objects): + if self.user and not self.user.is_active: + return [] + + User = get_user_model() + pks, model, ctype = _get_pks_model_and_ctype(objects) + + if self.user and self.user.is_superuser: + perms = list(chain( + *Permission.objects + .filter(content_type=ctype) + .values_list("codename"))) + + for pk in pks: +~~ key = (ctype.id, force_str(pk)) + self._obj_perms_cache[key] = perms + + return True + + group_model = get_group_obj_perms_model(model) + + if self.user: + fieldname = 'group__{}'.format( + User.groups.field.related_query_name(), + ) + group_filters = {fieldname: self.user} + else: + group_filters = {'group': self.group} + + if group_model.objects.is_generic(): + group_filters.update({ + 'content_type': ctype, + 'object_pk__in': pks, + }) + else: + group_filters.update({ + 'content_object_id__in': pks + }) + + + +## ... source file abbreviated to get to force_str examples ... + + + 'content_type': ctype, + 'object_pk__in': pks + }) + else: + user_filters.update({ + 'content_object_id__in': pks + }) + + user_perms_qs = model.objects.filter(**user_filters).select_related('permission') + group_perms_qs = group_model.objects.filter(**group_filters).select_related('permission') + perms = chain(user_perms_qs, group_perms_qs) + else: + perms = chain( + *(group_model.objects.filter(**group_filters).select_related('permission'),) + ) + + for obj in objects: + key = self.get_local_cache_key(obj) + if key not in self._obj_perms_cache: + self._obj_perms_cache[key] = [] + + for perm in perms: + if type(perm).objects.is_generic(): + key = (ctype.id, perm.object_pk) + else: +~~ key = (ctype.id, force_str(perm.content_object_id)) + + self._obj_perms_cache[key].append(perm.permission.codename) + + return True + + @staticmethod + def _init_obj_prefetch_cache(obj, *querysets): + cache = {} + for qs in querysets: + perms = qs.select_related('permission__codename').values_list('content_type_id', 'object_pk', + 'permission__codename') + for p in perms: + if p[:2] not in cache: + cache[p[:2]] = [] + cache[p[:2]] += [p[2], ] + obj._guardian_perms_cache = cache + return obj, cache + + def _prefetch_cache(self): + from guardian.utils import get_user_obj_perms_model, get_group_obj_perms_model + UserObjectPermission = get_user_obj_perms_model() + GroupObjectPermission = get_group_obj_perms_model() + if self.user: + obj = self.user + + +## ... source file continues with no further force_str examples... + +``` + + +## Example 6 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / models.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./models.py) + +```python +# models.py + +from django.core.exceptions import ObjectDoesNotExist +~~from django.utils.encoding import force_str +from django.utils.text import capfirst + +from haystack.constants import DEFAULT_ALIAS +from haystack.exceptions import NotHandled, SpatialError +from haystack.utils import log as logging +from haystack.utils.app_loading import haystack_get_model + +try: + from geopy import distance as geopy_distance +except ImportError: + geopy_distance = None + + +class SearchResult(object): + + def __init__(self, app_label, model_name, pk, score, **kwargs): + self.app_label, self.model_name = app_label, model_name + self.pk = pk + self.score = score + self._object = None + self._model = None + self._verbose_name = None + self._additional_fields = [] + self._point_of_origin = kwargs.pop("_point_of_origin", None) + self._distance = kwargs.pop("_distance", None) + self.stored_fields = None + self.log = self._get_log() + + for key, value in kwargs.items(): + if key not in self.__dict__: + self.__dict__[key] = value + self._additional_fields.append(key) + + def _get_log(self): + return logging.getLogger("haystack") + + def __repr__(self): + return "" % ( + self.app_label, + self.model_name, + self.pk, + ) + + def __str__(self): +~~ return force_str(self.__repr__()) + + def __getattr__(self, attr): + if attr == "__getnewargs__": + raise AttributeError + + return self.__dict__.get(attr, None) + + def _get_searchindex(self): + from haystack import connections + + return connections[DEFAULT_ALIAS].get_unified_index().get_index(self.model) + + searchindex = property(_get_searchindex) + + def _get_object(self): + if self._object is None: + if self.model is None: + self.log.error("Model could not be found for SearchResult '%s'.", self) + return None + + try: + try: + self._object = self.searchindex.read_queryset().get(pk=self.pk) + except NotHandled: + + +## ... source file abbreviated to get to force_str examples ... + + + ) + + po_lng, po_lat = self._point_of_origin["point"].coords + location_field = getattr(self, self._point_of_origin["field"]) + + if location_field is None: + return None + + lf_lng, lf_lat = location_field.coords + self._distance = Distance( + km=geopy_distance.distance((po_lat, po_lng), (lf_lat, lf_lng)).km + ) + + return self._distance + + def _set_distance(self, dist): + self._distance = dist + + distance = property(_get_distance, _set_distance) + + def _get_verbose_name(self): + if self.model is None: + self.log.error("Model could not be found for SearchResult '%s'.", self) + return "" + +~~ return force_str(capfirst(self.model._meta.verbose_name)) + + verbose_name = property(_get_verbose_name) + + def _get_verbose_name_plural(self): + if self.model is None: + self.log.error("Model could not be found for SearchResult '%s'.", self) + return "" + +~~ return force_str(capfirst(self.model._meta.verbose_name_plural)) + + verbose_name_plural = property(_get_verbose_name_plural) + + def content_type(self): + if self.model is None: + self.log.error("Model could not be found for SearchResult '%s'.", self) + return "" + + return str(self.model._meta) + + def get_additional_fields(self): + additional_fields = {} + + for fieldname in self._additional_fields: + additional_fields[fieldname] = getattr(self, fieldname) + + return additional_fields + + def get_stored_fields(self): + if self._stored_fields is None: + from haystack import connections + + try: + index = connections[DEFAULT_ALIAS].get_unified_index().get_index(self.model) + + +## ... source file continues with no further force_str examples... + +``` + + +## Example 7 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / widgets.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./widgets.py) + +```python +# widgets.py +import json +from datetime import date, datetime +from decimal import Decimal + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.utils import datetime_safe, timezone +from django.utils.dateparse import parse_duration +~~from django.utils.encoding import force_str, smart_str + + +class Widget: + def clean(self, value, row=None, *args, **kwargs): + return value + + def render(self, value, obj=None): +~~ return force_str(value) + + +class NumberWidget(Widget): + + def is_empty(self, value): + if isinstance(value, str): + value = value.strip() + return value is None or value == "" + + def render(self, value, obj=None): + return value + + +class FloatWidget(NumberWidget): + + def clean(self, value, row=None, *args, **kwargs): + if self.is_empty(value): + return None + return float(value) + + +class IntegerWidget(NumberWidget): + + def clean(self, value, row=None, *args, **kwargs): + if self.is_empty(value): + return None + return int(float(value)) + + +class DecimalWidget(NumberWidget): + + def clean(self, value, row=None, *args, **kwargs): + if self.is_empty(value): + return None + return Decimal(force_str(value)) + + +class CharWidget(Widget): + + def render(self, value, obj=None): +~~ return force_str(value) + + +class BooleanWidget(Widget): + TRUE_VALUES = ["1", 1, True, "true", "TRUE", "True"] + FALSE_VALUES = ["0", 0, False, "false", "FALSE", "False"] + NULL_VALUES = ["", None, "null", "NULL", "none", "NONE", "None"] + + def render(self, value, obj=None): + if value in self.NULL_VALUES: + return "" + return self.TRUE_VALUES[0] if value else self.FALSE_VALUES[0] + + def clean(self, value, row=None, *args, **kwargs): + if value in self.NULL_VALUES: + return None + return True if value in self.TRUE_VALUES else False + + +class DateWidget(Widget): + + def __init__(self, format=None): + if format is None: + if not settings.DATE_INPUT_FORMATS: + formats = ("%Y-%m-%d",) + + +## ... source file continues with no further force_str examples... + +``` + + +## Example 8 from django-jsonfield +[django-jsonfield](https://github.com/dmkoch/django-jsonfield) +([jsonfield on PyPi](https://pypi.org/project/jsonfield/)) is a +[Django](/django.html) code library that makes it easier to store validated +JSON in a [Django object-relational mapper (ORM)](/django-orm.html) database +model. + +The django-jsonfield project is open source under the +[MIT license](https://github.com/dmkoch/django-jsonfield/blob/master/LICENSE). + +[**django-jsonfield / src/jsonfield / encoder.py**](https://github.com/dmkoch/django-jsonfield/blob/master/src/jsonfield/./encoder.py) + +```python +# encoder.py +import datetime +import decimal +import json +import uuid + +from django.db.models.query import QuerySet +from django.utils import timezone +~~from django.utils.encoding import force_str +from django.utils.functional import Promise + + +class JSONEncoder(json.JSONEncoder): + def default(self, obj): # noqa: C901 + if isinstance(obj, Promise): +~~ return force_str(obj) + elif isinstance(obj, datetime.datetime): + representation = obj.isoformat() + if representation.endswith('+00:00'): + representation = representation[:-6] + 'Z' + return representation + elif isinstance(obj, datetime.date): + return obj.isoformat() + elif isinstance(obj, datetime.time): + if timezone and timezone.is_aware(obj): + raise ValueError("JSON can't represent timezone-aware times.") + representation = obj.isoformat() + return representation + elif isinstance(obj, datetime.timedelta): + return str(obj.total_seconds()) + elif isinstance(obj, decimal.Decimal): + return float(obj) + elif isinstance(obj, uuid.UUID): + return str(obj) + elif isinstance(obj, QuerySet): + return tuple(obj) + elif isinstance(obj, bytes): + return obj.decode() + elif hasattr(obj, 'tolist'): + return obj.tolist() + + +## ... source file continues with no further force_str examples... + +``` + + +## Example 9 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / validators.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./validators.py) + +```python +# validators.py +import re +from urllib.parse import urlsplit + +from django.core.exceptions import ValidationError +from django.core.validators import URLValidator +~~from django.utils.encoding import force_str + + +class URIValidator(URLValidator): + scheme_re = r"^(?:[a-z][a-z0-9\.\-\+]*)://" + + dotless_domain_re = r"(?!-)[A-Z\d-]{1,63}(?' + else: + li_format = '
  • {3}
  • ' +~~ err_tuple = (e[0], e[3], e[4], force_text(e[5])) + error_lists[e[2]].append(format_html(li_format, *err_tuple)) + dirty_errors, pristine_errors = '', '' + if len(error_lists['$dirty']) > 0: + dirty_errors = format_html( + '
      {2}
    ', # duck typing: !...$untouched + first[0], first[1], mark_safe(''.join(error_lists['$dirty'])) + ) + if len(error_lists['$pristine']) > 0: + pristine_errors = format_html( + '
      {2}
    ', + first[0], first[1], mark_safe(''.join(error_lists['$pristine'])) + ) + return format_html('{}{}', dirty_errors, pristine_errors) + return format_html('
      {0}
    ', + format_html_join('', '
  • {0}
  • ', ((force_text(e),) for e in self))) + + def as_text(self): + if not self: + return '' + if isinstance(self[0], tuple): +~~ return '\n'.join(['* %s' % force_text(e[5]) for e in self if bool(e[5])]) +~~ return '\n'.join(['* %s' % force_text(e) for e in self]) + + def __str__(self): + return self.as_ul() + + def __repr__(self): + if self and isinstance(self[0], tuple): + return repr([force_text(e[5]) for e in self]) + return repr([force_text(e) for e in self]) + + def __contains__(self, item): + return item in list(self) + + def __eq__(self, other): + return list(self) == other + + def __ne__(self, other): + return list(self) != other + + def __getitem__(self, i): + error = self.data[i] + if isinstance(error, tuple): + if isinstance(error[5], ValidationError): + error[5] = list(error[5])[0] + return error + if isinstance(error, ValidationError): + return list(error)[0] +~~ return force_text(error) + + +class NgWidgetMixin(object): + def get_context(self, name, value, attrs): + context = super(NgWidgetMixin, self).get_context(name, value, attrs) + if callable(getattr(self._field, 'update_widget_rendering_context', None)): + self._field.update_widget_rendering_context(context) + return context + + +class NgBoundField(forms.BoundField): + @property + def errors(self): + if not hasattr(self, '_errors_cache'): + self._errors_cache = self.form.get_field_errors(self) + return self._errors_cache + + def css_classes(self, extra_classes=None): + if hasattr(extra_classes, 'split'): + extra_classes = extra_classes.split() + extra_classes = set(extra_classes or []) + field_css_classes = getattr(self.form, 'field_css_classes', None) + if hasattr(field_css_classes, 'split'): + extra_classes.update(field_css_classes.split()) + + +## ... source file continues with no further force_text examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_base.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_base.py) + +```python +# plugin_base.py +import json +import re + +from django.shortcuts import render as render_to_response + +from django import forms +from django.contrib import admin +from django.contrib import messages +from django.core.exceptions import ( + ImproperlyConfigured, + ObjectDoesNotExist, + ValidationError, +) +~~from django.utils.encoding import force_text, smart_str +from django.utils.html import escapejs +from django.utils.translation import ugettext, ugettext_lazy as _ + +from six import with_metaclass, python_2_unicode_compatible + +from cms import operations +from cms.exceptions import SubClassNeededError +from cms.models import CMSPlugin +from cms.toolbar.utils import get_plugin_tree_as_json, get_plugin_toolbar_info +from cms.utils.conf import get_cms_setting + + +class CMSPluginBaseMetaclass(forms.MediaDefiningClass): + def __new__(cls, name, bases, attrs): + super_new = super(CMSPluginBaseMetaclass, cls).__new__ + parents = [base for base in bases if isinstance(base, CMSPluginBaseMetaclass)] + if not parents: + return super_new(cls, name, bases, attrs) + new_plugin = super_new(cls, name, bases, attrs) + if not issubclass(new_plugin.model, CMSPlugin): + raise SubClassNeededError( + "The 'model' attribute on CMSPluginBase subclasses must be " + "either CMSPlugin or a subclass of CMSPlugin. %r on %r is not." + % (new_plugin.model, new_plugin) + + +## ... source file abbreviated to get to force_text examples ... + + + else: + parent_id = obj.parent.pk if obj.parent else None + tree_order = obj.placeholder.get_plugin_tree_order(parent_id) + operation_kwargs['plugin'] = obj + operation_kwargs['operation'] = operations.ADD_PLUGIN + operation_kwargs['tree_order'] = tree_order + self._operation_token = pl_admin._send_pre_placeholder_operation(**operation_kwargs) + + self.saved_object = obj + return super(CMSPluginBase, self).save_model(request, obj, form, change) + + def save_form(self, request, form, change): + obj = super(CMSPluginBase, self).save_form(request, form, change) + + for field, value in self._cms_initial_attributes.items(): + setattr(obj, field, value) + return obj + + def response_add(self, request, obj, **kwargs): + self.object_successfully_changed = True + return self.render_close_frame(request, obj) + + def response_change(self, request, obj): + self.object_successfully_changed = True + opts = self.model._meta +~~ msg_dict = {'name': force_text(opts.verbose_name), 'obj': force_text(obj)} + msg = _('The %(name)s "%(obj)s" was changed successfully.') % msg_dict + self.message_user(request, msg, messages.SUCCESS) + return self.render_close_frame(request, obj) + + def log_addition(self, request, obj, bypass=None): + pass + + def log_change(self, request, obj, message, bypass=None): + pass + + def log_deletion(self, request, obj, object_repr, bypass=None): + pass + + def icon_src(self, instance): + return "" + + def icon_alt(self, instance): +~~ return "%s - %s" % (force_text(self.name), force_text(instance)) + + def get_fieldsets(self, request, obj=None): + fieldsets = super(CMSPluginBase, self).get_fieldsets(request, obj) + + for name, data in fieldsets: + if data.get('fields'): # if fieldset with non-empty fields is found, return fieldsets + return fieldsets + + if self.inlines: + return [] # if plugin has inlines but no own fields return empty fieldsets to remove empty white fieldset + + try: # if all fieldsets are empty (assuming there is only one fieldset then) add description + fieldsets[0][1]['description'] = self.get_empty_change_form_text(obj=obj) + except KeyError: + pass + return fieldsets + + @classmethod + def get_empty_change_form_text(cls, obj=None): + return ugettext('There are no further settings for this plugin. Please press save.') + + @classmethod + def get_child_class_overrides(cls, slot, page): + from cms.utils.placeholder import get_placeholder_conf + + +## ... source file continues with no further force_text examples... + +``` + + +## Example 3 from django-downloadview +[django-downloadview](https://github.com/benoitbryon/django-downloadview) +([project documentation](https://django-downloadview.readthedocs.io/en/1.9/) +and +[PyPI package information](https://pypi.org/project/django-downloadview/)) +is a [Django](/django.html) extension for serving downloads through your +web application. While typically you would use a web server to handle +[static content](/static-content.html), sometimes you need to control +file access, such as requiring a user to register before downloading a +PDF. In that situations, django-downloadview is a handy library to avoid +boilerplate code for common scenarios. + +[**django-downloadview / django_downloadview / io.py**](https://github.com/benoitbryon/django-downloadview/blob/master/django_downloadview/./io.py) + +```python +# io.py +import io + +~~from django.utils.encoding import force_bytes, force_text + + +class TextIteratorIO(io.TextIOBase): + + def __init__(self, iterator): + self._iter = iterator + + self._left = "" + + def readable(self): + return True + + def _read1(self, n=None): + while not self._left: + try: + self._left = next(self._iter) + except StopIteration: + break + else: +~~ self._left = force_text(self._left) + ret = self._left[:n] + self._left = self._left[len(ret) :] + return ret + + def read(self, n=None): + chunks = [] + if n is None or n < 0: + while True: + m = self._read1() + if not m: + break + chunks.append(m) + else: + while n > 0: + m = self._read1(n) + if not m: + break + n -= len(m) + chunks.append(m) + return "".join(chunks) + + def readline(self): + chunks = [] + while True: + + +## ... source file continues with no further force_text examples... + +``` + + +## Example 4 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / folderadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/folderadmin.py) + +```python +# folderadmin.py +from __future__ import absolute_import, division, unicode_literals + +import itertools +import os +import re +from collections import OrderedDict + +from django import forms +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import messages +from django.contrib.admin import helpers +from django.contrib.admin.utils import capfirst, quote, unquote +from django.core.exceptions import PermissionDenied, ValidationError +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db import models, router +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +~~from django.utils.encoding import force_text +from django.utils.html import escape +from django.utils.http import urlquote, urlunquote +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy, ungettext + +from .. import settings +from ..models import ( + File, Folder, FolderPermission, FolderRoot, ImagesWithMissingData, + UnsortedImages, tools, +) +from ..settings import FILER_IMAGE_MODEL, FILER_PAGINATE_BY +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import get_delete_permission +from ..utils.filer_easy_thumbnails import FilerActionThumbnailer +from ..utils.loader import load_model +from . import views +from .forms import CopyFilesAndFoldersForm, RenameFilesForm, ResizeImagesForm +from .patched.admin_utils import get_deleted_objects +from .permissions import PrimitivePermissionAwareModelAdmin +from .tools import ( + AdminContext, admin_url_params_encoded, check_files_edit_permissions, + check_files_read_permissions, check_folder_edit_permissions, + check_folder_read_permissions, popup_status, userperms_for_request, + + +## ... source file abbreviated to get to force_text examples ... + + + app_label = opts.app_label + + if not self.has_delete_permission(request): + raise PermissionDenied + + current_folder = self._get_current_action_folder( + request, files_queryset, folders_queryset) + + all_protected = [] + + using = router.db_for_write(self.model) + deletable_files, model_count_files, perms_needed_files, protected_files = get_deleted_objects(files_queryset, files_queryset.model._meta, request.user, self.admin_site, using) + deletable_folders, model_count_folder, perms_needed_folders, protected_folders = get_deleted_objects(folders_queryset, folders_queryset.model._meta, request.user, self.admin_site, using) + all_protected.extend(protected_files) + all_protected.extend(protected_folders) + + all_deletable_objects = [deletable_files, deletable_folders] + all_perms_needed = perms_needed_files.union(perms_needed_folders) + + if request.POST.get('post'): + if all_perms_needed: + raise PermissionDenied + n = files_queryset.count() + folders_queryset.count() + if n: + for f in files_queryset: +~~ self.log_deletion(request, f, force_text(f)) + f.delete() + folder_ids = set() + for folder in folders_queryset: + folder_ids.add(folder.id) + folder_ids.update( + folder.get_descendants().values_list('id', flat=True)) + for f in File.objects.filter(folder__in=folder_ids): +~~ self.log_deletion(request, f, force_text(f)) + f.delete() + for f in folders_queryset: +~~ self.log_deletion(request, f, force_text(f)) + f.delete() + self.message_user(request, _("Successfully deleted %(count)d files and/or folders.") % {"count": n, }) + return None + + if all_perms_needed or all_protected: + title = _("Cannot delete files and/or folders") + else: + title = _("Are you sure?") + + context = self.admin_site.each_context(request) + context.update({ + "title": title, + "instance": current_folder, + "breadcrumbs_action": _("Delete files and/or folders"), + "deletable_objects": all_deletable_objects, + "files_queryset": files_queryset, + "folders_queryset": folders_queryset, + "perms_lacking": all_perms_needed, + "protected": all_protected, + "opts": opts, + 'is_popup': popup_status(request), + 'filer_admin_context': AdminContext(request), + "root_path": reverse('admin:index'), + "app_label": app_label, + + +## ... source file abbreviated to get to force_text examples ... + + + request, + "admin/filer/delete_selected_files_confirmation.html", + context + ) + + delete_files_or_folders.short_description = ugettext_lazy( + "Delete selected files and/or folders") + + def _format_callback(self, obj, user, admin_site, perms_needed): + has_admin = obj.__class__ in admin_site._registry + opts = obj._meta + if has_admin: + admin_url = reverse('%s:%s_%s_change' + % (admin_site.name, + opts.app_label, + opts.object_name.lower()), + None, (quote(obj._get_pk_val()),)) + p = get_delete_permission(opts) + if not user.has_perm(p): + perms_needed.add(opts.verbose_name) + return mark_safe('%s: %s' % + (escape(capfirst(opts.verbose_name)), + admin_url, + escape(obj))) + else: +~~ return '%s: %s' % (capfirst(opts.verbose_name), force_text(obj)) + + def _check_copy_perms(self, request, files_queryset, folders_queryset): + try: + check_files_read_permissions(request, files_queryset) + check_folder_read_permissions(request, folders_queryset) + except PermissionDenied: + return True + return False + + def _check_move_perms(self, request, files_queryset, folders_queryset): + try: + check_files_read_permissions(request, files_queryset) + check_folder_read_permissions(request, folders_queryset) + check_files_edit_permissions(request, files_queryset) + check_folder_edit_permissions(request, folders_queryset) + except PermissionDenied: + return True + return False + + def _get_current_action_folder(self, request, files_queryset, + folders_queryset): + if files_queryset: + return files_queryset[0].folder + elif folders_queryset: + + +## ... source file abbreviated to get to force_text examples ... + + + else: + return None + + def _list_folders_to_copy_or_move(self, request, folders): + for fo in folders: + yield self._format_callback(fo, request.user, self.admin_site, set()) + children = list(self._list_folders_to_copy_or_move(request, fo.children.all())) + children.extend([self._format_callback(f, request.user, self.admin_site, set()) for f in sorted(fo.files)]) + if children: + yield children + + def _list_all_to_copy_or_move(self, request, files_queryset, folders_queryset): + to_copy_or_move = list(self._list_folders_to_copy_or_move(request, folders_queryset)) + to_copy_or_move.extend([self._format_callback(f, request.user, self.admin_site, set()) for f in sorted(files_queryset)]) + return to_copy_or_move + + def _list_all_destination_folders_recursive(self, request, folders_queryset, current_folder, folders, allow_self, level): + for fo in folders: + if not allow_self and fo in folders_queryset: + continue + + if not fo.has_read_permission(request): + continue + + enabled = (allow_self or fo != current_folder) and fo.has_add_children_permission(request) +~~ yield (fo, (mark_safe(("  " * level) + force_text(fo)), enabled)) + for c in self._list_all_destination_folders_recursive(request, folders_queryset, current_folder, fo.children.all(), allow_self, level + 1): + yield c + + def _list_all_destination_folders(self, request, folders_queryset, current_folder, allow_self): + root_folders = self.get_queryset(request).filter(parent__isnull=True).order_by('name') + return list(self._list_all_destination_folders_recursive(request, folders_queryset, current_folder, root_folders, allow_self, 0)) + + def _move_files_and_folders_impl(self, files_queryset, folders_queryset, destination): + for f in files_queryset: + f.folder = destination + f.save() + for f in folders_queryset: + f.move_to(destination, 'last-child') + f.save() + + def move_files_and_folders(self, request, files_queryset, folders_queryset): + opts = self.model._meta + app_label = opts.app_label + + current_folder = self._get_current_action_folder(request, files_queryset, folders_queryset) + perms_needed = self._check_move_perms(request, files_queryset, folders_queryset) + to_move = self._list_all_to_copy_or_move(request, files_queryset, folders_queryset) + folders = self._list_all_destination_folders(request, folders_queryset, current_folder, False) + + + +## ... source file continues with no further force_text examples... + +``` + + +## Example 5 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / utils.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./utils.py) + +```python +# utils.py +import datetime +import json +from django.template import Context +from django.utils import translation +from jet import settings +from jet.models import PinnedApplication + +try: + from django.apps.registry import apps +except ImportError: + try: + from django.apps import apps # Fix Django 1.7 import issue + except ImportError: + pass +from django.core.serializers.json import DjangoJSONEncoder +from django.http import HttpResponse +try: + from django.core.urlresolvers import reverse, resolve, NoReverseMatch +except ImportError: # Django 1.11 + from django.urls import reverse, resolve, NoReverseMatch + +from django.contrib.admin import AdminSite +from django.utils.encoding import smart_text +from django.utils.text import capfirst +from django.contrib import messages +~~from django.utils.encoding import force_text +from django.utils.functional import Promise +from django.contrib.admin.options import IncorrectLookupParameters +from django.contrib import admin +from django.utils.translation import ugettext_lazy as _ +from django.utils.text import slugify + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # Python 2.6 + + +class JsonResponse(HttpResponse): + + def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs): + if safe and not isinstance(data, dict): + raise TypeError('In order to allow non-dict objects to be ' + 'serialized set the safe parameter to False') + kwargs.setdefault('content_type', 'application/json') + data = json.dumps(data, cls=encoder) + super(JsonResponse, self).__init__(content=data, **kwargs) + + +def get_app_list(context, order=True): + + +## ... source file abbreviated to get to force_text examples ... + + + try: + current_resolver = resolve(context.get('request').path) + index_resolver = resolve(reverse('%s:index' % current_resolver.namespaces[0])) + + if hasattr(index_resolver.func, 'admin_site'): + return index_resolver.func.admin_site + + for func_closure in index_resolver.func.__closure__: + if isinstance(func_closure.cell_contents, AdminSite): + return func_closure.cell_contents + except: + pass + + return admin.site + + +def get_admin_site_name(context): + return get_admin_site(context).name + + +class LazyDateTimeEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date): + return obj.isoformat() + elif isinstance(obj, Promise): +~~ return force_text(obj) + return self.encode(obj) + + +def get_model_instance_label(instance): + if getattr(instance, "related_label", None): + return instance.related_label() + return smart_text(instance) + + +class SuccessMessageMixin(object): + success_message = '' + + def form_valid(self, form): + response = super(SuccessMessageMixin, self).form_valid(form) + success_message = self.get_success_message(form.cleaned_data) + if success_message: + messages.success(self.request, success_message) + return response + + def get_success_message(self, cleaned_data): + return self.success_message % cleaned_data + + +def get_model_queryset(admin_site, model, request, preserved_filters=None): + + +## ... source file continues with no further force_text examples... + +``` + + +## Example 6 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / compressors / __init__.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/compressors/__init__.py) + +```python +# __init__.py +import base64 +import os +import posixpath +import re +import subprocess + +from itertools import takewhile + +from django.contrib.staticfiles.storage import staticfiles_storage +~~from django.utils.encoding import smart_bytes, force_text + +from pipeline.conf import settings +from pipeline.exceptions import CompressorError +from pipeline.utils import to_class, relpath, set_std_streams_blocking + +URL_DETECTOR = r"""url\((['"]?)\s*(.*?)\1\)""" +URL_REPLACER = r"""url\(__EMBED__(.+?)(\?\d+)?\)""" +NON_REWRITABLE_URL = re.compile(r'^(#|http:|https:|data:|//)') + +DEFAULT_TEMPLATE_FUNC = "template" +TEMPLATE_FUNC = r"""var template = function(str){var fn = new Function('obj', 'var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push(\''+str.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/<%=([\s\S]+?)%>/g,function(match,code){return "',"+code.replace(/\\'/g, "'")+",'";}).replace(/<%([\s\S]+?)%>/g,function(match,code){return "');"+code.replace(/\\'/g, "'").replace(/[\r\n\t]/g,' ')+"__p.push('";}).replace(/\r/g,'\\r').replace(/\n/g,'\\n').replace(/\t/g,'\\t')+"');}return __p.join('');");return fn;};""" + +MIME_TYPES = { + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.gif': 'image/gif', + '.tif': 'image/tiff', + '.tiff': 'image/tiff', + '.ttf': 'font/truetype', + '.otf': 'font/opentype', + '.woff': 'font/woff' +} +EMBED_EXTS = MIME_TYPES.keys() + + +## ... source file abbreviated to get to force_text examples ... + + + def embeddable(self, path, variant): + name, ext = os.path.splitext(path) + font = ext in FONT_EXTS + if not variant: + return False + if not (re.search(settings.EMBED_PATH, path.replace('\\', '/')) and self.storage.exists(path)): + return False + if ext not in EMBED_EXTS: + return False + if not (font or len(self.encoded_content(path)) < settings.EMBED_MAX_IMAGE_SIZE): + return False + return True + + def with_data_uri(self, css): + def datauri(match): + path = match.group(1) + mime_type = self.mime_type(path) + data = self.encoded_content(path) + return f"url(\"data:{mime_type};charset=utf-8;base64,{data}\")" + return re.sub(URL_REPLACER, datauri, css) + + def encoded_content(self, path): + if path in self.__class__.asset_contents: + return self.__class__.asset_contents[path] + data = self.read_bytes(path) +~~ self.__class__.asset_contents[path] = force_text(base64.b64encode(data)) + return self.__class__.asset_contents[path] + + def mime_type(self, path): + name, ext = os.path.splitext(path) + return MIME_TYPES[ext] + + def absolute_path(self, path, start): + if posixpath.isabs(path): + path = posixpath.join(staticfiles_storage.location, path) + else: + path = posixpath.join(start, path) + return posixpath.normpath(path) + + def relative_path(self, absolute_path, output_filename): + absolute_path = posixpath.join(settings.PIPELINE_ROOT, absolute_path) + output_path = posixpath.join(settings.PIPELINE_ROOT, posixpath.dirname(output_filename)) + return relpath(absolute_path, output_path) + + def read_bytes(self, path): + file = staticfiles_storage.open(path) + content = file.read() + file.close() + return content + + def read_text(self, path): + content = self.read_bytes(path) +~~ return force_text(content) + + +class CompressorBase(object): + def __init__(self, verbose): + self.verbose = verbose + + def filter_css(self, css): + raise NotImplementedError + + def filter_js(self, js): + raise NotImplementedError + + +class SubProcessCompressor(CompressorBase): + def execute_command(self, command, content): + argument_list = [] + for flattening_arg in command: + if isinstance(flattening_arg, (str,)): + argument_list.append(flattening_arg) + else: + argument_list.extend(flattening_arg) + + pipe = subprocess.Popen(argument_list, stdout=subprocess.PIPE, + stdin=subprocess.PIPE, stderr=subprocess.PIPE) + if content: + content = smart_bytes(content) + stdout, stderr = pipe.communicate(content) + set_std_streams_blocking() + if stderr.strip() and pipe.returncode != 0: + raise CompressorError(stderr) + elif self.verbose: + print(stderr) +~~ return force_text(stdout) + + +class NoopCompressor(CompressorBase): + def compress_js(self, js): + return js + + def compress_css(self, css): + return css + + + +## ... source file continues with no further force_text examples... + +``` + diff --git a/content/pages/examples/django/django-utils-encoding-iri-to-uri.markdown b/content/pages/examples/django/django-utils-encoding-iri-to-uri.markdown new file mode 100644 index 000000000..5f11c5609 --- /dev/null +++ b/content/pages/examples/django/django-utils-encoding-iri-to-uri.markdown @@ -0,0 +1,176 @@ +title: django.utils.encoding iri_to_uri Example Code +category: page +slug: django-utils-encoding-iri-to-uri-examples +sortorder: 500011445 +toc: False +sidebartitle: django.utils.encoding iri_to_uri +meta: Python example code for the iri_to_uri callable from the django.utils.encoding module of the Django project. + + +iri_to_uri is a callable within the django.utils.encoding module of the Django project. + + +## Example 1 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / http.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./http.py) + +```python +# http.py +from urllib.parse import urlparse + +from django.core.exceptions import DisallowedRedirect +from django.http import HttpResponse +~~from django.utils.encoding import iri_to_uri + + +class OAuth2ResponseRedirect(HttpResponse): + status_code = 302 + + def __init__(self, redirect_to, allowed_schemes, *args, **kwargs): + super().__init__(*args, **kwargs) +~~ self["Location"] = iri_to_uri(redirect_to) + self.allowed_schemes = allowed_schemes + self.validate_redirect(redirect_to) + + @property + def url(self): + return self["Location"] + + def validate_redirect(self, redirect_to): + parsed = urlparse(str(redirect_to)) + if not parsed.scheme: + raise DisallowedRedirect("OAuth2 redirects require a URI scheme.") + if parsed.scheme not in self.allowed_schemes: + raise DisallowedRedirect( + "Redirect to scheme {!r} is not permitted".format(parsed.scheme) + ) + + + +## ... source file continues with no further iri_to_uri examples... + +``` + + +## Example 2 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / templatetags / rest_framework.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/templatetags/rest_framework.py) + +```python +# rest_framework.py +import re +from collections import OrderedDict + +from django import template +from django.template import loader +from django.urls import NoReverseMatch, reverse +~~from django.utils.encoding import force_str, iri_to_uri +from django.utils.html import escape, format_html, smart_urlquote +from django.utils.safestring import SafeData, mark_safe + +from rest_framework.compat import apply_markdown, pygments_highlight +from rest_framework.renderers import HTMLFormRenderer +from rest_framework.utils.urls import replace_query_param + +register = template.Library() + +class_re = re.compile(r'(?<=class=["\'])(.*)(?=["\'])') + + +@register.tag(name='code') +def highlight_code(parser, token): + code = token.split_contents()[-1] + nodelist = parser.parse(('endcode',)) + parser.delete_first_token() + return CodeNode(code, nodelist) + + +class CodeNode(template.Node): + style = 'emacs' + + def __init__(self, lang, code): + + +## ... source file abbreviated to get to iri_to_uri examples ... + + +@register.simple_tag +def optional_logout(request, user): + try: + logout_url = reverse('rest_framework:logout') + except NoReverseMatch: + snippet = format_html('', user=escape(user)) + return mark_safe(snippet) + + snippet = """""" + snippet = format_html(snippet, user=escape(user), href=logout_url, next=escape(request.path)) + + return mark_safe(snippet) + + +@register.simple_tag +def add_query_param(request, key, val): + iri = request.get_full_path() +~~ uri = iri_to_uri(iri) + return escape(replace_query_param(uri, key, val)) + + +@register.filter +def as_string(value): + if value is None: + return '' + return '%s' % value + + +@register.filter +def as_list_of_strings(value): + return [ + '' if (item is None) else ('%s' % item) + for item in value + ] + + +@register.filter +def add_class(value, css_class): + html = str(value) + match = class_re.search(html) + if match: + m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class, + + +## ... source file continues with no further iri_to_uri examples... + +``` + diff --git a/content/pages/examples/django/django-utils-encoding-is-protected-type.markdown b/content/pages/examples/django/django-utils-encoding-is-protected-type.markdown new file mode 100644 index 000000000..a28dcd7df --- /dev/null +++ b/content/pages/examples/django/django-utils-encoding-is-protected-type.markdown @@ -0,0 +1,121 @@ +title: django.utils.encoding is_protected_type Example Code +category: page +slug: django-utils-encoding-is-protected-type-examples +sortorder: 500011446 +toc: False +sidebartitle: django.utils.encoding is_protected_type +meta: Python example code for the is_protected_type callable from the django.utils.encoding module of the Django project. + + +is_protected_type is a callable within the django.utils.encoding module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / fields.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./fields.py) + +```python +# fields.py +import datetime +import decimal +import functools +import inspect +import re +import uuid +import warnings +from collections import OrderedDict +from collections.abc import Mapping + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import ( + EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator, + MinValueValidator, ProhibitNullCharactersValidator, RegexValidator, + URLValidator, ip_address_validators +) +from django.forms import FilePathField as DjangoFilePathField +from django.forms import ImageField as DjangoImageField +from django.utils import timezone +from django.utils.dateparse import ( + parse_date, parse_datetime, parse_duration, parse_time +) +from django.utils.duration import duration_string +~~from django.utils.encoding import is_protected_type, smart_str +from django.utils.formats import localize_input, sanitize_separators +from django.utils.ipv6 import clean_ipv6_address +from django.utils.timezone import utc +from django.utils.translation import gettext_lazy as _ +from pytz.exceptions import InvalidTimeError + +from rest_framework import ( + ISO_8601, RemovedInDRF313Warning, RemovedInDRF314Warning +) +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.settings import api_settings +from rest_framework.utils import html, humanize_datetime, json, representation +from rest_framework.utils.formatting import lazy_format +from rest_framework.validators import ProhibitSurrogateCharactersValidator + + +class empty: + pass + + +class BuiltinSignatureError(Exception): + pass + + + + +## ... source file abbreviated to get to is_protected_type examples ... + + +class ModelField(Field): + default_error_messages = { + 'max_length': _('Ensure this field has no more than {max_length} characters.'), + } + + def __init__(self, model_field, **kwargs): + self.model_field = model_field + self.max_length = kwargs.pop('max_length', None) + super().__init__(**kwargs) + if self.max_length is not None: + message = lazy_format(self.error_messages['max_length'], max_length=self.max_length) + self.validators.append( + MaxLengthValidator(self.max_length, message=message)) + + def to_internal_value(self, data): + rel = self.model_field.remote_field + if rel is not None: + return rel.model._meta.get_field(rel.field_name).to_python(data) + return self.model_field.to_python(data) + + def get_attribute(self, obj): + return obj + + def to_representation(self, obj): + value = self.model_field.value_from_object(obj) +~~ if is_protected_type(value): + return value + return self.model_field.value_to_string(obj) + + + +## ... source file continues with no further is_protected_type examples... + +``` + diff --git a/content/pages/examples/django/django-utils-encoding-smart-bytes.markdown b/content/pages/examples/django/django-utils-encoding-smart-bytes.markdown new file mode 100644 index 000000000..762cb4379 --- /dev/null +++ b/content/pages/examples/django/django-utils-encoding-smart-bytes.markdown @@ -0,0 +1,117 @@ +title: django.utils.encoding smart_bytes Example Code +category: page +slug: django-utils-encoding-smart-bytes-examples +sortorder: 500011447 +toc: False +sidebartitle: django.utils.encoding smart_bytes +meta: Python example code for the smart_bytes callable from the django.utils.encoding module of the Django project. + + +smart_bytes is a callable within the django.utils.encoding module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / compressors / __init__.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/compressors/__init__.py) + +```python +# __init__.py +import base64 +import os +import posixpath +import re +import subprocess + +from itertools import takewhile + +from django.contrib.staticfiles.storage import staticfiles_storage +~~from django.utils.encoding import smart_bytes, force_text + +from pipeline.conf import settings +from pipeline.exceptions import CompressorError +from pipeline.utils import to_class, relpath, set_std_streams_blocking + +URL_DETECTOR = r"""url\((['"]?)\s*(.*?)\1\)""" +URL_REPLACER = r"""url\(__EMBED__(.+?)(\?\d+)?\)""" +NON_REWRITABLE_URL = re.compile(r'^(#|http:|https:|data:|//)') + +DEFAULT_TEMPLATE_FUNC = "template" +TEMPLATE_FUNC = r"""var template = function(str){var fn = new Function('obj', 'var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push(\''+str.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/<%=([\s\S]+?)%>/g,function(match,code){return "',"+code.replace(/\\'/g, "'")+",'";}).replace(/<%([\s\S]+?)%>/g,function(match,code){return "');"+code.replace(/\\'/g, "'").replace(/[\r\n\t]/g,' ')+"__p.push('";}).replace(/\r/g,'\\r').replace(/\n/g,'\\n').replace(/\t/g,'\\t')+"');}return __p.join('');");return fn;};""" + +MIME_TYPES = { + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.gif': 'image/gif', + '.tif': 'image/tiff', + '.tiff': 'image/tiff', + '.ttf': 'font/truetype', + '.otf': 'font/opentype', + '.woff': 'font/woff' +} +EMBED_EXTS = MIME_TYPES.keys() + + +## ... source file abbreviated to get to smart_bytes examples ... + + + + +class CompressorBase(object): + def __init__(self, verbose): + self.verbose = verbose + + def filter_css(self, css): + raise NotImplementedError + + def filter_js(self, js): + raise NotImplementedError + + +class SubProcessCompressor(CompressorBase): + def execute_command(self, command, content): + argument_list = [] + for flattening_arg in command: + if isinstance(flattening_arg, (str,)): + argument_list.append(flattening_arg) + else: + argument_list.extend(flattening_arg) + + pipe = subprocess.Popen(argument_list, stdout=subprocess.PIPE, + stdin=subprocess.PIPE, stderr=subprocess.PIPE) + if content: +~~ content = smart_bytes(content) + stdout, stderr = pipe.communicate(content) + set_std_streams_blocking() + if stderr.strip() and pipe.returncode != 0: + raise CompressorError(stderr) + elif self.verbose: + print(stderr) + return force_text(stdout) + + +class NoopCompressor(CompressorBase): + def compress_js(self, js): + return js + + def compress_css(self, css): + return css + + + +## ... source file continues with no further smart_bytes examples... + +``` + diff --git a/content/pages/examples/django/django-utils-encoding-smart-str.markdown b/content/pages/examples/django/django-utils-encoding-smart-str.markdown new file mode 100644 index 000000000..e75686ef7 --- /dev/null +++ b/content/pages/examples/django/django-utils-encoding-smart-str.markdown @@ -0,0 +1,366 @@ +title: django.utils.encoding smart_str Example Code +category: page +slug: django-utils-encoding-smart-str-examples +sortorder: 500011448 +toc: False +sidebartitle: django.utils.encoding smart_str +meta: Python example code for the smart_str callable from the django.utils.encoding module of the Django project. + + +smart_str is a callable within the django.utils.encoding module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_base.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_base.py) + +```python +# plugin_base.py +import json +import re + +from django.shortcuts import render as render_to_response + +from django import forms +from django.contrib import admin +from django.contrib import messages +from django.core.exceptions import ( + ImproperlyConfigured, + ObjectDoesNotExist, + ValidationError, +) +~~from django.utils.encoding import force_text, smart_str +from django.utils.html import escapejs +from django.utils.translation import ugettext, ugettext_lazy as _ + +from six import with_metaclass, python_2_unicode_compatible + +from cms import operations +from cms.exceptions import SubClassNeededError +from cms.models import CMSPlugin +from cms.toolbar.utils import get_plugin_tree_as_json, get_plugin_toolbar_info +from cms.utils.conf import get_cms_setting + + +class CMSPluginBaseMetaclass(forms.MediaDefiningClass): + def __new__(cls, name, bases, attrs): + super_new = super(CMSPluginBaseMetaclass, cls).__new__ + parents = [base for base in bases if isinstance(base, CMSPluginBaseMetaclass)] + if not parents: + return super_new(cls, name, bases, attrs) + new_plugin = super_new(cls, name, bases, attrs) + if not issubclass(new_plugin.model, CMSPlugin): + raise SubClassNeededError( + "The 'model' attribute on CMSPluginBase subclasses must be " + "either CMSPlugin or a subclass of CMSPlugin. %r on %r is not." + % (new_plugin.model, new_plugin) + + +## ... source file abbreviated to get to smart_str examples ... + + + def get_parent_classes(cls, slot, page, instance=None): + from cms.utils.placeholder import get_placeholder_conf + + template = page.get_template() if page else None + + ph_conf = get_placeholder_conf('parent_classes', slot, template, default={}) + parent_classes = ph_conf.get(cls.__name__, cls.parent_classes) + return parent_classes + + def get_plugin_urls(self): + return [] + + def plugin_urls(self): + return self.get_plugin_urls() + plugin_urls = property(plugin_urls) + + @classmethod + def get_extra_placeholder_menu_items(self, request, placeholder): + pass + + @classmethod + def get_extra_plugin_menu_items(cls, request, plugin): + pass + + def __repr__(self): +~~ return smart_str(self.name) + + def __str__(self): + return self.name + + +class PluginMenuItem(object): + + def __init__(self, name, url, data=None, question=None, action='ajax', attributes=None): + if not attributes: + attributes = {} + + if data: + data = json.dumps(data) + + self.name = name + self.url = url + self.data = data + self.question = question + self.action = action + self.attributes = attributes + + + +## ... source file continues with no further smart_str examples... + +``` + + +## Example 2 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / admin / __init__.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/admin/__init__.py) + +```python +# __init__.py +import six +import operator +from functools import update_wrapper +from six.moves import reduce +from typing import Tuple, Dict, Callable # NOQA + +from django.apps import apps +from django.http import HttpResponse, HttpResponseNotFound +from django.conf import settings +from django.db import models +from django.db.models.query import QuerySet +~~from django.utils.encoding import smart_str +from django.utils.translation import gettext as _ +from django.utils.text import get_text_list +from django.contrib import admin + +from django_extensions.admin.widgets import ForeignKeySearchInput + + +class ForeignKeyAutocompleteAdminMixin: + + related_search_fields = {} # type: Dict[str, Tuple[str]] + related_string_functions = {} # type: Dict[str, Callable] + autocomplete_limit = getattr(settings, 'FOREIGNKEY_AUTOCOMPLETE_LIMIT', None) + + def get_urls(self): + from django.urls import path + + def wrap(view): + def wrapper(*args, **kwargs): + return self.admin_site.admin_view(view)(*args, **kwargs) + return update_wrapper(wrapper, view) + + return [ + path('foreignkey_autocomplete/', wrap(self.foreignkey_autocomplete), + name='%s_%s_autocomplete' % (self.model._meta.app_label, self.model._meta.model_name)) + + +## ... source file abbreviated to get to smart_str examples ... + + + search_fields = request.GET.get('search_fields', None) + object_pk = request.GET.get('object_pk', None) + + try: + to_string_function = self.related_string_functions[model_name] + except KeyError: + to_string_function = lambda x: x.__str__() + + if search_fields and app_label and model_name and (query or object_pk): + def construct_search(field_name): + if field_name.startswith('^'): + return "%s__istartswith" % field_name[1:] + elif field_name.startswith('='): + return "%s__iexact" % field_name[1:] + elif field_name.startswith('@'): + return "%s__search" % field_name[1:] + else: + return "%s__icontains" % field_name + + model = apps.get_model(app_label, model_name) + + queryset = model._default_manager.all() + data = '' + if query: + for bit in query.split(): +~~ or_queries = [models.Q(**{construct_search(smart_str(field_name)): smart_str(bit)}) for field_name in search_fields.split(',')] + other_qs = QuerySet(model) + other_qs.query.select_related = queryset.query.select_related + other_qs = other_qs.filter(reduce(operator.or_, or_queries)) + queryset = queryset & other_qs + + additional_filter = self.get_related_filter(model, request) + if additional_filter: + queryset = queryset.filter(additional_filter) + + if self.autocomplete_limit: + queryset = queryset[:self.autocomplete_limit] + + data = ''.join([six.u('%s|%s\n') % (to_string_function(f), f.pk) for f in queryset]) + elif object_pk: + try: + obj = queryset.get(pk=object_pk) + except Exception: # FIXME: use stricter exception checking + pass + else: + data = to_string_function(obj) + return HttpResponse(data, content_type='text/plain') + return HttpResponseNotFound() + + def get_related_filter(self, model, request): + + +## ... source file continues with no further smart_str examples... + +``` + + +## Example 3 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / fields.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./fields.py) + +```python +# fields.py +import datetime +import decimal +import functools +import inspect +import re +import uuid +import warnings +from collections import OrderedDict +from collections.abc import Mapping + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import ( + EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator, + MinValueValidator, ProhibitNullCharactersValidator, RegexValidator, + URLValidator, ip_address_validators +) +from django.forms import FilePathField as DjangoFilePathField +from django.forms import ImageField as DjangoImageField +from django.utils import timezone +from django.utils.dateparse import ( + parse_date, parse_datetime, parse_duration, parse_time +) +from django.utils.duration import duration_string +~~from django.utils.encoding import is_protected_type, smart_str +from django.utils.formats import localize_input, sanitize_separators +from django.utils.ipv6 import clean_ipv6_address +from django.utils.timezone import utc +from django.utils.translation import gettext_lazy as _ +from pytz.exceptions import InvalidTimeError + +from rest_framework import ( + ISO_8601, RemovedInDRF313Warning, RemovedInDRF314Warning +) +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.settings import api_settings +from rest_framework.utils import html, humanize_datetime, json, representation +from rest_framework.utils.formatting import lazy_format +from rest_framework.validators import ProhibitSurrogateCharactersValidator + + +class empty: + pass + + +class BuiltinSignatureError(Exception): + pass + + + + +## ... source file abbreviated to get to smart_str examples ... + + + + if self.max_digits is not None and self.decimal_places is not None: + self.max_whole_digits = self.max_digits - self.decimal_places + else: + self.max_whole_digits = None + + super().__init__(**kwargs) + + if self.max_value is not None: + message = lazy_format(self.error_messages['max_value'], max_value=self.max_value) + self.validators.append( + MaxValueValidator(self.max_value, message=message)) + if self.min_value is not None: + message = lazy_format(self.error_messages['min_value'], min_value=self.min_value) + self.validators.append( + MinValueValidator(self.min_value, message=message)) + + if rounding is not None: + valid_roundings = [v for k, v in vars(decimal).items() if k.startswith('ROUND_')] + assert rounding in valid_roundings, ( + 'Invalid rounding option %s. Valid values for rounding are: %s' % (rounding, valid_roundings)) + self.rounding = rounding + + def to_internal_value(self, data): + +~~ data = smart_str(data).strip() + + if self.localize: + data = sanitize_separators(data) + + if len(data) > self.MAX_STRING_LENGTH: + self.fail('max_string_length') + + try: + value = decimal.Decimal(data) + except decimal.DecimalException: + self.fail('invalid') + + if value.is_nan(): + self.fail('invalid') + + if value in (decimal.Decimal('Inf'), decimal.Decimal('-Inf')): + self.fail('invalid') + + return self.quantize(self.validate_precision(value)) + + def validate_precision(self, value): + sign, digittuple, exponent = value.as_tuple() + + if exponent >= 0: + + +## ... source file continues with no further smart_str examples... + +``` + diff --git a/content/pages/examples/django/django-utils-encoding-smart-text.markdown b/content/pages/examples/django/django-utils-encoding-smart-text.markdown new file mode 100644 index 000000000..82d6442d5 --- /dev/null +++ b/content/pages/examples/django/django-utils-encoding-smart-text.markdown @@ -0,0 +1,509 @@ +title: django.utils.encoding smart_text Example Code +category: page +slug: django-utils-encoding-smart-text-examples +sortorder: 500011449 +toc: False +sidebartitle: django.utils.encoding smart_text +meta: Python example code for the smart_text callable from the django.utils.encoding module of the Django project. + + +smart_text is a callable within the django.utils.encoding module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog / models.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog/models.py) + +```python +# models.py +from __future__ import unicode_literals + +import json +import ast + +from django.conf import settings +from django.contrib.contenttypes.fields import GenericRelation +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import FieldDoesNotExist +from django.db import models, DEFAULT_DB_ALIAS +from django.db.models import QuerySet, Q +from django.utils import formats, timezone +~~from django.utils.encoding import python_2_unicode_compatible, smart_text +from django.utils.six import iteritems, integer_types +from django.utils.translation import ugettext_lazy as _ + +from jsonfield.fields import JSONField +from dateutil import parser +from dateutil.tz import gettz + + +class LogEntryManager(models.Manager): + + def log_create(self, instance, **kwargs): + changes = kwargs.get('changes', None) + pk = self._get_pk_value(instance) + + if changes is not None: + kwargs.setdefault('content_type', ContentType.objects.get_for_model(instance)) + kwargs.setdefault('object_pk', pk) +~~ kwargs.setdefault('object_repr', smart_text(instance)) + + if isinstance(pk, integer_types): + kwargs.setdefault('object_id', pk) + + get_additional_data = getattr(instance, 'get_additional_data', None) + if callable(get_additional_data): + kwargs.setdefault('additional_data', get_additional_data()) + + if kwargs.get('action', None) is LogEntry.Action.CREATE: + if kwargs.get('object_id', None) is not None and self.filter(content_type=kwargs.get('content_type'), object_id=kwargs.get('object_id')).exists(): + self.filter(content_type=kwargs.get('content_type'), object_id=kwargs.get('object_id')).delete() + else: + self.filter(content_type=kwargs.get('content_type'), object_pk=kwargs.get('object_pk', '')).delete() + db = instance._state.db + return self.create(**kwargs) if db is None or db == '' else self.using(db).create(**kwargs) + return None + + def get_for_object(self, instance): + if not isinstance(instance, models.Model): + return self.none() + + content_type = ContentType.objects.get_for_model(instance.__class__) + pk = self._get_pk_value(instance) + + + +## ... source file abbreviated to get to smart_text examples ... + + + + def __str__(self): + if self.action == self.Action.CREATE: + fstring = _("Created {repr:s}") + elif self.action == self.Action.UPDATE: + fstring = _("Updated {repr:s}") + elif self.action == self.Action.DELETE: + fstring = _("Deleted {repr:s}") + else: + fstring = _("Logged {repr:s}") + + return fstring.format(repr=self.object_repr) + + @property + def changes_dict(self): + try: + return json.loads(self.changes) + except ValueError: + return {} + + @property +~~ def changes_str(self, colon=': ', arrow=smart_text(' \u2192 '), separator='; '): + substrings = [] + + for field, values in iteritems(self.changes_dict): +~~ substring = smart_text('{field_name:s}{colon:s}{old:s}{arrow:s}{new:s}').format( + field_name=field, + colon=colon, + old=values[0], + arrow=arrow, + new=values[1], + ) + substrings.append(substring) + + return separator.join(substrings) + + @property + def changes_display_dict(self): + from auditlog.registry import auditlog + model = self.content_type.model_class() + model_fields = auditlog.get_model_fields(model._meta.model) + changes_display_dict = {} + for field_name, values in iteritems(self.changes_dict): + try: + field = model._meta.get_field(field_name) + except FieldDoesNotExist: + changes_display_dict[field_name] = values + continue + values_display = [] + choices_dict = None + if isinstance(pk, integer_types): + return self.filter(content_type=content_type, object_id=pk) + else: +~~ return self.filter(content_type=content_type, object_pk=smart_text(pk)) + + def get_for_objects(self, queryset): + if not isinstance(queryset, QuerySet) or queryset.count() == 0: + return self.none() + + content_type = ContentType.objects.get_for_model(queryset.model) + primary_keys = list(queryset.values_list(queryset.model._meta.pk.name, flat=True)) + + if isinstance(primary_keys[0], integer_types): + return self.filter(content_type=content_type).filter(Q(object_id__in=primary_keys)).distinct() + elif isinstance(queryset.model._meta.pk, models.UUIDField): + primary_keys = [smart_text(pk) for pk in primary_keys] + return self.filter(content_type=content_type).filter(Q(object_pk__in=primary_keys)).distinct() + else: + return self.filter(content_type=content_type).filter(Q(object_pk__in=primary_keys)).distinct() + + def get_for_model(self, model): + if not issubclass(model, models.Model): + return self.none() + + content_type = ContentType.objects.get_for_model(model) + + return self.filter(content_type=content_type) + + + +## ... source file abbreviated to get to smart_text examples ... + + + get_latest_by = 'timestamp' + ordering = ['-timestamp'] + verbose_name = _("log entry") + verbose_name_plural = _("log entries") + + +## ... source file continues with no further smart_text examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / templatetags / cms_tags.py**](https://github.com/divio/django-cms/blob/develop/cms/templatetags/cms_tags.py) + +```python +# cms_tags.py +from collections import namedtuple, OrderedDict +from copy import copy +from datetime import datetime + +from django import template +from django.conf import settings +from django.contrib.sites.models import Site +from django.core.mail import mail_managers +from django.db.models import Model +from django.middleware.common import BrokenLinkEmailsMiddleware +from django.template.loader import render_to_string +from django.urls import reverse +~~from django.utils.encoding import force_text, smart_text +from django.utils.html import escape +from django.utils.http import urlencode +from django.utils.translation import ( + get_language, + override as force_language, + ugettext_lazy as _, +) + +from six import string_types, integer_types + +from classytags.arguments import (Argument, MultiValueArgument, + MultiKeywordArgument) +from classytags.core import Options, Tag +from classytags.helpers import InclusionTag, AsTag +from classytags.parser import Parser +from classytags.utils import flatten_context +from classytags.values import ListValue, StringValue + +from cms.cache.page import get_page_url_cache, set_page_url_cache +from cms.exceptions import PlaceholderNotFound +from cms.models import Page, Placeholder as PlaceholderModel, CMSPlugin, StaticPlaceholder +from cms.plugin_pool import plugin_pool +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils import get_current_site, get_language_from_request, get_site_id + + +## ... source file abbreviated to get to smart_text examples ... + + + def render_tag(self, context, **kwargs): + context.push() + template = self.get_template(context, **kwargs) + data = self.get_context(context, **kwargs) + output = render_to_string(template, flatten_context(data)).strip() + context.pop() + if kwargs.get('varname'): + context[kwargs['varname']] = output + return '' + else: + return output + + def _get_editable_context(self, context, instance, language, edit_fields, + view_method, view_url, querystring, editmode=True): + request = context['request'] + if hasattr(request, 'toolbar'): + lang = request.toolbar.toolbar_language + else: + lang = get_language() + opts = instance._meta + if getattr(instance, '_deferred', False): + opts = opts.proxy_for_model._meta + with force_language(lang): + extra_context = {} + if edit_fields == 'changelist': +~~ instance.get_plugin_name = u"%s %s list" % (smart_text(_('Edit')), smart_text(opts.verbose_name)) + extra_context['attribute_name'] = 'changelist' + elif editmode: +~~ instance.get_plugin_name = u"%s %s" % (smart_text(_('Edit')), smart_text(opts.verbose_name)) + if not context.get('attribute_name', None): + extra_context['attribute_name'] = '-'.join(edit_fields) \ + if not isinstance('edit_fields', string_types) else edit_fields + else: +~~ instance.get_plugin_name = u"%s %s" % (smart_text(_('Add')), smart_text(opts.verbose_name)) + extra_context['attribute_name'] = 'add' + extra_context['instance'] = instance + extra_context['generic'] = opts + if view_method: + method = getattr(instance, view_method) + if callable(method): + url_base = method(context['request']) + else: + url_base = method + else: + if not editmode: + view_url = 'admin:%s_%s_add' % ( + opts.app_label, opts.model_name) + url_base = reverse(view_url) + elif not edit_fields: + if not view_url: + view_url = 'admin:%s_%s_change' % ( + opts.app_label, opts.model_name) + if isinstance(instance, Page): + url_base = reverse(view_url, args=(instance.pk, language)) + else: + url_base = reverse(view_url, args=(instance.pk,)) + else: + if not view_url: + + +## ... source file continues with no further smart_text examples... + +``` + + +## Example 3 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / utils.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./utils.py) + +```python +# utils.py +import datetime +import json +from django.template import Context +from django.utils import translation +from jet import settings +from jet.models import PinnedApplication + +try: + from django.apps.registry import apps +except ImportError: + try: + from django.apps import apps # Fix Django 1.7 import issue + except ImportError: + pass +from django.core.serializers.json import DjangoJSONEncoder +from django.http import HttpResponse +try: + from django.core.urlresolvers import reverse, resolve, NoReverseMatch +except ImportError: # Django 1.11 + from django.urls import reverse, resolve, NoReverseMatch + +from django.contrib.admin import AdminSite +~~from django.utils.encoding import smart_text +from django.utils.text import capfirst +from django.contrib import messages +from django.utils.encoding import force_text +from django.utils.functional import Promise +from django.contrib.admin.options import IncorrectLookupParameters +from django.contrib import admin +from django.utils.translation import ugettext_lazy as _ +from django.utils.text import slugify + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # Python 2.6 + + +class JsonResponse(HttpResponse): + + def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs): + if safe and not isinstance(data, dict): + raise TypeError('In order to allow non-dict objects to be ' + 'serialized set the safe parameter to False') + kwargs.setdefault('content_type', 'application/json') + data = json.dumps(data, cls=encoder) + super(JsonResponse, self).__init__(content=data, **kwargs) + + +## ... source file abbreviated to get to smart_text examples ... + + + for func_closure in index_resolver.func.__closure__: + if isinstance(func_closure.cell_contents, AdminSite): + return func_closure.cell_contents + except: + pass + + return admin.site + + +def get_admin_site_name(context): + return get_admin_site(context).name + + +class LazyDateTimeEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date): + return obj.isoformat() + elif isinstance(obj, Promise): + return force_text(obj) + return self.encode(obj) + + +def get_model_instance_label(instance): + if getattr(instance, "related_label", None): + return instance.related_label() +~~ return smart_text(instance) + + +class SuccessMessageMixin(object): + success_message = '' + + def form_valid(self, form): + response = super(SuccessMessageMixin, self).form_valid(form) + success_message = self.get_success_message(form.cleaned_data) + if success_message: + messages.success(self.request, success_message) + return response + + def get_success_message(self, cleaned_data): + return self.success_message % cleaned_data + + +def get_model_queryset(admin_site, model, request, preserved_filters=None): + model_admin = admin_site._registry.get(model) + + if model_admin is None: + return + + try: + changelist_url = reverse('%s:%s_%s_changelist' % ( + + +## ... source file continues with no further smart_text examples... + +``` + + +## Example 4 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / utils.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./utils.py) + +```python +# utils.py +try: + import fcntl +except ImportError: + fcntl = None + +import importlib +import mimetypes +import posixpath +import os +import sys + +from urllib.parse import quote + +~~from django.utils.encoding import smart_text + +from pipeline.conf import settings + + +def to_class(class_str): + if not class_str: + return None + + module_bits = class_str.split('.') + module_path, class_name = '.'.join(module_bits[:-1]), module_bits[-1] + module = importlib.import_module(module_path) + return getattr(module, class_name, None) + + +def filepath_to_uri(path): + if path is None: + return path + return quote(smart_text(path).replace("\\", "/"), safe="/-!*()'#?") + + +def guess_type(path, default=None): + for type, ext in settings.MIMETYPES: + mimetypes.add_type(type, ext) + mimetype, _ = mimetypes.guess_type(path) + if not mimetype: + return default +~~ return smart_text(mimetype) + + +def relpath(path, start=posixpath.curdir): + if not path: + raise ValueError("no path specified") + + start_list = posixpath.abspath(start).split(posixpath.sep) + path_list = posixpath.abspath(path).split(posixpath.sep) + + i = len(posixpath.commonprefix([start_list, path_list])) + + rel_list = [posixpath.pardir] * (len(start_list) - i) + path_list[i:] + if not rel_list: + return posixpath.curdir + return posixpath.join(*rel_list) + + +def set_std_streams_blocking(): + if not fcntl: + return + for f in (sys.__stdout__, sys.__stderr__): + fileno = f.fileno() + flags = fcntl.fcntl(fileno, fcntl.F_GETFL) + fcntl.fcntl(fileno, fcntl.F_SETFL, flags & -os.O_NONBLOCK) + + +## ... source file continues with no further smart_text examples... + +``` + diff --git a/content/pages/examples/django/django-utils-encoding-uri-to-iri.markdown b/content/pages/examples/django/django-utils-encoding-uri-to-iri.markdown new file mode 100644 index 000000000..cdef21329 --- /dev/null +++ b/content/pages/examples/django/django-utils-encoding-uri-to-iri.markdown @@ -0,0 +1,125 @@ +title: django.utils.encoding uri_to_iri Example Code +category: page +slug: django-utils-encoding-uri-to-iri-examples +sortorder: 500011450 +toc: False +sidebartitle: django.utils.encoding uri_to_iri +meta: Python example code for the uri_to_iri callable from the django.utils.encoding module of the Django project. + + +uri_to_iri is a callable within the django.utils.encoding module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / relations.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./relations.py) + +```python +# relations.py +import sys +from collections import OrderedDict +from urllib import parse + +from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist +from django.db.models import Manager +from django.db.models.query import QuerySet +from django.urls import NoReverseMatch, Resolver404, get_script_prefix, resolve +~~from django.utils.encoding import smart_str, uri_to_iri +from django.utils.translation import gettext_lazy as _ + +from rest_framework.fields import ( + Field, empty, get_attribute, is_simple_callable, iter_options +) +from rest_framework.reverse import reverse +from rest_framework.settings import api_settings +from rest_framework.utils import html + + +def method_overridden(method_name, klass, instance): + method = getattr(klass, method_name) + default_method = getattr(method, '__func__', method) # Python 3 compat + return default_method is not getattr(instance, method_name).__func__ + + +class ObjectValueError(ValueError): + + +class ObjectTypeError(TypeError): + + +class Hyperlink(str): + def __new__(cls, url, obj): + + +## ... source file abbreviated to get to uri_to_iri examples ... + + + except TypeError: + exc = ObjectTypeError(str(sys.exc_info()[1])) + raise exc.with_traceback(sys.exc_info()[2]) + + def get_url(self, obj, view_name, request, format): + if hasattr(obj, 'pk') and obj.pk in (None, ''): + return None + + lookup_value = getattr(obj, self.lookup_field) + kwargs = {self.lookup_url_kwarg: lookup_value} + return self.reverse(view_name, kwargs=kwargs, request=request, format=format) + + def to_internal_value(self, data): + request = self.context.get('request', None) + try: + http_prefix = data.startswith(('http:', 'https:')) + except AttributeError: + self.fail('incorrect_type', data_type=type(data).__name__) + + if http_prefix: + data = parse.urlparse(data).path + prefix = get_script_prefix() + if data.startswith(prefix): + data = '/' + data[len(prefix):] + +~~ data = uri_to_iri(parse.unquote(data)) + + try: + match = resolve(data) + except Resolver404: + self.fail('no_match') + + try: + expected_viewname = request.versioning_scheme.get_versioned_viewname( + self.view_name, request + ) + except AttributeError: + expected_viewname = self.view_name + + if match.view_name != expected_viewname: + self.fail('incorrect_match') + + try: + return self.get_object(match.view_name, match.args, match.kwargs) + except (ObjectDoesNotExist, ObjectValueError, ObjectTypeError): + self.fail('does_not_exist') + + def to_representation(self, value): + assert 'request' in self.context, ( + "`%s` requires the request in the serializer" + + +## ... source file continues with no further uri_to_iri examples... + +``` + diff --git a/content/pages/examples/django/django-utils-formats-get-format.markdown b/content/pages/examples/django/django-utils-formats-get-format.markdown new file mode 100644 index 000000000..23bcfe1a7 --- /dev/null +++ b/content/pages/examples/django/django-utils-formats-get-format.markdown @@ -0,0 +1,252 @@ +title: django.utils.formats get_format Example Code +category: page +slug: django-utils-formats-get-format-examples +sortorder: 500011451 +toc: False +sidebartitle: django.utils.formats get_format +meta: Python example code for the get_format callable from the django.utils.formats module of the Django project. + + +get_format is a callable within the django.utils.formats module of the Django project. + + +## Example 1 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / templatetags / jet_tags.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/templatetags/jet_tags.py) + +```python +# jet_tags.py +from __future__ import unicode_literals +import json +import os +from django import template +try: + from django.core.urlresolvers import reverse +except ImportError: # Django 1.11 + from django.urls import reverse + +from django.forms import CheckboxInput, ModelChoiceField, Select, ModelMultipleChoiceField, SelectMultiple +from django.contrib.admin.widgets import RelatedFieldWidgetWrapper +~~from django.utils.formats import get_format +from django.utils.safestring import mark_safe +from django.utils.encoding import smart_text +from jet import settings, VERSION +from jet.models import Bookmark +from jet.utils import get_model_instance_label, get_model_queryset, get_possible_language_codes, \ + get_admin_site, get_menu_items + +try: + from urllib.parse import parse_qsl +except ImportError: + from urlparse import parse_qsl + + +register = template.Library() +assignment_tag = register.assignment_tag if hasattr(register, 'assignment_tag') else register.simple_tag + + +@assignment_tag +def jet_get_date_format(): +~~ return get_format('DATE_INPUT_FORMATS')[0] + + +@assignment_tag +def jet_get_time_format(): +~~ return get_format('TIME_INPUT_FORMATS')[0] + + +@assignment_tag +def jet_get_datetime_format(): +~~ return get_format('DATETIME_INPUT_FORMATS')[0] + + +@assignment_tag(takes_context=True) +def jet_get_menu(context): + return get_menu_items(context) + + +@assignment_tag +def jet_get_bookmarks(user): + if user is None: + return None + return Bookmark.objects.filter(user=user.pk) + + +@register.filter +def jet_is_checkbox(field): + return field.field.widget.__class__.__name__ == CheckboxInput().__class__.__name__ + + +@register.filter +def jet_select2_lookups(field): + if hasattr(field, 'field') and \ + (isinstance(field.field, ModelChoiceField) or isinstance(field.field, ModelMultipleChoiceField)): + qs = field.field.queryset + + +## ... source file continues with no further get_format examples... + +``` + + +## Example 2 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / admin / widgets.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/admin/widgets.py) + +```python +# widgets.py +import itertools +import json +from functools import total_ordering + +from django import forms +from django.conf import settings +from django.forms import widgets +from django.forms.utils import flatatt +from django.template.loader import render_to_string +from django.urls import reverse +~~from django.utils.formats import get_format +from django.utils.functional import cached_property +from django.utils.html import format_html +from django.utils.translation import gettext_lazy as _ +from taggit.forms import TagWidget +from taggit.models import Tag + +from wagtail.admin.datetimepicker import to_datetimepicker_format +from wagtail.admin.staticfiles import versioned_static +from wagtail.core import hooks +from wagtail.core.models import Page +from wagtail.utils.widgets import WidgetWithScript + +DEFAULT_DATE_FORMAT = '%Y-%m-%d' +DEFAULT_DATETIME_FORMAT = '%Y-%m-%d %H:%M' +DEFAULT_TIME_FORMAT = '%H:%M' + + +class AdminAutoHeightTextInput(widgets.Textarea): + template_name = 'wagtailadmin/widgets/auto_height_text_input.html' + + def __init__(self, attrs=None): + default_attrs = {'rows': '1'} + if attrs: + default_attrs.update(attrs) + + super().__init__(default_attrs) + + +class AdminDateInput(widgets.DateInput): + template_name = 'wagtailadmin/widgets/date_input.html' + + def __init__(self, attrs=None, format=None): + default_attrs = {'autocomplete': 'off'} + fmt = format + if attrs: + default_attrs.update(attrs) + if fmt is None: + fmt = getattr(settings, 'WAGTAIL_DATE_FORMAT', DEFAULT_DATE_FORMAT) + self.js_format = to_datetimepicker_format(fmt) + super().__init__(attrs=default_attrs, format=fmt) + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + + config = { +~~ 'dayOfWeekStart': get_format('FIRST_DAY_OF_WEEK'), + 'format': self.js_format, + } + context['widget']['config_json'] = json.dumps(config) + + return context + + @property + def media(self): + return forms.Media(js=[ + versioned_static('wagtailadmin/js/date-time-chooser.js'), + ]) + + +class AdminTimeInput(widgets.TimeInput): + template_name = 'wagtailadmin/widgets/time_input.html' + + def __init__(self, attrs=None, format=None): + default_attrs = {'autocomplete': 'off'} + if attrs: + default_attrs.update(attrs) + fmt = format + if fmt is None: + fmt = getattr(settings, 'WAGTAIL_TIME_FORMAT', DEFAULT_TIME_FORMAT) + self.js_format = to_datetimepicker_format(fmt) + + +## ... source file abbreviated to get to get_format examples ... + + + versioned_static('wagtailadmin/js/date-time-chooser.js'), + ]) + + +class AdminDateTimeInput(widgets.DateTimeInput): + template_name = 'wagtailadmin/widgets/datetime_input.html' + + def __init__(self, attrs=None, format=None, time_format=None): + default_attrs = {'autocomplete': 'off'} + fmt = format + if attrs: + default_attrs.update(attrs) + if fmt is None: + fmt = getattr(settings, 'WAGTAIL_DATETIME_FORMAT', DEFAULT_DATETIME_FORMAT) + time_fmt = time_format + if time_fmt is None: + time_fmt = getattr(settings, 'WAGTAIL_TIME_FORMAT', DEFAULT_TIME_FORMAT) + self.js_format = to_datetimepicker_format(fmt) + self.js_time_format = to_datetimepicker_format(time_fmt) + super().__init__(attrs=default_attrs, format=fmt) + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + + config = { +~~ 'dayOfWeekStart': get_format('FIRST_DAY_OF_WEEK'), + 'format': self.js_format, + 'formatTime': self.js_time_format + } + context['widget']['config_json'] = json.dumps(config) + + return context + + @property + def media(self): + return forms.Media(js=[ + versioned_static('wagtailadmin/js/date-time-chooser.js'), + ]) + + +class AdminTagWidget(TagWidget): + template_name = 'wagtailadmin/widgets/tag_widget.html' + + def __init__(self, *args, **kwargs): + self.tag_model = kwargs.pop('tag_model', Tag) + self.free_tagging = kwargs.pop('free_tagging', None) + super().__init__(*args, **kwargs) + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + + +## ... source file continues with no further get_format examples... + +``` + diff --git a/content/pages/examples/django/django-utils-formats-localize-input.markdown b/content/pages/examples/django/django-utils-formats-localize-input.markdown new file mode 100644 index 000000000..a91cde6f6 --- /dev/null +++ b/content/pages/examples/django/django-utils-formats-localize-input.markdown @@ -0,0 +1,142 @@ +title: django.utils.formats localize_input Example Code +category: page +slug: django-utils-formats-localize-input-examples +sortorder: 500011452 +toc: False +sidebartitle: django.utils.formats localize_input +meta: Python example code for the localize_input callable from the django.utils.formats module of the Django project. + + +localize_input is a callable within the django.utils.formats module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / fields.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./fields.py) + +```python +# fields.py +import decimal +import functools +import inspect +import re +import uuid +import warnings +from collections import OrderedDict +from collections.abc import Mapping + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import ( + EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator, + MinValueValidator, ProhibitNullCharactersValidator, RegexValidator, + URLValidator, ip_address_validators +) +from django.forms import FilePathField as DjangoFilePathField +from django.forms import ImageField as DjangoImageField +from django.utils import timezone +from django.utils.dateparse import ( + parse_date, parse_datetime, parse_duration, parse_time +) +from django.utils.duration import duration_string +from django.utils.encoding import is_protected_type, smart_str +~~from django.utils.formats import localize_input, sanitize_separators +from django.utils.ipv6 import clean_ipv6_address +from django.utils.timezone import utc +from django.utils.translation import gettext_lazy as _ +from pytz.exceptions import InvalidTimeError + +from rest_framework import ( + ISO_8601, RemovedInDRF313Warning, RemovedInDRF314Warning +) +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.settings import api_settings +from rest_framework.utils import html, humanize_datetime, json, representation +from rest_framework.utils.formatting import lazy_format +from rest_framework.validators import ProhibitSurrogateCharactersValidator + + +class empty: + pass + + +class BuiltinSignatureError(Exception): + pass + + +def is_simple_callable(obj): + + +## ... source file abbreviated to get to localize_input examples ... + + + else: + total_digits = abs(exponent) + whole_digits = 0 + decimal_places = total_digits + + if self.max_digits is not None and total_digits > self.max_digits: + self.fail('max_digits', max_digits=self.max_digits) + if self.decimal_places is not None and decimal_places > self.decimal_places: + self.fail('max_decimal_places', max_decimal_places=self.decimal_places) + if self.max_whole_digits is not None and whole_digits > self.max_whole_digits: + self.fail('max_whole_digits', max_whole_digits=self.max_whole_digits) + + return value + + def to_representation(self, value): + coerce_to_string = getattr(self, 'coerce_to_string', api_settings.COERCE_DECIMAL_TO_STRING) + + if not isinstance(value, decimal.Decimal): + value = decimal.Decimal(str(value).strip()) + + quantized = self.quantize(value) + + if not coerce_to_string: + return quantized + if self.localize: +~~ return localize_input(quantized) + + return '{:f}'.format(quantized) + + def quantize(self, value): + if self.decimal_places is None: + return value + + context = decimal.getcontext().copy() + if self.max_digits is not None: + context.prec = self.max_digits + return value.quantize( + decimal.Decimal('.1') ** self.decimal_places, + rounding=self.rounding, + context=context + ) + + + +class DateTimeField(Field): + default_error_messages = { + 'invalid': _('Datetime has wrong format. Use one of these formats instead: {format}.'), + 'date': _('Expected a datetime but got a date.'), + 'make_aware': _('Invalid datetime for the timezone "{timezone}".'), + 'overflow': _('Datetime value out of range.') + + +## ... source file continues with no further localize_input examples... + +``` + diff --git a/content/pages/examples/django/django-utils-formats-sanitize-separators.markdown b/content/pages/examples/django/django-utils-formats-sanitize-separators.markdown new file mode 100644 index 000000000..d1a696a89 --- /dev/null +++ b/content/pages/examples/django/django-utils-formats-sanitize-separators.markdown @@ -0,0 +1,142 @@ +title: django.utils.formats sanitize_separators Example Code +category: page +slug: django-utils-formats-sanitize-separators-examples +sortorder: 500011453 +toc: False +sidebartitle: django.utils.formats sanitize_separators +meta: Python example code for the sanitize_separators callable from the django.utils.formats module of the Django project. + + +sanitize_separators is a callable within the django.utils.formats module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / fields.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./fields.py) + +```python +# fields.py +import decimal +import functools +import inspect +import re +import uuid +import warnings +from collections import OrderedDict +from collections.abc import Mapping + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import ( + EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator, + MinValueValidator, ProhibitNullCharactersValidator, RegexValidator, + URLValidator, ip_address_validators +) +from django.forms import FilePathField as DjangoFilePathField +from django.forms import ImageField as DjangoImageField +from django.utils import timezone +from django.utils.dateparse import ( + parse_date, parse_datetime, parse_duration, parse_time +) +from django.utils.duration import duration_string +from django.utils.encoding import is_protected_type, smart_str +~~from django.utils.formats import localize_input, sanitize_separators +from django.utils.ipv6 import clean_ipv6_address +from django.utils.timezone import utc +from django.utils.translation import gettext_lazy as _ +from pytz.exceptions import InvalidTimeError + +from rest_framework import ( + ISO_8601, RemovedInDRF313Warning, RemovedInDRF314Warning +) +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.settings import api_settings +from rest_framework.utils import html, humanize_datetime, json, representation +from rest_framework.utils.formatting import lazy_format +from rest_framework.validators import ProhibitSurrogateCharactersValidator + + +class empty: + pass + + +class BuiltinSignatureError(Exception): + pass + + +def is_simple_callable(obj): + + +## ... source file abbreviated to get to sanitize_separators examples ... + + + else: + self.max_whole_digits = None + + super().__init__(**kwargs) + + if self.max_value is not None: + message = lazy_format(self.error_messages['max_value'], max_value=self.max_value) + self.validators.append( + MaxValueValidator(self.max_value, message=message)) + if self.min_value is not None: + message = lazy_format(self.error_messages['min_value'], min_value=self.min_value) + self.validators.append( + MinValueValidator(self.min_value, message=message)) + + if rounding is not None: + valid_roundings = [v for k, v in vars(decimal).items() if k.startswith('ROUND_')] + assert rounding in valid_roundings, ( + 'Invalid rounding option %s. Valid values for rounding are: %s' % (rounding, valid_roundings)) + self.rounding = rounding + + def to_internal_value(self, data): + + data = smart_str(data).strip() + + if self.localize: +~~ data = sanitize_separators(data) + + if len(data) > self.MAX_STRING_LENGTH: + self.fail('max_string_length') + + try: + value = decimal.Decimal(data) + except decimal.DecimalException: + self.fail('invalid') + + if value.is_nan(): + self.fail('invalid') + + if value in (decimal.Decimal('Inf'), decimal.Decimal('-Inf')): + self.fail('invalid') + + return self.quantize(self.validate_precision(value)) + + def validate_precision(self, value): + sign, digittuple, exponent = value.as_tuple() + + if exponent >= 0: + total_digits = len(digittuple) + exponent + whole_digits = total_digits + decimal_places = 0 + + +## ... source file continues with no further sanitize_separators examples... + +``` + diff --git a/content/pages/examples/django/django-utils-formats.markdown b/content/pages/examples/django/django-utils-formats.markdown new file mode 100644 index 000000000..4367f4298 --- /dev/null +++ b/content/pages/examples/django/django-utils-formats.markdown @@ -0,0 +1,536 @@ +title: django.utils formats Example Code +category: page +slug: django-utils-formats-examples +sortorder: 500011418 +toc: False +sidebartitle: django.utils formats +meta: Python example code for the formats callable from the django.utils module of the Django project. + + +formats is a callable within the django.utils module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog_tests / tests.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog_tests/tests.py) + +```python +# tests.py +import datetime +import django +from django.conf import settings +from django.contrib import auth +from django.contrib.auth.models import User, AnonymousUser +from django.core.exceptions import ValidationError +from django.db.models.signals import pre_save +from django.http import HttpResponse +from django.test import TestCase, RequestFactory +~~from django.utils import dateformat, formats, timezone +from dateutil.tz import gettz + +from auditlog.middleware import AuditlogMiddleware +from auditlog.models import LogEntry +from auditlog.registry import auditlog +from auditlog_tests.models import SimpleModel, AltPrimaryKeyModel, UUIDPrimaryKeyModel, \ + ProxyModel, SimpleIncludeModel, SimpleExcludeModel, SimpleMappingModel, RelatedModel, \ + ManyRelatedModel, AdditionalDataIncludedModel, DateTimeFieldModel, ChoicesFieldModel, \ + CharfieldTextfieldModel, PostgresArrayFieldModel, NoDeleteHistoryModel +from auditlog import compat + + +class SimpleModelTest(TestCase): + def setUp(self): + self.obj = SimpleModel.objects.create(text='I am not difficult.') + + def test_create(self): + obj = self.obj + + self.assertTrue(obj.history.count() == 1, msg="There is one log entry") + + try: + history = obj.history.get() + except obj.history.DoesNotExist: + + +## ... source file abbreviated to get to formats examples ... + + + + self.assertTrue(dtm.history.count() == 2, msg="There are two log entries") + + def test_changes_display_dict_datetime(self): + timestamp = datetime.datetime(2017, 1, 10, 15, 0, tzinfo=timezone.utc) + date = datetime.date(2017, 1, 10) + time = datetime.time(12, 0) + dtm = DateTimeFieldModel(label='DateTimeField model', timestamp=timestamp, date=date, time=time, naive_dt=self.now) + dtm.save() + localized_timestamp = timestamp.astimezone(gettz(settings.TIME_ZONE)) + self.assertTrue(dtm.history.latest().changes_display_dict["timestamp"][1] == \ + dateformat.format(localized_timestamp, settings.DATETIME_FORMAT), + msg=("The datetime should be formatted according to Django's settings for" + " DATETIME_FORMAT")) + timestamp = timezone.now() + dtm.timestamp = timestamp + dtm.save() + localized_timestamp = timestamp.astimezone(gettz(settings.TIME_ZONE)) + self.assertTrue(dtm.history.latest().changes_display_dict["timestamp"][1] == \ + dateformat.format(localized_timestamp, settings.DATETIME_FORMAT), + msg=("The datetime should be formatted according to Django's settings for" + " DATETIME_FORMAT")) + + with self.settings(USE_L10N=True, LANGUAGE_CODE='en-GB'): + self.assertTrue(dtm.history.latest().changes_display_dict["timestamp"][1] == \ +~~ formats.localize(localized_timestamp), + msg=("The datetime should be formatted according to Django's settings for" + " USE_L10N is True with a different LANGUAGE_CODE.")) + + + def test_changes_display_dict_date(self): + timestamp = datetime.datetime(2017, 1, 10, 15, 0, tzinfo=timezone.utc) + date = datetime.date(2017, 1, 10) + time = datetime.time(12, 0) + dtm = DateTimeFieldModel(label='DateTimeField model', timestamp=timestamp, date=date, time=time, naive_dt=self.now) + dtm.save() + self.assertTrue(dtm.history.latest().changes_display_dict["date"][1] == \ + dateformat.format(date, settings.DATE_FORMAT), + msg=("The date should be formatted according to Django's settings for" + " DATE_FORMAT unless USE_L10N is True.")) + date = datetime.date(2017, 1, 11) + dtm.date = date + dtm.save() + self.assertTrue(dtm.history.latest().changes_display_dict["date"][1] == \ + dateformat.format(date, settings.DATE_FORMAT), + msg=("The date should be formatted according to Django's settings for" + " DATE_FORMAT unless USE_L10N is True.")) + + with self.settings(USE_L10N=True, LANGUAGE_CODE='en-GB'): + self.assertTrue(dtm.history.latest().changes_display_dict["date"][1] == \ +~~ formats.localize(date), + msg=("The date should be formatted according to Django's settings for" + " USE_L10N is True with a different LANGUAGE_CODE.")) + + def test_changes_display_dict_time(self): + timestamp = datetime.datetime(2017, 1, 10, 15, 0, tzinfo=timezone.utc) + date = datetime.date(2017, 1, 10) + time = datetime.time(12, 0) + dtm = DateTimeFieldModel(label='DateTimeField model', timestamp=timestamp, date=date, time=time, naive_dt=self.now) + dtm.save() + self.assertTrue(dtm.history.latest().changes_display_dict["time"][1] == \ + dateformat.format(time, settings.TIME_FORMAT), + msg=("The time should be formatted according to Django's settings for" + " TIME_FORMAT unless USE_L10N is True.")) + time = datetime.time(6, 0) + dtm.time = time + dtm.save() + self.assertTrue(dtm.history.latest().changes_display_dict["time"][1] == \ + dateformat.format(time, settings.TIME_FORMAT), + msg=("The time should be formatted according to Django's settings for" + " TIME_FORMAT unless USE_L10N is True.")) + + with self.settings(USE_L10N=True, LANGUAGE_CODE='en-GB'): + self.assertTrue(dtm.history.latest().changes_display_dict["time"][1] == \ +~~ formats.localize(time), + msg=("The time should be formatted according to Django's settings for" + " USE_L10N is True with a different LANGUAGE_CODE.")) + + def test_update_naive_dt(self): + timestamp = datetime.datetime(2017, 1, 10, 15, 0, tzinfo=timezone.utc) + date = datetime.date(2017, 1, 10) + time = datetime.time(12, 0) + dtm = DateTimeFieldModel(label='DateTimeField model', timestamp=timestamp, date=date, time=time, naive_dt=self.now) + dtm.save() + + dtm.naive_dt = timezone.make_naive(timezone.now(), timezone=timezone.utc) + dtm.save() + + +class UnregisterTest(TestCase): + def setUp(self): + auditlog.unregister(SimpleModel) + self.obj = SimpleModel.objects.create(text='No history') + + def tearDown(self): + auditlog.register(SimpleModel) + + def test_unregister_create(self): + obj = self.obj + + +## ... source file continues with no further formats examples... + +``` + + +## Example 2 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / widgets.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./widgets.py) + +```python +# widgets.py +import datetime +import re +from itertools import chain + +import django +from django import forms +from django.conf import settings +from django.forms.widgets import FILE_INPUT_CONTRADICTION +from django.template import loader +~~from django.utils import datetime_safe, formats +from django.utils.dates import MONTHS +from django.utils.encoding import force_str +from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + +from .compat import MULTIVALUE_DICT_TYPES, flatten_contexts + + +from django.forms.utils import to_current_timezone + + +RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$') + + +__all__ = ( + 'TextInput', 'PasswordInput', 'HiddenInput', 'ClearableFileInput', + 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', + 'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple', + 'RadioSelect', 'CheckboxSelectMultiple', 'SearchInput', 'RangeInput', + 'ColorInput', 'EmailInput', 'URLInput', 'PhoneNumberInput', 'NumberInput', + 'IPAddressInput', 'MultiWidget', 'Widget', 'SplitDateTimeWidget', + 'SplitHiddenDateTimeWidget', 'MultipleHiddenInput', 'SelectDateWidget', + 'SlugInput', + + +## ... source file abbreviated to get to formats examples ... + + + if not hasattr(forms.Widget, 'format_value'): + def format_value(self, value): + return self._format_value(value) + + +class Input(Widget): + template_name = 'floppyforms/input.html' + input_type = None + datalist = None + + def __init__(self, *args, **kwargs): + datalist = kwargs.pop('datalist', None) + if datalist is not None: + self.datalist = datalist + template_name = kwargs.pop('template_name', None) + if template_name is not None: + self.template_name = template_name + super(Input, self).__init__(*args, **kwargs) + self.context_instance = None + + def get_context_data(self): + return {} + + def format_value(self, value): + if self.is_localized: +~~ value = formats.localize_input(value) + return force_str(value) + + def get_context(self, name, value, attrs=None): + context = { + 'widget': self, + 'type': self.input_type, + 'name': name, + 'hidden': self.is_hidden, + 'required': self.is_required, + 'True': True, + } + + if self.is_hidden: + context['hidden'] = True + + if value is None: + value = '' + + if value != '': + context['value'] = self.format_value(value) + + context.update(self.get_context_data()) + context['attrs'] = self.build_attrs(attrs) + + + +## ... source file abbreviated to get to formats examples ... + + + default_attrs.update(attrs) + super(Textarea, self).__init__(default_attrs) + + def format_value(self, value): + return conditional_escape(force_str(value)) + + +class DateInput(Input): + template_name = 'floppyforms/date.html' + input_type = 'date' + supports_microseconds = False + + def __init__(self, attrs=None, format=None): + super(DateInput, self).__init__(attrs) + self.format = '%Y-%m-%d' + + def format_value(self, value): + if hasattr(value, 'strftime'): + value = datetime_safe.new_date(value) + return value.strftime(self.format) + return value + + if django.VERSION < (1, 6): + def _has_changed(self, initial, data): + try: +~~ input_format = formats.get_format('DATE_INPUT_FORMATS')[0] + initial = datetime.datetime.strptime(initial, input_format).date() + except (TypeError, ValueError): + pass + return super(DateInput, self)._has_changed( + self._format_value(initial), data + ) + + +class DateTimeInput(Input): + template_name = 'floppyforms/datetime.html' + input_type = 'datetime' + supports_microseconds = False + + def __init__(self, attrs=None, format=None): + super(DateTimeInput, self).__init__(attrs) + if format: + self.format = format + self.manual_format = True + else: +~~ self.format = formats.get_format('DATETIME_INPUT_FORMATS')[0] + self.manual_format = False + + def format_value(self, value): + if hasattr(value, 'strftime'): + value = datetime_safe.new_datetime(value) + return value.strftime(self.format) + return value + + if django.VERSION < (1, 6): + def _has_changed(self, initial, data): + try: +~~ input_format = formats.get_format('DATETIME_INPUT_FORMATS')[0] + initial = datetime.datetime.strptime(initial, input_format) + except (TypeError, ValueError): + pass + return super(DateTimeInput, self)._has_changed( + self._format_value(initial), data + ) + + +class TimeInput(Input): + template_name = 'floppyforms/time.html' + input_type = 'time' + supports_microseconds = False + + def __init__(self, attrs=None, format=None): + super(TimeInput, self).__init__(attrs) + if format: + self.format = format + self.manual_format = True + else: +~~ self.format = formats.get_format('TIME_INPUT_FORMATS')[0] + self.manual_format = False + + def format_value(self, value): + if hasattr(value, 'strftime'): + return value.strftime(self.format) + return value + + if django.VERSION < (1, 6): + def _has_changed(self, initial, data): + try: +~~ input_format = formats.get_format('TIME_INPUT_FORMATS')[0] + initial = datetime.datetime.strptime(initial, input_format).time() + except (TypeError, ValueError): + pass + return super(TimeInput, self)._has_changed( + self._format_value(initial), data + ) + + +class SearchInput(Input): + template_name = 'floppyforms/search.html' + input_type = 'search' + + +class EmailInput(TextInput): + template_name = 'floppyforms/email.html' + input_type = 'email' + + +class URLInput(TextInput): + template_name = 'floppyforms/url.html' + input_type = 'url' + + +class ColorInput(Input): + + +## ... source file abbreviated to get to formats examples ... + + +class RadioSelect(Select): + template_name = 'floppyforms/radio.html' + + +class CheckboxSelectMultiple(SelectMultiple): + template_name = 'floppyforms/checkbox_select.html' + + +class MultiWidget(forms.MultiWidget): + @property + def is_hidden(self): + return all(w.is_hidden for w in self.widgets) + + def build_attrs(self, base_attrs, extra_attrs=None, **kwargs): + attrs = dict(self.attrs, **kwargs) + attrs.update(base_attrs) + if extra_attrs: + attrs.update(extra_attrs) + return attrs + + if django.VERSION < (1, 11): + def format_value(self, value): + if value == '' or value is None: + return None + if self.is_localized: +~~ return formats.localize_input(value) + return force_str(value) + + def get_context(self, name, value, attrs): + context = {} + context['widget'] = { + 'name': name, + 'is_hidden': self.is_hidden, + 'required': self.is_required, + 'value': self.format_value(value), + 'attrs': self.build_attrs(self.attrs, attrs), + 'template_name': self.template_name, + } + if self.is_localized: + for widget in self.widgets: + widget.is_localized = self.is_localized + if not isinstance(value, list): + value = self.decompress(value) + + final_attrs = context['widget']['attrs'] + input_type = final_attrs.pop('type', None) + id_ = final_attrs.get('id') + subwidgets = [] + for i, widget in enumerate(self.widgets): + if input_type is not None: + + +## ... source file abbreviated to get to formats examples ... + + + if value is None: + value = '' + + context.update(self.get_context_data()) + attrs.update(self.attrs) + + for key, value in attrs.items(): + if value is True: + attrs[key] = False + context['year_id'] = self.year_field % attrs['id'] + context['month_id'] = self.month_field % attrs['id'] + context['day_id'] = self.day_field % attrs['id'] + del attrs['id'] + + context['attrs'] = attrs + return context + + def render(self, name, value, attrs=None, extra_context={}, renderer=None): + try: + year_val, month_val, day_val = value.year, value.month, value.day + except AttributeError: + year_val = month_val = day_val = None + if isinstance(value, str): + if settings.USE_L10N: + try: +~~ input_format = formats.get_format( + 'DATE_INPUT_FORMATS' + )[0] + v = datetime.datetime.strptime(value, input_format) + year_val, month_val, day_val = v.year, v.month, v.day + except ValueError: + pass + else: + match = RE_DATE.match(value) + if match: + year_val, month_val, day_val = map(int, match.groups()) + + context = self.get_context(name, value, attrs=attrs, + extra_context=extra_context) + + context['year_choices'] = [(i, i) for i in self.years] + context['year_val'] = year_val + + context['month_choices'] = list(MONTHS.items()) + context['month_val'] = month_val + + context['day_choices'] = [(i, i) for i in range(1, 32)] + context['day_val'] = day_val + + + if self.required is False: + context['year_choices'].insert(0, self.none_value) + context['month_choices'].insert(0, self.none_value) + context['day_choices'].insert(0, self.none_value) + + return loader.render_to_string(self.template_name, context) + + def value_from_datadict(self, data, files, name): + y = data.get(self.year_field % name) + m = data.get(self.month_field % name) + d = data.get(self.day_field % name) + if y == m == d == "0": + return None + if y and m and d: + if settings.USE_L10N: +~~ input_format = formats.get_format('DATE_INPUT_FORMATS')[0] + try: + date_value = datetime.date(int(y), int(m), int(d)) + except ValueError: + return '%s-%s-%s' % (y, m, d) + else: + date_value = datetime_safe.new_date(date_value) + return date_value.strftime(input_format) + else: + return '%s-%s-%s' % (y, m, d) + return data.get(name, None) + + + +## ... source file continues with no further formats examples... + +``` + diff --git a/content/pages/examples/django/django-utils-functional-keep-lazy.markdown b/content/pages/examples/django/django-utils-functional-keep-lazy.markdown new file mode 100644 index 000000000..cf82dbe3e --- /dev/null +++ b/content/pages/examples/django/django-utils-functional-keep-lazy.markdown @@ -0,0 +1,72 @@ +title: django.utils.functional keep_lazy Example Code +category: page +slug: django-utils-functional-keep-lazy-examples +sortorder: 500011457 +toc: False +sidebartitle: django.utils.functional keep_lazy +meta: Python example code for the keep_lazy callable from the django.utils.functional module of the Django project. + + +keep_lazy is a callable within the django.utils.functional module of the Django project. + + +## Example 1 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / utils / compatibility.py**](https://github.com/divio/django-filer/blob/develop/filer/utils/compatibility.py) + +```python +# compatibility.py +from __future__ import absolute_import, unicode_literals + +import sys + +from django.utils import six +~~from django.utils.functional import keep_lazy +from django.utils.text import Truncator, format_lazy + + +def string_concat(*strings): + return format_lazy('{}' * len(strings), *strings) + + +def truncate_words(s, num, end_text='...'): + truncate = end_text and ' %s' % end_text or '' + return Truncator(s).words(num, truncate=truncate) + + +~~truncate_words = keep_lazy(truncate_words, six.text_type) + + +if not six.PY3: + fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() + + +def upath(path): + if six.PY2 and not isinstance(path, six.text_type): + return path.decode(fs_encoding) + return path + + +def get_delete_permission(opts): + from django.contrib.auth import get_permission_codename # noqa + return '%s.%s' % (opts.app_label, get_permission_codename('delete', opts)) + + +try: + from PIL import Image as PILImage # noqa + from PIL import ImageDraw as PILImageDraw # noqa + from PIL import ExifTags as PILExifTags # noqa +except ImportError: + try: + import Image as PILImage # noqa + + +## ... source file continues with no further keep_lazy examples... + +``` + diff --git a/content/pages/examples/django/django-utils-functional-lazy.markdown b/content/pages/examples/django/django-utils-functional-lazy.markdown new file mode 100644 index 000000000..4d92b9125 --- /dev/null +++ b/content/pages/examples/django/django-utils-functional-lazy.markdown @@ -0,0 +1,198 @@ +title: django.utils.functional lazy Example Code +category: page +slug: django-utils-functional-lazy-examples +sortorder: 500011458 +toc: False +sidebartitle: django.utils.functional lazy +meta: Python example code for the lazy callable from the django.utils.functional module of the Django project. + + +lazy is a callable within the django.utils.functional module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / context_processors.py**](https://github.com/divio/django-cms/blob/develop/cms/./context_processors.py) + +```python +# context_processors.py +try: + from functools import lru_cache +except ImportError: + from django.utils.lru_cache import lru_cache + +~~from django.utils.functional import lazy + +from cms.utils.conf import get_cms_setting +from cms.utils.page import get_page_template_from_request + + +def cms_settings(request): + from menus.menu_pool import MenuRenderer + + @lru_cache(maxsize=None) + def _get_menu_renderer(): + from menus.menu_pool import menu_pool + return menu_pool.get_renderer(request) + +~~ _get_menu_renderer = lazy(_get_menu_renderer, MenuRenderer) + + return { + 'cms_menu_renderer': _get_menu_renderer(), + 'CMS_MEDIA_URL': get_cms_setting('MEDIA_URL'), + 'CMS_TEMPLATE': lambda: get_page_template_from_request(request), + } + + + +## ... source file continues with no further lazy examples... + +``` + + +## Example 2 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / reverse.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./reverse.py) + +```python +# reverse.py +from django.urls import NoReverseMatch +from django.urls import reverse as django_reverse +~~from django.utils.functional import lazy + +from rest_framework.settings import api_settings +from rest_framework.utils.urls import replace_query_param + + +def preserve_builtin_query_params(url, request=None): + if request is None: + return url + + overrides = [ + api_settings.URL_FORMAT_OVERRIDE, + ] + + for param in overrides: + if param and (param in request.GET): + value = request.GET[param] + url = replace_query_param(url, param, value) + + return url + + +def reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra): + scheme = getattr(request, 'versioning_scheme', None) + if scheme is not None: + try: + url = scheme.reverse(viewname, args, kwargs, request, format, **extra) + except NoReverseMatch: + url = _reverse(viewname, args, kwargs, request, format, **extra) + else: + url = _reverse(viewname, args, kwargs, request, format, **extra) + + return preserve_builtin_query_params(url, request) + + +def _reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra): + if format is not None: + kwargs = kwargs or {} + kwargs['format'] = format + url = django_reverse(viewname, args=args, kwargs=kwargs, **extra) + if request: + return request.build_absolute_uri(url) + return url + + +~~reverse_lazy = lazy(reverse, str) + + + +## ... source file continues with no further lazy examples... + +``` + + +## Example 3 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / models / __init__.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/models/__init__.py) + +```python +# __init__.py +from django import shortcuts +from django import urls +from django.urls import base +~~from django.utils.functional import lazy + +from .article import * # noqa +from .pluginbase import * # noqa +from .urlpath import * # noqa + +original_django_reverse = urls.reverse + + +def reverse(*args, **kwargs): + if isinstance(args[0], str) and args[0].startswith("wiki:"): + url_kwargs = kwargs.get("kwargs", {}) + path = url_kwargs.get("path", False) + if path is not False: + url_kwargs.pop("article_id", None) + url_kwargs["path"] = path + kwargs["kwargs"] = url_kwargs + + url = original_django_reverse(*args, **kwargs) + if hasattr(reverse, "_transform_url"): + url = reverse._transform_url(url) + else: + url = original_django_reverse(*args, **kwargs) + + return url + + +~~reverse_lazy = lazy(reverse, str) + + +base.reverse = reverse +base.reverse_lazy = reverse_lazy +urls.reverse = reverse +urls.reverse_lazy = reverse_lazy +shortcuts.reverse = reverse + + + +## ... source file continues with no further lazy examples... + +``` + diff --git a/content/pages/examples/django/django-utils-functional-lazyobject.markdown b/content/pages/examples/django/django-utils-functional-lazyobject.markdown new file mode 100644 index 000000000..4d3d89471 --- /dev/null +++ b/content/pages/examples/django/django-utils-functional-lazyobject.markdown @@ -0,0 +1,266 @@ +title: django.utils.functional LazyObject Example Code +category: page +slug: django-utils-functional-lazyobject-examples +sortorder: 500011454 +toc: False +sidebartitle: django.utils.functional LazyObject +meta: Python example code for the LazyObject class from the django.utils.functional module of the Django project. + + +LazyObject is a class within the django.utils.functional module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / utils / __init__.py**](https://github.com/divio/django-cms/blob/develop/cms/utils/__init__.py) + +```python +# __init__.py +from django.conf import settings +from django.core.files.storage import get_storage_class +~~from django.utils.functional import LazyObject + +from cms.utils.conf import get_site_id # nopyflakes +from cms.utils.i18n import get_default_language +from cms.utils.i18n import get_language_list +from cms.utils.i18n import get_language_code + + +def get_current_site(): + from django.contrib.sites.models import Site + + return Site.objects.get_current() + + +def get_language_from_request(request, current_page=None): + language = None + if hasattr(request, 'POST'): + language = request.POST.get('language', None) + if hasattr(request, 'GET') and not language: + language = request.GET.get('language', None) + site_id = current_page.node.site_id if current_page else None + if language: + language = get_language_code(language) + if not language in get_language_list(site_id): + language = None + if not language: + language = get_language_code(getattr(request, 'LANGUAGE_CODE', None)) + if language: + if not language in get_language_list(site_id): + language = None + + if not language and current_page: + languages = current_page.get_languages() + + if len(languages) > 0: + language = languages[0] + + if not language: + language = get_default_language(site_id=site_id) + + return language + +default_storage = 'django.contrib.staticfiles.storage.StaticFilesStorage' + + +~~class ConfiguredStorage(LazyObject): + def _setup(self): + self._wrapped = get_storage_class(getattr(settings, 'STATICFILES_STORAGE', default_storage))() + +configured_storage = ConfiguredStorage() + + + +## ... source file continues with no further LazyObject examples... + +``` + + +## Example 2 from django-debug-toolbar +[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar) +([project documentation](https://github.com/jazzband/django-debug-toolbar) +and [PyPI page](https://pypi.org/project/django-debug-toolbar/)) +grants a developer detailed request-response cycle information while +developing a [Django](/django.html) web application. +The code for django-debug-toolbar is +[open source](https://github.com/jazzband/django-debug-toolbar/blob/master/LICENSE) +and maintained by the developer community group known as +[Jazzband](https://jazzband.co/). + +[**django-debug-toolbar / debug_toolbar / panels / staticfiles.py**](https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/panels/staticfiles.py) + +```python +# staticfiles.py +from collections import OrderedDict +from os.path import join, normpath + +from django.conf import settings +from django.contrib.staticfiles import finders, storage +from django.core.files.storage import get_storage_class +~~from django.utils.functional import LazyObject +from django.utils.translation import gettext_lazy as _, ngettext as __ + +from debug_toolbar import panels +from debug_toolbar.utils import ThreadCollector + +try: + import threading +except ImportError: + threading = None + + +class StaticFile: + + def __init__(self, path): + self.path = path + + def __str__(self): + return self.path + + def real_path(self): + return finders.find(self.path) + + def url(self): + return storage.staticfiles_storage.url(self.path) + + +class FileCollector(ThreadCollector): + def collect(self, path, thread=None): + if path.endswith("/"): + return + super().collect(StaticFile(path), thread) + + +collector = FileCollector() + + +~~class DebugConfiguredStorage(LazyObject): + + def _setup(self): + + configured_storage_cls = get_storage_class(settings.STATICFILES_STORAGE) + + class DebugStaticFilesStorage(configured_storage_cls): + def __init__(self, collector, *args, **kwargs): + super().__init__(*args, **kwargs) + self.collector = collector + + def url(self, path): + self.collector.collect(path) + return super().url(path) + + self._wrapped = DebugStaticFilesStorage(collector) + + +_original_storage = storage.staticfiles_storage + + +class StaticFilesPanel(panels.Panel): + + name = "Static files" + template = "debug_toolbar/panels/staticfiles.html" + + +## ... source file continues with no further LazyObject examples... + +``` + + +## Example 3 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / sites.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./sites.py) + +```python +# sites.py +from django.apps import apps +from django.urls import include +from django.urls import re_path +~~from django.utils.functional import LazyObject +from django.utils.module_loading import import_string +from wiki.conf import settings +from wiki.core.plugins import registry + + +class WikiSite: + + def __init__(self, name="wiki"): + from wiki.views import accounts, article, deleted_list + + self.name = name + + self.root_view = getattr(self, "root_view", article.CreateRootView.as_view()) + self.root_missing_view = getattr( + self, "root_missing_view", article.MissingRootView.as_view() + ) + + self.article_view = getattr(self, "article_view", article.ArticleView.as_view()) + self.article_create_view = getattr( + self, "article_create_view", article.Create.as_view() + ) + self.article_delete_view = getattr( + self, "article_delete_view", article.Delete.as_view() + ) + + +## ... source file abbreviated to get to LazyObject examples ... + + + return urlpatterns + + def get_plugin_urls(self): + urlpatterns = [] + for plugin in registry.get_plugins().values(): + slug = getattr(plugin, "slug", None) + if slug: + article_urlpatterns = plugin.urlpatterns.get("article", []) + urlpatterns += [ + re_path( + r"^(?P[0-9]+)/plugin/" + slug + "/", + include(article_urlpatterns), + ), + re_path( + r"^(?P.+/|)_plugin/" + slug + "/", + include(article_urlpatterns), + ), + ] + root_urlpatterns = plugin.urlpatterns.get("root", []) + urlpatterns += [ + re_path(r"^_plugin/" + slug + "/", include(root_urlpatterns)), + ] + return urlpatterns + + +~~class DefaultWikiSite(LazyObject): + def _setup(self): + WikiSiteClass = import_string(apps.get_app_config("wiki").default_site) + self._wrapped = WikiSiteClass() + + +site = DefaultWikiSite() + + + +## ... source file continues with no further LazyObject examples... + +``` + diff --git a/content/pages/examples/django/django-utils-functional-promise.markdown b/content/pages/examples/django/django-utils-functional-promise.markdown new file mode 100644 index 000000000..12ec1be58 --- /dev/null +++ b/content/pages/examples/django/django-utils-functional-promise.markdown @@ -0,0 +1,335 @@ +title: django.utils.functional Promise Example Code +category: page +slug: django-utils-functional-promise-examples +sortorder: 500011455 +toc: False +sidebartitle: django.utils.functional Promise +meta: Python example code for the Promise class from the django.utils.functional module of the Django project. + + +Promise is a class within the django.utils.functional module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / toolbar / items.py**](https://github.com/divio/django-cms/blob/develop/cms/toolbar/items.py) + +```python +# items.py +import json +from abc import ABCMeta +from collections import defaultdict + +from django.template.loader import render_to_string +from django.utils.encoding import force_text +~~from django.utils.functional import Promise + +from six import with_metaclass + +from cms.constants import RIGHT, LEFT, REFRESH_PAGE, URL_CHANGE + + +class ItemSearchResult(object): + def __init__(self, item, index): + self.item = item + self.index = index + + def __add__(self, other): + return ItemSearchResult(self.item, self.index + other) + + def __sub__(self, other): + return ItemSearchResult(self.item, self.index - other) + + def __int__(self): + return self.index + + +def may_be_lazy(thing): +~~ if isinstance(thing, Promise): + return thing._proxy____args[0] + else: + return thing + + +class ToolbarAPIMixin(with_metaclass(ABCMeta)): + REFRESH_PAGE = REFRESH_PAGE + URL_CHANGE = URL_CHANGE + LEFT = LEFT + RIGHT = RIGHT + + def __init__(self): + self.items = [] + self.menus = {} + self._memo = defaultdict(list) + + def _memoize(self, item): + self._memo[item.__class__].append(item) + + def _unmemoize(self, item): + self._memo[item.__class__].remove(item) + + def _item_position(self, item): + return self.items.index(item) + + +## ... source file continues with no further Promise examples... + +``` + + +## Example 2 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / utils.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./utils.py) + +```python +# utils.py +import json +from django.template import Context +from django.utils import translation +from jet import settings +from jet.models import PinnedApplication + +try: + from django.apps.registry import apps +except ImportError: + try: + from django.apps import apps # Fix Django 1.7 import issue + except ImportError: + pass +from django.core.serializers.json import DjangoJSONEncoder +from django.http import HttpResponse +try: + from django.core.urlresolvers import reverse, resolve, NoReverseMatch +except ImportError: # Django 1.11 + from django.urls import reverse, resolve, NoReverseMatch + +from django.contrib.admin import AdminSite +from django.utils.encoding import smart_text +from django.utils.text import capfirst +from django.contrib import messages +from django.utils.encoding import force_text +~~from django.utils.functional import Promise +from django.contrib.admin.options import IncorrectLookupParameters +from django.contrib import admin +from django.utils.translation import ugettext_lazy as _ +from django.utils.text import slugify + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # Python 2.6 + + +class JsonResponse(HttpResponse): + + def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs): + if safe and not isinstance(data, dict): + raise TypeError('In order to allow non-dict objects to be ' + 'serialized set the safe parameter to False') + kwargs.setdefault('content_type', 'application/json') + data = json.dumps(data, cls=encoder) + super(JsonResponse, self).__init__(content=data, **kwargs) + + +def get_app_list(context, order=True): + admin_site = get_admin_site(context) + + +## ... source file abbreviated to get to Promise examples ... + + +def get_admin_site(context): + try: + current_resolver = resolve(context.get('request').path) + index_resolver = resolve(reverse('%s:index' % current_resolver.namespaces[0])) + + if hasattr(index_resolver.func, 'admin_site'): + return index_resolver.func.admin_site + + for func_closure in index_resolver.func.__closure__: + if isinstance(func_closure.cell_contents, AdminSite): + return func_closure.cell_contents + except: + pass + + return admin.site + + +def get_admin_site_name(context): + return get_admin_site(context).name + + +class LazyDateTimeEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date): + return obj.isoformat() +~~ elif isinstance(obj, Promise): + return force_text(obj) + return self.encode(obj) + + +def get_model_instance_label(instance): + if getattr(instance, "related_label", None): + return instance.related_label() + return smart_text(instance) + + +class SuccessMessageMixin(object): + success_message = '' + + def form_valid(self, form): + response = super(SuccessMessageMixin, self).form_valid(form) + success_message = self.get_success_message(form.cleaned_data) + if success_message: + messages.success(self.request, success_message) + return response + + def get_success_message(self, cleaned_data): + return self.success_message % cleaned_data + + + + +## ... source file continues with no further Promise examples... + +``` + + +## Example 3 from django-jsonfield +[django-jsonfield](https://github.com/dmkoch/django-jsonfield) +([jsonfield on PyPi](https://pypi.org/project/jsonfield/)) is a +[Django](/django.html) code library that makes it easier to store validated +JSON in a [Django object-relational mapper (ORM)](/django-orm.html) database +model. + +The django-jsonfield project is open source under the +[MIT license](https://github.com/dmkoch/django-jsonfield/blob/master/LICENSE). + +[**django-jsonfield / src/jsonfield / encoder.py**](https://github.com/dmkoch/django-jsonfield/blob/master/src/jsonfield/./encoder.py) + +```python +# encoder.py +import datetime +import decimal +import json +import uuid + +from django.db.models.query import QuerySet +from django.utils import timezone +from django.utils.encoding import force_str +~~from django.utils.functional import Promise + + +class JSONEncoder(json.JSONEncoder): + def default(self, obj): # noqa: C901 +~~ if isinstance(obj, Promise): + return force_str(obj) + elif isinstance(obj, datetime.datetime): + representation = obj.isoformat() + if representation.endswith('+00:00'): + representation = representation[:-6] + 'Z' + return representation + elif isinstance(obj, datetime.date): + return obj.isoformat() + elif isinstance(obj, datetime.time): + if timezone and timezone.is_aware(obj): + raise ValueError("JSON can't represent timezone-aware times.") + representation = obj.isoformat() + return representation + elif isinstance(obj, datetime.timedelta): + return str(obj.total_seconds()) + elif isinstance(obj, decimal.Decimal): + return float(obj) + elif isinstance(obj, uuid.UUID): + return str(obj) + elif isinstance(obj, QuerySet): + return tuple(obj) + elif isinstance(obj, bytes): + return obj.decode() + elif hasattr(obj, 'tolist'): + + +## ... source file continues with no further Promise examples... + +``` + + +## Example 4 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / utils / encoders.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/utils/encoders.py) + +```python +# encoders.py +import datetime +import decimal +import json # noqa +import uuid + +from django.db.models.query import QuerySet +from django.utils import timezone +from django.utils.encoding import force_str +~~from django.utils.functional import Promise + +from rest_framework.compat import coreapi + + +class JSONEncoder(json.JSONEncoder): + def default(self, obj): +~~ if isinstance(obj, Promise): + return force_str(obj) + elif isinstance(obj, datetime.datetime): + representation = obj.isoformat() + if representation.endswith('+00:00'): + representation = representation[:-6] + 'Z' + return representation + elif isinstance(obj, datetime.date): + return obj.isoformat() + elif isinstance(obj, datetime.time): + if timezone and timezone.is_aware(obj): + raise ValueError("JSON can't represent timezone-aware times.") + representation = obj.isoformat() + return representation + elif isinstance(obj, datetime.timedelta): + return str(obj.total_seconds()) + elif isinstance(obj, decimal.Decimal): + return float(obj) + elif isinstance(obj, uuid.UUID): + return str(obj) + elif isinstance(obj, QuerySet): + return tuple(obj) + elif isinstance(obj, bytes): + return obj.decode() + elif hasattr(obj, 'tolist'): + + +## ... source file continues with no further Promise examples... + +``` + diff --git a/content/pages/examples/django/django-utils-functional-simplelazyobject.markdown b/content/pages/examples/django/django-utils-functional-simplelazyobject.markdown new file mode 100644 index 000000000..7bc37e79c --- /dev/null +++ b/content/pages/examples/django/django-utils-functional-simplelazyobject.markdown @@ -0,0 +1,98 @@ +title: django.utils.functional SimpleLazyObject Example Code +category: page +slug: django-utils-functional-simplelazyobject-examples +sortorder: 500011456 +toc: False +sidebartitle: django.utils.functional SimpleLazyObject +meta: Python example code for the SimpleLazyObject class from the django.utils.functional module of the Django project. + + +SimpleLazyObject is a class within the django.utils.functional module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / cms_menus.py**](https://github.com/divio/django-cms/blob/develop/cms/./cms_menus.py) + +```python +# cms_menus.py +from django.db.models.query import Prefetch, prefetch_related_objects +from django.urls import reverse +~~from django.utils.functional import SimpleLazyObject +from django.utils.translation import override as force_language + +from cms import constants +from cms.api import get_page_draft +from cms.apphook_pool import apphook_pool +from cms.models import EmptyTitle +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import ( + get_fallback_languages, + get_public_languages, + hide_untranslated, + is_valid_site_language, +) +from cms.utils.permissions import get_view_restrictions +from cms.utils.page import get_page_queryset +from cms.utils.page_permissions import user_can_view_all_pages + +from menus.base import Menu, NavigationNode, Modifier +from menus.menu_pool import menu_pool + + +def get_visible_nodes(request, pages, site): + user = request.user + _get_page_draft = get_page_draft + public_for = get_cms_setting('PUBLIC_FOR') + can_see_unrestricted = public_for == 'all' or (public_for == 'staff' and user.is_staff) + + if not user.is_authenticated and not can_see_unrestricted: + return [] + + if user_can_view_all_pages(user, site): + return list(pages) + + draft_pages = [_get_page_draft(page) for page in pages] + restricted_pages = get_view_restrictions(draft_pages) + + if not restricted_pages: + return list(pages) if can_see_unrestricted else [] + + user_id = user.pk +~~ user_groups = SimpleLazyObject(lambda: frozenset(user.groups.values_list('pk', flat=True))) + is_auth_user = user.is_authenticated + + def user_can_see_page(page): + page_id = page.pk if page.publisher_is_draft else page.publisher_public_id + page_permissions = restricted_pages.get(page_id, []) + + if not page_permissions: + return can_see_unrestricted + + if not is_auth_user: + return False + + for perm in page_permissions: + if perm.user_id == user_id or perm.group_id in user_groups: + return True + return False + return [page for page in pages if user_can_see_page(page)] + + +def get_menu_node_for_page(renderer, page, language, fallbacks=None): + if fallbacks is None: + fallbacks = [] + + attr = { + + +## ... source file continues with no further SimpleLazyObject examples... + +``` + diff --git a/content/pages/examples/django/django-utils-functional-total-ordering.markdown b/content/pages/examples/django/django-utils-functional-total-ordering.markdown new file mode 100644 index 000000000..de5323a43 --- /dev/null +++ b/content/pages/examples/django/django-utils-functional-total-ordering.markdown @@ -0,0 +1,65 @@ +title: django.utils.functional total_ordering Example Code +category: page +slug: django-utils-functional-total-ordering-examples +sortorder: 500011459 +toc: False +sidebartitle: django.utils.functional total_ordering +meta: Python example code for the total_ordering callable from the django.utils.functional module of the Django project. + + +total_ordering is a callable within the django.utils.functional module of the Django project. + + +## Example 1 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / admin / search.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/admin/search.py) + +```python +# search.py +from django.forms import Media, MediaDefiningClass +from django.forms.utils import flatatt +from django.template.loader import render_to_string +~~from django.utils.functional import cached_property, total_ordering +from django.utils.safestring import mark_safe +from django.utils.text import slugify + +from wagtail.admin.forms.search import SearchForm +from wagtail.core import hooks + + +~~@total_ordering +class SearchArea(metaclass=MediaDefiningClass): + template = 'wagtailadmin/shared/search_area.html' + + def __init__(self, label, url, name=None, classnames='', attrs=None, order=1000): + self.label = label + self.url = url + self.classnames = classnames + self.name = (name or slugify(str(label))) + self.order = order + + if attrs: + self.attr_string = flatatt(attrs) + else: + self.attr_string = "" + + def __lt__(self, other): + return (self.order, self.label) < (other.order, other.label) + + def __eq__(self, other): + return (self.order, self.label) == (other.order, other.label) + + def is_shown(self, request): + return True + + + +## ... source file continues with no further total_ordering examples... + +``` + diff --git a/content/pages/examples/django/django-utils-functional-wraps.markdown b/content/pages/examples/django/django-utils-functional-wraps.markdown new file mode 100644 index 000000000..81fb60b74 --- /dev/null +++ b/content/pages/examples/django/django-utils-functional-wraps.markdown @@ -0,0 +1,206 @@ +title: django.utils.functional wraps Example Code +category: page +slug: django-utils-functional-wraps-examples +sortorder: 500011460 +toc: False +sidebartitle: django.utils.functional wraps +meta: Python example code for the wraps callable from the django.utils.functional module of the Django project. + + +wraps is a callable within the django.utils.functional module of the Django project. + + +## Example 1 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / decorators.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./decorators.py) + +```python +# decorators.py +from django.apps import apps +from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.db.models import Model +from django.db.models.base import ModelBase +from django.db.models.query import QuerySet +from django.shortcuts import get_object_or_404 +~~from django.utils.functional import wraps +from guardian.exceptions import GuardianError +from guardian.utils import get_40x_or_None + + +def permission_required(perm, lookup_variables=None, **kwargs): + login_url = kwargs.pop('login_url', settings.LOGIN_URL) + redirect_field_name = kwargs.pop( + 'redirect_field_name', REDIRECT_FIELD_NAME) + return_403 = kwargs.pop('return_403', False) + return_404 = kwargs.pop('return_404', False) + accept_global_perms = kwargs.pop('accept_global_perms', False) + + if not isinstance(perm, str): + raise GuardianError("First argument must be in format: " + "'app_label.codename or a callable which return similar string'") + + def decorator(view_func): + def _wrapped_view(request, *args, **kwargs): + obj = None + if lookup_variables: + model, lookups = lookup_variables[0], lookup_variables[1:] + if isinstance(model, str): + splitted = model.split('.') + if len(splitted) != 2: + + +## ... source file abbreviated to get to wraps examples ... + + + "string it needs format: 'app_label.ModelClass'") + model = apps.get_model(*splitted) + elif issubclass(model.__class__, (Model, ModelBase, QuerySet)): + pass + else: + raise GuardianError("First lookup argument must always be " + "a model, string pointing at app/model or queryset. " + "Given: %s (type: %s)" % (model, type(model))) + if len(lookups) % 2 != 0: + raise GuardianError("Lookup variables must be provided " + "as pairs of lookup_string and view_arg") + lookup_dict = {} + for lookup, view_arg in zip(lookups[::2], lookups[1::2]): + if view_arg not in kwargs: + raise GuardianError("Argument %s was not passed " + "into view function" % view_arg) + lookup_dict[lookup] = kwargs[view_arg] + obj = get_object_or_404(model, **lookup_dict) + + response = get_40x_or_None(request, perms=[perm], obj=obj, + login_url=login_url, redirect_field_name=redirect_field_name, + return_403=return_403, return_404=return_404, accept_global_perms=accept_global_perms) + if response: + return response + return view_func(request, *args, **kwargs) +~~ return wraps(view_func)(_wrapped_view) + return decorator + + +def permission_required_or_403(perm, *args, **kwargs): + kwargs['return_403'] = True + return permission_required(perm, *args, **kwargs) + + +def permission_required_or_404(perm, *args, **kwargs): + kwargs['return_404'] = True + return permission_required(perm, *args, **kwargs) + + + +## ... source file continues with no further wraps examples... + +``` + + +## Example 2 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / utils.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./utils.py) + +```python +# utils.py +from django.conf import settings +~~from django.utils.functional import wraps +from django.utils.module_loading import import_string + + +def _parse_tags(tagstring): + if not tagstring: + return [] + + if "," not in tagstring and '"' not in tagstring: + words = list(set(split_strip(tagstring, " "))) + words.sort() + return words + + words = [] + buffer = [] + to_be_split = [] + saw_loose_comma = False + open_quote = False + i = iter(tagstring) + try: + while True: + c = next(i) + if c == '"': + if buffer: + to_be_split.append("".join(buffer)) + + +## ... source file abbreviated to get to wraps examples ... + + + words = list(set(words)) + words.sort() + return words + + +def split_strip(string, delimiter=","): + if not string: + return [] + + words = [w.strip() for w in string.split(delimiter)] + return [w for w in words if w] + + +def _edit_string_for_tags(tags): + names = [] + for tag in tags: + name = tag.name + if "," in name or " " in name: + names.append('"%s"' % name) + else: + names.append(name) + return ", ".join(sorted(names)) + + +def require_instance_manager(func): +~~ @wraps(func) + def inner(self, *args, **kwargs): + if self.instance is None: + raise TypeError("Can't call %s with a non-instance manager" % func.__name__) + return func(self, *args, **kwargs) + + return inner + + +def get_func(key, default): + func_path = getattr(settings, key, None) + return default if func_path is None else import_string(func_path) + + +def parse_tags(tagstring): + func = get_func("TAGGIT_TAGS_FROM_STRING", _parse_tags) + return func(tagstring) + + +def edit_string_for_tags(tags): + func = get_func("TAGGIT_STRING_FROM_TAGS", _edit_string_for_tags) + return func(tags) + + + +## ... source file continues with no further wraps examples... + +``` + diff --git a/content/pages/examples/django/django-utils-html-conditional-escape.markdown b/content/pages/examples/django/django-utils-html-conditional-escape.markdown new file mode 100644 index 000000000..afad2150a --- /dev/null +++ b/content/pages/examples/django/django-utils-html-conditional-escape.markdown @@ -0,0 +1,207 @@ +title: django.utils.html conditional_escape Example Code +category: page +slug: django-utils-html-conditional-escape-examples +sortorder: 500011461 +toc: False +sidebartitle: django.utils.html conditional_escape +meta: Python example code for the conditional_escape callable from the django.utils.html module of the Django project. + + +conditional_escape is a callable within the django.utils.html module of the Django project. + + +## Example 1 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / widgets.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./widgets.py) + +```python +# widgets.py +import datetime +import re +from itertools import chain + +import django +from django import forms +from django.conf import settings +from django.forms.widgets import FILE_INPUT_CONTRADICTION +from django.template import loader +from django.utils import datetime_safe, formats +from django.utils.dates import MONTHS +from django.utils.encoding import force_str +~~from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + +from .compat import MULTIVALUE_DICT_TYPES, flatten_contexts + + +from django.forms.utils import to_current_timezone + + +RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$') + + +__all__ = ( + 'TextInput', 'PasswordInput', 'HiddenInput', 'ClearableFileInput', + 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', + 'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple', + 'RadioSelect', 'CheckboxSelectMultiple', 'SearchInput', 'RangeInput', + 'ColorInput', 'EmailInput', 'URLInput', 'PhoneNumberInput', 'NumberInput', + 'IPAddressInput', 'MultiWidget', 'Widget', 'SplitDateTimeWidget', + 'SplitHiddenDateTimeWidget', 'MultipleHiddenInput', 'SelectDateWidget', + 'SlugInput', +) + + + + +## ... source file abbreviated to get to conditional_escape examples ... + + + data, files, self.clear_checkbox_name(name) + ): + if upload: + return FILE_INPUT_CONTRADICTION + return False + return upload + + def format_value(self, value): + if not value: + return None + return value + + +class Textarea(Input): + template_name = 'floppyforms/textarea.html' + rows = 10 + cols = 40 + + def __init__(self, attrs=None): + default_attrs = {'cols': self.cols, 'rows': self.rows} + if attrs: + default_attrs.update(attrs) + super(Textarea, self).__init__(default_attrs) + + def format_value(self, value): +~~ return conditional_escape(force_str(value)) + + +class DateInput(Input): + template_name = 'floppyforms/date.html' + input_type = 'date' + supports_microseconds = False + + def __init__(self, attrs=None, format=None): + super(DateInput, self).__init__(attrs) + self.format = '%Y-%m-%d' + + def format_value(self, value): + if hasattr(value, 'strftime'): + value = datetime_safe.new_date(value) + return value.strftime(self.format) + return value + + if django.VERSION < (1, 6): + def _has_changed(self, initial, data): + try: + input_format = formats.get_format('DATE_INPUT_FORMATS')[0] + initial = datetime.datetime.strptime(initial, input_format).date() + except (TypeError, ValueError): + pass + + +## ... source file continues with no further conditional_escape examples... + +``` + + +## Example 2 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / columns / manytomanycolumn.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/columns/manytomanycolumn.py) + +```python +# manytomanycolumn.py +from django.db import models +from django.utils.encoding import force_str +~~from django.utils.html import conditional_escape, mark_safe + +from .base import Column, LinkTransform, library + + +@library.register +class ManyToManyColumn(Column): + + def __init__( + self, transform=None, filter=None, separator=", ", linkify_item=None, *args, **kwargs + ): + kwargs.setdefault("orderable", False) + super().__init__(*args, **kwargs) + + if transform is not None: + self.transform = transform + if filter is not None: + self.filter = filter + self.separator = separator + + link_kwargs = None + if callable(linkify_item): + link_kwargs = dict(url=linkify_item) + elif isinstance(linkify_item, (dict, tuple)): + link_kwargs = dict(reverse_args=linkify_item) + elif linkify_item is True: + link_kwargs = dict() + + if link_kwargs is not None: + self.linkify_item = LinkTransform(attrs=self.attrs.get("a", {}), **link_kwargs) + + def transform(self, obj): + return force_str(obj) + + def filter(self, qs): + return qs.all() + + def render(self, value): + if not value.exists(): + return self.default + + items = [] + for item in self.filter(value): +~~ content = conditional_escape(self.transform(item)) + if hasattr(self, "linkify_item"): + content = self.linkify_item(content=content, record=item) + + items.append(content) + + return mark_safe(conditional_escape(self.separator).join(items)) + + @classmethod + def from_field(cls, field, **kwargs): + if isinstance(field, models.ManyToManyField): + return cls(**kwargs) + + + +## ... source file continues with no further conditional_escape examples... + +``` + diff --git a/content/pages/examples/django/django-utils-html-escape.markdown b/content/pages/examples/django/django-utils-html-escape.markdown new file mode 100644 index 000000000..5dfc6dac2 --- /dev/null +++ b/content/pages/examples/django/django-utils-html-escape.markdown @@ -0,0 +1,829 @@ +title: django.utils.html escape Example Code +category: page +slug: django-utils-html-escape-examples +sortorder: 500011462 +toc: False +sidebartitle: django.utils.html escape +meta: Python example code for the escape callable from the django.utils.html module of the Django project. + + +escape is a callable within the django.utils.html module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / forms / angular_base.py**](https://github.com/jrief/django-angular/blob/master/djng/forms/angular_base.py) + +```python +# angular_base.py +from base64 import b64encode +from collections import UserList +import json +import warnings + +from django.forms import forms +from django.http import QueryDict +~~from django.utils.html import format_html, format_html_join, escape, conditional_escape +from django.utils.encoding import force_text +from django.utils.module_loading import import_string +from django.utils.safestring import mark_safe, SafeText, SafeData +from django.core.exceptions import ValidationError, ImproperlyConfigured + +from .fields import DefaultFieldMixin + + +class SafeTuple(SafeData, tuple): + + +class TupleErrorList(UserList, list): + def __init__(self, initlist=None, error_class=None): + super(TupleErrorList, self).__init__(initlist) + + if error_class is None: + self.error_class = 'errorlist' + else: + self.error_class = 'errorlist {}'.format(error_class) + + def as_data(self): + return ValidationError(self.data).error_list + + def get_json_data(self, escape_html=False): + errors = [] + for error in self.as_data(): + message = list(error)[0] + errors.append({ +~~ 'message': escape(message) if escape_html else message, + 'code': error.code or '', + }) + return errors + + def as_json(self, escape_html=False): + return json.dumps(self.get_json_data(escape_html)) + + def extend(self, iterable): + for item in iterable: + if not isinstance(item, str): + self.append(item) + return None + + def as_ul(self): + if not self: + return SafeText() + first = self[0] + if isinstance(first, tuple): + error_lists = {'$pristine': [], '$dirty': []} + for e in self: + if e[5] == '$message': + li_format = '
  • ' + else: + li_format = '
  • {3}
  • ' + + +## ... source file continues with no further escape examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / templatetags / cms_tags.py**](https://github.com/divio/django-cms/blob/develop/cms/templatetags/cms_tags.py) + +```python +# cms_tags.py +from collections import namedtuple, OrderedDict +from copy import copy +from datetime import datetime + +from django import template +from django.conf import settings +from django.contrib.sites.models import Site +from django.core.mail import mail_managers +from django.db.models import Model +from django.middleware.common import BrokenLinkEmailsMiddleware +from django.template.loader import render_to_string +from django.urls import reverse +from django.utils.encoding import force_text, smart_text +~~from django.utils.html import escape +from django.utils.http import urlencode +from django.utils.translation import ( + get_language, + override as force_language, + ugettext_lazy as _, +) + +from six import string_types, integer_types + +from classytags.arguments import (Argument, MultiValueArgument, + MultiKeywordArgument) +from classytags.core import Options, Tag +from classytags.helpers import InclusionTag, AsTag +from classytags.parser import Parser +from classytags.utils import flatten_context +from classytags.values import ListValue, StringValue + +from cms.cache.page import get_page_url_cache, set_page_url_cache +from cms.exceptions import PlaceholderNotFound +from cms.models import Page, Placeholder as PlaceholderModel, CMSPlugin, StaticPlaceholder +from cms.plugin_pool import plugin_pool +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils import get_current_site, get_language_from_request, get_site_id +from cms.utils.compat.dj import get_middleware + + +## ... source file abbreviated to get to escape examples ... + + + 'as', + Argument('varname', required=False, resolve=False) + ) + + valid_attributes = [ + "title", + "slug", + "meta_description", + "page_title", + "menu_title", + "changed_date", + "changed_by", + ] + + def get_value(self, context, name, page_lookup): + if not 'request' in context: + return '' + name = name.lower() + request = context['request'] + lang = get_language_from_request(request) + page = _get_page_by_untyped_arg(page_lookup, request, get_site_id(None)) + if page and name in self.valid_attributes: + func = getattr(page, "get_%s" % name) + ret_val = func(language=lang, fallback=True) + if not isinstance(ret_val, datetime): +~~ ret_val = escape(ret_val) + return ret_val + return '' + + +class CMSToolbar(RenderBlock): + name = 'cms_toolbar' + + options = Options( + Argument('name', required=False), # just here so sekizai thinks this is a RenderBlock + parser_class=SekizaiParser, + ) + + def render_tag(self, context, name, nodelist): + request = context.get('request') + + if not request: + return nodelist.render(context) + + toolbar = get_toolbar_from_request(request) + + if toolbar and toolbar.show_toolbar: + toolbar.init_toolbar(request) + return toolbar.render_with_structure(context, nodelist) + return nodelist.render(context) + + +## ... source file continues with no further escape examples... + +``` + + +## Example 3 from django-debug-toolbar +[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar) +([project documentation](https://github.com/jazzband/django-debug-toolbar) +and [PyPI page](https://pypi.org/project/django-debug-toolbar/)) +grants a developer detailed request-response cycle information while +developing a [Django](/django.html) web application. +The code for django-debug-toolbar is +[open source](https://github.com/jazzband/django-debug-toolbar/blob/master/LICENSE) +and maintained by the developer community group known as +[Jazzband](https://jazzband.co/). + +[**django-debug-toolbar / debug_toolbar / views.py**](https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/./views.py) + +```python +# views.py +from django.http import JsonResponse +~~from django.utils.html import escape +from django.utils.translation import gettext as _ + +from debug_toolbar.decorators import require_show_toolbar +from debug_toolbar.toolbar import DebugToolbar + + +@require_show_toolbar +def render_panel(request): + toolbar = DebugToolbar.fetch(request.GET["store_id"]) + if toolbar is None: + content = _( + "Data for this panel isn't available anymore. " + "Please reload the page and retry." + ) +~~ content = "

    %s

    " % escape(content) + scripts = [] + else: + panel = toolbar.get_panel_by_id(request.GET["panel_id"]) + content = panel.content + scripts = panel.scripts + return JsonResponse({"content": content, "scripts": scripts}) + + + +## ... source file continues with no further escape examples... + +``` + + +## Example 4 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / folderadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/folderadmin.py) + +```python +# folderadmin.py +from __future__ import absolute_import, division, unicode_literals + +import itertools +import os +import re +from collections import OrderedDict + +from django import forms +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import messages +from django.contrib.admin import helpers +from django.contrib.admin.utils import capfirst, quote, unquote +from django.core.exceptions import PermissionDenied, ValidationError +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db import models, router +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils.encoding import force_text +~~from django.utils.html import escape +from django.utils.http import urlquote, urlunquote +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy, ungettext + +from .. import settings +from ..models import ( + File, Folder, FolderPermission, FolderRoot, ImagesWithMissingData, + UnsortedImages, tools, +) +from ..settings import FILER_IMAGE_MODEL, FILER_PAGINATE_BY +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import get_delete_permission +from ..utils.filer_easy_thumbnails import FilerActionThumbnailer +from ..utils.loader import load_model +from . import views +from .forms import CopyFilesAndFoldersForm, RenameFilesForm, ResizeImagesForm +from .patched.admin_utils import get_deleted_objects +from .permissions import PrimitivePermissionAwareModelAdmin +from .tools import ( + AdminContext, admin_url_params_encoded, check_files_edit_permissions, + check_files_read_permissions, check_folder_edit_permissions, + check_folder_read_permissions, popup_status, userperms_for_request, +) + + +## ... source file abbreviated to get to escape examples ... + + + + return render( + request, + "admin/filer/delete_selected_files_confirmation.html", + context + ) + + delete_files_or_folders.short_description = ugettext_lazy( + "Delete selected files and/or folders") + + def _format_callback(self, obj, user, admin_site, perms_needed): + has_admin = obj.__class__ in admin_site._registry + opts = obj._meta + if has_admin: + admin_url = reverse('%s:%s_%s_change' + % (admin_site.name, + opts.app_label, + opts.object_name.lower()), + None, (quote(obj._get_pk_val()),)) + p = get_delete_permission(opts) + if not user.has_perm(p): + perms_needed.add(opts.verbose_name) + return mark_safe('%s: %s' % + (escape(capfirst(opts.verbose_name)), + admin_url, +~~ escape(obj))) + else: + return '%s: %s' % (capfirst(opts.verbose_name), force_text(obj)) + + def _check_copy_perms(self, request, files_queryset, folders_queryset): + try: + check_files_read_permissions(request, files_queryset) + check_folder_read_permissions(request, folders_queryset) + except PermissionDenied: + return True + return False + + def _check_move_perms(self, request, files_queryset, folders_queryset): + try: + check_files_read_permissions(request, files_queryset) + check_folder_read_permissions(request, folders_queryset) + check_files_edit_permissions(request, files_queryset) + check_folder_edit_permissions(request, folders_queryset) + except PermissionDenied: + return True + return False + + def _get_current_action_folder(self, request, files_queryset, + folders_queryset): + if files_queryset: + + +## ... source file continues with no further escape examples... + +``` + + +## Example 5 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / templatetags / rest_framework.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/templatetags/rest_framework.py) + +```python +# rest_framework.py +import re +from collections import OrderedDict + +from django import template +from django.template import loader +from django.urls import NoReverseMatch, reverse +from django.utils.encoding import force_str, iri_to_uri +~~from django.utils.html import escape, format_html, smart_urlquote +from django.utils.safestring import SafeData, mark_safe + +from rest_framework.compat import apply_markdown, pygments_highlight +from rest_framework.renderers import HTMLFormRenderer +from rest_framework.utils.urls import replace_query_param + +register = template.Library() + +class_re = re.compile(r'(?<=class=["\'])(.*)(?=["\'])') + + +@register.tag(name='code') +def highlight_code(parser, token): + code = token.split_contents()[-1] + nodelist = parser.parse(('endcode',)) + parser.delete_first_token() + return CodeNode(code, nodelist) + + +class CodeNode(template.Node): + style = 'emacs' + + def __init__(self, lang, code): + self.lang = lang + + +## ... source file abbreviated to get to escape examples ... + + +def optional_logout(request, user): + try: + logout_url = reverse('rest_framework:logout') + except NoReverseMatch: +~~ snippet = format_html('', user=escape(user)) + return mark_safe(snippet) + + snippet = """""" +~~ snippet = format_html(snippet, user=escape(user), href=logout_url, next=escape(request.path)) + + return mark_safe(snippet) + + +@register.simple_tag +def add_query_param(request, key, val): + iri = request.get_full_path() + uri = iri_to_uri(iri) +~~ return escape(replace_query_param(uri, key, val)) + + +@register.filter +def as_string(value): + if value is None: + return '' + return '%s' % value + + +@register.filter +def as_list_of_strings(value): + return [ + '' if (item is None) else ('%s' % item) + for item in value + ] + + +@register.filter +def add_class(value, css_class): + html = str(value) + match = class_re.search(html) + if match: + m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class, + css_class, css_class), + match.group(1)) + if not m: + return mark_safe(class_re.sub(match.group(1) + " " + css_class, + html)) + else: + return mark_safe(html.replace('>', ' class="%s">' % css_class, 1)) + return value + + +@register.filter +def format_value(value): + if getattr(value, 'is_hyperlink', False): + name = str(value.obj) +~~ return mark_safe('%s' % (value, escape(name))) + if value is None or isinstance(value, bool): + return mark_safe('%s' % {True: 'true', False: 'false', None: 'null'}[value]) + elif isinstance(value, list): + if any([isinstance(item, (list, dict)) for item in value]): + template = loader.get_template('rest_framework/admin/list_value.html') + else: + template = loader.get_template('rest_framework/admin/simple_list_value.html') + context = {'value': value} + return template.render(context) + elif isinstance(value, dict): + template = loader.get_template('rest_framework/admin/dict_value.html') + context = {'value': value} + return template.render(context) + elif isinstance(value, str): + if ( + (value.startswith('http:') or value.startswith('https:')) and not + re.search(r'\s', value) + ): +~~ return mark_safe('{value}'.format(value=escape(value))) + elif '@' in value and not re.search(r'\s', value): +~~ return mark_safe('{value}'.format(value=escape(value))) + elif '\n' in value: +~~ return mark_safe('
    %s
    ' % escape(value)) + return str(value) + + +@register.filter +def items(value): + if value is None: + return [] + return value.items() + + +@register.filter +def data(value): + return value.data + + +@register.filter +def schema_links(section, sec_key=None): + NESTED_FORMAT = '%s > %s' # this format is used in docs/js/api.js:normalizeKeys + links = section.links + if section.data: + data = section.data.items() + for sub_section_key, sub_section in data: + new_links = schema_links(sub_section, sec_key=sub_section_key) + links.update(new_links) + + +## ... source file abbreviated to get to escape examples ... + + + +TRAILING_PUNCTUATION = ['.', ',', ':', ';', '.)', '"', "']", "'}", "'"] +WRAPPING_PUNCTUATION = [('(', ')'), ('<', '>'), ('[', ']'), ('<', '>'), + ('"', '"'), ("'", "'")] +word_split_re = re.compile(r'(\s+)') +simple_url_re = re.compile(r'^https?://\[?\w', re.IGNORECASE) +simple_url_2_re = re.compile(r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)$', re.IGNORECASE) +simple_email_re = re.compile(r'^\S+@\S+\.\S+$') + + +def smart_urlquote_wrapper(matched_url): + try: + return smart_urlquote(matched_url) + except ValueError: + return None + + +@register.filter(needs_autoescape=True) +def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=True): + def trim_url(x, limit=trim_url_limit): + return limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x + + safe_input = isinstance(text, SafeData) + + def conditional_escape(text): +~~ return escape(text) if autoescape and not safe_input else text + + words = word_split_re.split(force_str(text)) + for i, word in enumerate(words): + if '.' in word or '@' in word or ':' in word: + lead, middle, trail = '', word, '' + for punctuation in TRAILING_PUNCTUATION: + if middle.endswith(punctuation): + middle = middle[:-len(punctuation)] + trail = punctuation + trail + for opening, closing in WRAPPING_PUNCTUATION: + if middle.startswith(opening): + middle = middle[len(opening):] + lead = lead + opening + if ( + middle.endswith(closing) and + middle.count(closing) == middle.count(opening) + 1 + ): + middle = middle[:-len(closing)] + trail = closing + trail + + url = None + nofollow_attr = ' rel="nofollow"' if nofollow else '' + if simple_url_re.match(middle): + url = smart_urlquote_wrapper(middle) +def get_pagination_html(pager): + return pager.to_html() + + +@register.simple_tag +def render_form(serializer, template_pack=None): + style = {'template_pack': template_pack} if template_pack else {} + renderer = HTMLFormRenderer() + return renderer.render(serializer.data, None, {'style': style}) + + +@register.simple_tag +def render_field(field, style): + renderer = style.get('renderer', HTMLFormRenderer()) + return renderer.render_field(field, style) + + +@register.simple_tag +def optional_login(request): + try: + login_url = reverse('rest_framework:login') + except NoReverseMatch: + return '' + + snippet = "
  • Log in
  • " +~~ snippet = format_html(snippet, href=login_url, next=escape(request.path)) + + return mark_safe(snippet) + + +@register.simple_tag +def optional_docs_login(request): + try: + login_url = reverse('rest_framework:login') + except NoReverseMatch: + return 'log in' + + snippet = "log in" +~~ snippet = format_html(snippet, href=login_url, next=escape(request.path)) + + return mark_safe(snippet) + + +@register.simple_tag + + +## ... source file continues with no further escape examples... + +``` + + +## Example 6 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / templatetags / django_tables2.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/templatetags/django_tables2.py) + +```python +# django_tables2.py +import re +from collections import OrderedDict + +from django import template +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.template import Node, TemplateSyntaxError +from django.template.loader import get_template, select_template +from django.templatetags.l10n import register as l10n_register +~~from django.utils.html import escape +from django.utils.http import urlencode + +import django_tables2 as tables +from django_tables2.paginators import LazyPaginator +from django_tables2.utils import AttributeDict + +register = template.Library() +kwarg_re = re.compile(r"(?:(.+)=)?(.+)") +context_processor_error_msg = ( + "Tag {%% %s %%} requires django.template.context_processors.request to be " + "in the template configuration in " + "settings.TEMPLATES[]OPTIONS.context_processors) in order for the included " + "template tags to function correctly." +) + + +def token_kwargs(bits, parser): + if not bits: + return {} + kwargs = OrderedDict() + while bits: + match = kwarg_re.match(bits[0]) + if not match or not match.group(1): + return kwargs + + +## ... source file abbreviated to get to escape examples ... + + + + +class QuerystringNode(Node): + def __init__(self, updates, removals, asvar=None): + super().__init__() + self.updates = updates + self.removals = removals + self.asvar = asvar + + def render(self, context): + if "request" not in context: + raise ImproperlyConfigured(context_processor_error_msg % "querystring") + + params = dict(context["request"].GET) + for key, value in self.updates.items(): + if isinstance(key, str): + params[key] = value + continue + key = key.resolve(context) + value = value.resolve(context) + if key not in ("", None): + params[key] = value + for removal in self.removals: + params.pop(removal.resolve(context), None) + +~~ value = escape("?" + urlencode(params, doseq=True)) + + if self.asvar: + context[str(self.asvar)] = value + return "" + else: + return value + + +@register.tag +def querystring(parser, token): + bits = token.split_contents() + tag = bits.pop(0) + updates = token_kwargs(bits, parser) + + asvar_key = None + for key in updates: + if str(key) == "as": + asvar_key = key + + if asvar_key is not None: + asvar = updates[asvar_key] + del updates[asvar_key] + else: + asvar = None + + +## ... source file continues with no further escape examples... + +``` + + +## Example 7 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / images / formats.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/images/formats.py) + +```python +# formats.py +~~from django.utils.html import escape +from django.utils.translation import gettext_lazy as _ + +from wagtail.utils.apps import get_app_submodules + +from .shortcuts import get_rendition_or_not_found + + +class Format: + def __init__(self, name, label, classnames, filter_spec): + self.name = name + self.label = label + self.classnames = classnames + self.filter_spec = filter_spec + + def editor_attributes(self, image, alt_text): + return { + 'data-embedtype': "image", + 'data-id': image.id, + 'data-format': self.name, +~~ 'data-alt': escape(alt_text), + } + + def image_to_editor_html(self, image, alt_text): + return self.image_to_html( + image, alt_text, self.editor_attributes(image, alt_text) + ) + + def image_to_html(self, image, alt_text, extra_attributes=None): + if extra_attributes is None: + extra_attributes = {} + rendition = get_rendition_or_not_found(image, self.filter_spec) + +~~ extra_attributes['alt'] = escape(alt_text) + if self.classnames: +~~ extra_attributes['class'] = "%s" % escape(self.classnames) + + return rendition.img_tag(extra_attributes) + + +FORMATS = [] +FORMATS_BY_NAME = {} + + +def register_image_format(format): + if format.name in FORMATS_BY_NAME: + raise KeyError("Image format '%s' is already registered" % format.name) + FORMATS_BY_NAME[format.name] = format + FORMATS.append(format) + + +def unregister_image_format(format_name): + global FORMATS + try: + format_name = format_name.name + except AttributeError: + pass + + try: + del FORMATS_BY_NAME[format_name] + + +## ... source file continues with no further escape examples... + +``` + diff --git a/content/pages/examples/django/django-utils-html-escapejs.markdown b/content/pages/examples/django/django-utils-html-escapejs.markdown new file mode 100644 index 000000000..c797295b6 --- /dev/null +++ b/content/pages/examples/django/django-utils-html-escapejs.markdown @@ -0,0 +1,124 @@ +title: django.utils.html escapejs Example Code +category: page +slug: django-utils-html-escapejs-examples +sortorder: 500011463 +toc: False +sidebartitle: django.utils.html escapejs +meta: Python example code for the escapejs callable from the django.utils.html module of the Django project. + + +escapejs is a callable within the django.utils.html module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_base.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_base.py) + +```python +# plugin_base.py +import json +import re + +from django.shortcuts import render as render_to_response + +from django import forms +from django.contrib import admin +from django.contrib import messages +from django.core.exceptions import ( + ImproperlyConfigured, + ObjectDoesNotExist, + ValidationError, +) +from django.utils.encoding import force_text, smart_str +~~from django.utils.html import escapejs +from django.utils.translation import ugettext, ugettext_lazy as _ + +from six import with_metaclass, python_2_unicode_compatible + +from cms import operations +from cms.exceptions import SubClassNeededError +from cms.models import CMSPlugin +from cms.toolbar.utils import get_plugin_tree_as_json, get_plugin_toolbar_info +from cms.utils.conf import get_cms_setting + + +class CMSPluginBaseMetaclass(forms.MediaDefiningClass): + def __new__(cls, name, bases, attrs): + super_new = super(CMSPluginBaseMetaclass, cls).__new__ + parents = [base for base in bases if isinstance(base, CMSPluginBaseMetaclass)] + if not parents: + return super_new(cls, name, bases, attrs) + new_plugin = super_new(cls, name, bases, attrs) + if not issubclass(new_plugin.model, CMSPlugin): + raise SubClassNeededError( + "The 'model' attribute on CMSPluginBase subclasses must be " + "either CMSPlugin or a subclass of CMSPlugin. %r on %r is not." + % (new_plugin.model, new_plugin) + ) + + +## ... source file abbreviated to get to escapejs examples ... + + + def render_close_frame(self, request, obj, extra_context=None): + try: + root = obj.parent.get_bound_plugin() if obj.parent else obj + except ObjectDoesNotExist: + root = obj + + plugins = [root] + list(root.get_descendants().order_by('path')) + + child_classes = self.get_child_classes( + slot=obj.placeholder.slot, + page=obj.page, + instance=obj, + ) + + parent_classes = self.get_parent_classes( + slot=obj.placeholder.slot, + page=obj.page, + instance=obj, + ) + + data = get_plugin_toolbar_info( + obj, + children=child_classes, + parents=parent_classes, + ) +~~ data['plugin_desc'] = escapejs(force_text(obj.get_short_description())) + + context = { + 'plugin': obj, + 'is_popup': True, + 'plugin_data': json.dumps(data), + 'plugin_structure': get_plugin_tree_as_json(request, plugins), + } + + if extra_context: + context.update(extra_context) + return render_to_response( + request, 'admin/cms/page/plugin/confirm_form.html', context + ) + + def save_model(self, request, obj, form, change): + pl_admin = obj.placeholder._get_attached_admin() + + if pl_admin: + operation_kwargs = { + 'request': request, + 'placeholder': obj.placeholder, + } + + if change: + + +## ... source file continues with no further escapejs examples... + +``` + diff --git a/content/pages/examples/django/django-utils-html-format-html-join.markdown b/content/pages/examples/django/django-utils-html-format-html-join.markdown new file mode 100644 index 000000000..755f93e3d --- /dev/null +++ b/content/pages/examples/django/django-utils-html-format-html-join.markdown @@ -0,0 +1,313 @@ +title: django.utils.html format_html_join Example Code +category: page +slug: django-utils-html-format-html-join-examples +sortorder: 500011465 +toc: False +sidebartitle: django.utils.html format_html_join +meta: Python example code for the format_html_join callable from the django.utils.html module of the Django project. + + +format_html_join is a callable within the django.utils.html module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / sekizai_processors.py**](https://github.com/jrief/django-angular/blob/master/djng/./sekizai_processors.py) + +```python +# sekizai_processors.py + +import warnings + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +~~from django.utils.html import format_html_join +from django.utils.safestring import mark_safe + +if 'sekizai' not in settings.INSTALLED_APPS: + msg = "Install django-sekizai when using these postprocessors" + raise ImproperlyConfigured(msg) + + +def module_list(context, data, namespace): + warnings.warn("This postprocessor is deprecated. Read on how to resolve AngularJS dependencies using `{% with_data \"ng-requires\" ... %}`") + modules = set(m.strip(' "\'') for m in data.split()) +~~ text = format_html_join(', ', '"{0}"', ((m,) for m in modules)) + return text + + +def module_config(context, data, namespace): + warnings.warn("This postprocessor is deprecated. Read on how to resolve AngularJS dependencies using `{% with_data \"ng-config\" ... %}`") + configs = [(mark_safe(c),) for c in data.split('\n') if c] +~~ text = format_html_join('', '.config({0})', configs) + return text + + + +## ... source file continues with no further format_html_join examples... + +``` + + +## Example 2 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / templatetags / filer_admin_tags.py**](https://github.com/divio/django-filer/blob/develop/filer/templatetags/filer_admin_tags.py) + +```python +# filer_admin_tags.py +from __future__ import absolute_import, unicode_literals + +from django.template import Library +~~from django.utils.html import format_html_join + +from ..admin.tools import admin_url_params, admin_url_params_encoded + + +register = Library() + +assignment_tag = getattr(register, 'assignment_tag', register.simple_tag) + + +def filer_actions(context): + context['action_index'] = context.get('action_index', -1) + 1 + return context + + +filer_actions = register.inclusion_tag( + "admin/filer/actions.html", takes_context=True)(filer_actions) + + +@register.simple_tag(takes_context=True) +def filer_admin_context_url_params(context, first_separator='?'): + return admin_url_params_encoded( + context['request'], first_separator=first_separator) + + +@register.simple_tag(takes_context=True) +def filer_admin_context_hidden_formfields(context): + request = context.get('request') +~~ return format_html_join( + '\n', + '', + admin_url_params(request).items(), + ) + + +@assignment_tag(takes_context=True) +def filer_has_permission(context, item, action): + permission_method_name = 'has_{action}_permission'.format(action=action) + permission_method = getattr(item, permission_method_name, None) + request = context.get('request') + + if not permission_method or not request: + return False + return permission_method(request) + + + +## ... source file continues with no further format_html_join examples... + +``` + + +## Example 3 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / utils.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/./utils.py) + +```python +# utils.py +import inspect +import warnings +from collections import OrderedDict +from functools import total_ordering +from itertools import chain + +from django.core.exceptions import FieldDoesNotExist +from django.db import models +~~from django.utils.html import format_html_join + + +class Sequence(list): + + def expand(self, columns): + ellipses = self.count("...") + if ellipses > 1: + raise ValueError("'...' must be used at most once in a sequence.") + elif ellipses == 0: + self.append("...") + + columns = list(columns) # take a copy and exhaust the generator + head = [] + tail = [] + target = head # start by adding things to the head + for name in self: + if name == "...": + target = tail + continue + target.append(name) + if name in columns: + columns.pop(columns.index(name)) + self[:] = chain(head, columns, tail) + + + +## ... source file abbreviated to get to format_html_join examples ... + + + if hasattr(field, "remote_field"): + rel = getattr(field, "remote_field", None) + model = getattr(rel, "model", model) + + return field + + def penultimate(self, context, quiet=True): + path, _, remainder = self.rpartition(self.SEPARATOR) + return A(path).resolve(context, quiet=quiet), remainder + + +A = Accessor # alias + + +class AttributeDict(OrderedDict): + + blacklist = ("th", "td", "_ordering", "thead", "tbody", "tfoot") + + def _iteritems(self): + for key, v in self.items(): + value = v() if callable(v) else v + if key not in self.blacklist and value is not None: + yield (key, value) + + def as_html(self): +~~ return format_html_join(" ", '{}="{}"', self._iteritems()) + + +def segment(sequence, aliases): + if not (sequence or aliases): + return + for alias, parts in aliases.items(): + variants = { + alias: OrderByTuple(parts), + OrderBy(alias).opposite: OrderByTuple(parts).opposite, + } + for valias, vparts in variants.items(): + if list(sequence[: len(vparts)]) == list(vparts): + tail_aliases = dict(aliases) + del tail_aliases[alias] + tail_sequence = sequence[len(vparts) :] + if tail_sequence: + for tail in segment(tail_sequence, tail_aliases): + yield tuple(chain([valias], tail)) + else: + continue + else: + yield tuple([valias]) + + + + +## ... source file continues with no further format_html_join examples... + +``` + + +## Example 4 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / admin / messages.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/admin/messages.py) + +```python +# messages.py +from django.contrib import messages +from django.core.exceptions import NON_FIELD_ERRORS +from django.template.loader import render_to_string +~~from django.utils.html import format_html, format_html_join + + +def render(message, buttons, detail=''): + return render_to_string('wagtailadmin/shared/messages.html', { + 'message': message, + 'buttons': buttons, + 'detail': detail, + }) + + +def debug(request, message, buttons=None, extra_tags=''): + return messages.debug(request, render(message, buttons), extra_tags=extra_tags) + + +def info(request, message, buttons=None, extra_tags=''): + return messages.info(request, render(message, buttons), extra_tags=extra_tags) + + +def success(request, message, buttons=None, extra_tags=''): + return messages.success(request, render(message, buttons), extra_tags=extra_tags) + + +def warning(request, message, buttons=None, extra_tags=''): + return messages.warning(request, render(message, buttons), extra_tags=extra_tags) + + +def error(request, message, buttons=None, extra_tags=''): + return messages.error(request, render(message, buttons), extra_tags=extra_tags) + + +def validation_error(request, message, form, buttons=None): + if not form.non_field_errors(): + detail = '' + else: + all_errors = [] + for field_name, errors in form.errors.items(): + if field_name == NON_FIELD_ERRORS: + prefix = '' + else: + try: + field_label = form[field_name].label + except KeyError: + field_label = field_name + prefix = "%s: " % field_label + + for error in errors: + all_errors.append(prefix + error) + +~~ errors_html = format_html_join('\n', '
  • {}
  • ', ((e,) for e in all_errors)) + detail = format_html("""
      {}
    """, errors_html) + + return messages.error(request, render(message, buttons, detail=detail)) + + +def button(url, text, new_window=False): + if url is None: + raise ValueError("Button URLs must not be None") + return url, text, new_window + + + +## ... source file continues with no further format_html_join examples... + +``` + diff --git a/content/pages/examples/django/django-utils-html-mark-safe.markdown b/content/pages/examples/django/django-utils-html-mark-safe.markdown new file mode 100644 index 000000000..bf8143c5d --- /dev/null +++ b/content/pages/examples/django/django-utils-html-mark-safe.markdown @@ -0,0 +1,321 @@ +title: django.utils.html mark_safe Example Code +category: page +slug: django-utils-html-mark-safe-examples +sortorder: 500011466 +toc: False +sidebartitle: django.utils.html mark_safe +meta: Python example code for the mark_safe callable from the django.utils.html module of the Django project. + + +mark_safe is a callable within the django.utils.html module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / renderers.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./renderers.py) + +```python +# renderers.py +import base64 +from collections import OrderedDict +from urllib import parse + +from django import forms +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.core.paginator import Page +from django.http.multipartparser import parse_header +from django.template import engines, loader +from django.urls import NoReverseMatch +~~from django.utils.html import mark_safe + +from rest_framework import VERSION, exceptions, serializers, status +from rest_framework.compat import ( + INDENT_SEPARATORS, LONG_SEPARATORS, SHORT_SEPARATORS, coreapi, coreschema, + pygments_css, yaml +) +from rest_framework.exceptions import ParseError +from rest_framework.request import is_form_media_type, override_method +from rest_framework.settings import api_settings +from rest_framework.utils import encoders, json +from rest_framework.utils.breadcrumbs import get_breadcrumbs +from rest_framework.utils.field_mapping import ClassLookupDict + + +def zero_as_none(value): + return None if value == 0 else value + + +class BaseRenderer: + media_type = None + format = None + charset = 'utf-8' + render_style = 'text' + + + +## ... source file abbreviated to get to mark_safe examples ... + + + template = loader.get_template(self.template) + context = self.get_context(data, renderer_context['request']) + return template.render(context, request=renderer_context['request']) + else: + template = loader.get_template(self.error_template) + context = { + "data": data, + "request": renderer_context['request'], + "response": renderer_context['response'], + "debug": settings.DEBUG, + } + return template.render(context, request=renderer_context['request']) + + +class SchemaJSRenderer(BaseRenderer): + media_type = 'application/javascript' + format = 'javascript' + charset = 'utf-8' + template = 'rest_framework/schema.js' + + def render(self, data, accepted_media_type=None, renderer_context=None): + codec = coreapi.codecs.CoreJSONCodec() + schema = base64.b64encode(codec.encode(data)).decode('ascii') + + template = loader.get_template(self.template) +~~ context = {'schema': mark_safe(schema)} + request = renderer_context['request'] + return template.render(context, request=request) + + +class MultiPartRenderer(BaseRenderer): + media_type = 'multipart/form-data; boundary=BoUnDaRyStRiNg' + format = 'multipart' + charset = 'utf-8' + BOUNDARY = 'BoUnDaRyStRiNg' + + def render(self, data, accepted_media_type=None, renderer_context=None): + from django.test.client import encode_multipart + + if hasattr(data, 'items'): + for key, value in data.items(): + assert not isinstance(value, dict), ( + "Test data contained a dictionary value for key '%s', " + "but multipart uploads do not support nested data. " + "You may want to consider using format='json' in this " + "test case." % key + ) + return encode_multipart(self.BOUNDARY, data) + + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 2 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / columns / manytomanycolumn.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/columns/manytomanycolumn.py) + +```python +# manytomanycolumn.py +from django.db import models +from django.utils.encoding import force_str +~~from django.utils.html import conditional_escape, mark_safe + +from .base import Column, LinkTransform, library + + +@library.register +class ManyToManyColumn(Column): + + def __init__( + self, transform=None, filter=None, separator=", ", linkify_item=None, *args, **kwargs + ): + kwargs.setdefault("orderable", False) + super().__init__(*args, **kwargs) + + if transform is not None: + self.transform = transform + if filter is not None: + self.filter = filter + self.separator = separator + + link_kwargs = None + if callable(linkify_item): + link_kwargs = dict(url=linkify_item) + elif isinstance(linkify_item, (dict, tuple)): + link_kwargs = dict(reverse_args=linkify_item) + elif linkify_item is True: + link_kwargs = dict() + + if link_kwargs is not None: + self.linkify_item = LinkTransform(attrs=self.attrs.get("a", {}), **link_kwargs) + + def transform(self, obj): + return force_str(obj) + + def filter(self, qs): + return qs.all() + + def render(self, value): + if not value.exists(): + return self.default + + items = [] + for item in self.filter(value): + content = conditional_escape(self.transform(item)) + if hasattr(self, "linkify_item"): + content = self.linkify_item(content=content, record=item) + + items.append(content) + +~~ return mark_safe(conditional_escape(self.separator).join(items)) + + @classmethod + def from_field(cls, field, **kwargs): + if isinstance(field, models.ManyToManyField): + return cls(**kwargs) + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 3 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / users / forms.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/users/forms.py) + +```python +# forms.py +import warnings +from itertools import groupby +from operator import itemgetter + +import l18n + +from django import forms +from django.conf import settings +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group, Permission +from django.contrib.auth.password_validation import ( + password_validators_help_text_html, validate_password) +from django.db import transaction +from django.db.models.fields import BLANK_CHOICE_DASH +from django.template.loader import render_to_string +~~from django.utils.html import mark_safe +from django.utils.translation import gettext_lazy as _ + +from wagtail.admin.localization import get_available_admin_languages, get_available_admin_time_zones +from wagtail.admin.widgets import AdminPageChooser +from wagtail.core import hooks +from wagtail.core.models import ( + PAGE_PERMISSION_TYPE_CHOICES, PAGE_PERMISSION_TYPES, GroupPagePermission, Page, + UserPagePermissionsProxy) +from wagtail.users.models import UserProfile + +User = get_user_model() + +standard_fields = set(['email', 'first_name', 'last_name', 'is_superuser', 'groups']) +if hasattr(settings, 'WAGTAIL_USER_CUSTOM_FIELDS'): + custom_fields = set(settings.WAGTAIL_USER_CUSTOM_FIELDS) +else: + custom_fields = set() + + +class UsernameForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if User.USERNAME_FIELD == 'username': + field = self.fields['username'] + + +## ... source file abbreviated to get to mark_safe examples ... + + + } + + email = forms.EmailField(required=True, label=_('Email')) + first_name = forms.CharField(required=True, label=_('First Name')) + last_name = forms.CharField(required=True, label=_('Last Name')) + + password1 = forms.CharField( + label=_('Password'), required=False, + widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}), + help_text=_("Leave blank if not changing.")) + password2 = forms.CharField( + label=_("Password confirmation"), required=False, + widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}), + help_text=_("Enter the same password as above, for verification.")) + + is_superuser = forms.BooleanField( + label=_("Administrator"), required=False, + help_text=_('Administrators have full access to manage any object ' + 'or setting.')) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + if self.password_enabled: + if self.password_required: +~~ self.fields['password1'].help_text = mark_safe(password_validators_help_text_html()) + self.fields['password1'].required = True + self.fields['password2'].required = True + else: + del self.fields['password1'] + del self.fields['password2'] + + def _clean_username(self): + username_field = User.USERNAME_FIELD + if username_field not in self.cleaned_data: + return + username = self.cleaned_data[username_field] + + users = User._default_manager.all() + if self.instance.pk is not None: + users = users.exclude(pk=self.instance.pk) + if users.filter(**{username_field: username}).exists(): + self.add_error(User.USERNAME_FIELD, forms.ValidationError( + self.error_messages['duplicate_username'], + code='duplicate_username', + )) + return username + + def clean_password2(self): + password1 = self.cleaned_data.get("password1") + + +## ... source file continues with no further mark_safe examples... + +``` + diff --git a/content/pages/examples/django/django-utils-html-smart-urlquote.markdown b/content/pages/examples/django/django-utils-html-smart-urlquote.markdown new file mode 100644 index 000000000..029f04c3c --- /dev/null +++ b/content/pages/examples/django/django-utils-html-smart-urlquote.markdown @@ -0,0 +1,124 @@ +title: django.utils.html smart_urlquote Example Code +category: page +slug: django-utils-html-smart-urlquote-examples +sortorder: 500011467 +toc: False +sidebartitle: django.utils.html smart_urlquote +meta: Python example code for the smart_urlquote callable from the django.utils.html module of the Django project. + + +smart_urlquote is a callable within the django.utils.html module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / templatetags / rest_framework.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/templatetags/rest_framework.py) + +```python +# rest_framework.py +import re +from collections import OrderedDict + +from django import template +from django.template import loader +from django.urls import NoReverseMatch, reverse +from django.utils.encoding import force_str, iri_to_uri +~~from django.utils.html import escape, format_html, smart_urlquote +from django.utils.safestring import SafeData, mark_safe + +from rest_framework.compat import apply_markdown, pygments_highlight +from rest_framework.renderers import HTMLFormRenderer +from rest_framework.utils.urls import replace_query_param + +register = template.Library() + +class_re = re.compile(r'(?<=class=["\'])(.*)(?=["\'])') + + +@register.tag(name='code') +def highlight_code(parser, token): + code = token.split_contents()[-1] + nodelist = parser.parse(('endcode',)) + parser.delete_first_token() + return CodeNode(code, nodelist) + + +class CodeNode(template.Node): + style = 'emacs' + + def __init__(self, lang, code): + self.lang = lang + + +## ... source file abbreviated to get to smart_urlquote examples ... + + + return new_links + + return links + + +@register.filter +def add_nested_class(value): + if isinstance(value, dict): + return 'class=nested' + if isinstance(value, list) and any([isinstance(item, (list, dict)) for item in value]): + return 'class=nested' + return '' + + +TRAILING_PUNCTUATION = ['.', ',', ':', ';', '.)', '"', "']", "'}", "'"] +WRAPPING_PUNCTUATION = [('(', ')'), ('<', '>'), ('[', ']'), ('<', '>'), + ('"', '"'), ("'", "'")] +word_split_re = re.compile(r'(\s+)') +simple_url_re = re.compile(r'^https?://\[?\w', re.IGNORECASE) +simple_url_2_re = re.compile(r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)$', re.IGNORECASE) +simple_email_re = re.compile(r'^\S+@\S+\.\S+$') + + +def smart_urlquote_wrapper(matched_url): + try: +~~ return smart_urlquote(matched_url) + except ValueError: + return None + + +@register.filter(needs_autoescape=True) +def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=True): + def trim_url(x, limit=trim_url_limit): + return limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x + + safe_input = isinstance(text, SafeData) + + def conditional_escape(text): + return escape(text) if autoescape and not safe_input else text + + words = word_split_re.split(force_str(text)) + for i, word in enumerate(words): + if '.' in word or '@' in word or ':' in word: + lead, middle, trail = '', word, '' + for punctuation in TRAILING_PUNCTUATION: + if middle.endswith(punctuation): + middle = middle[:-len(punctuation)] + trail = punctuation + trail + for opening, closing in WRAPPING_PUNCTUATION: + if middle.startswith(opening): + + +## ... source file continues with no further smart_urlquote examples... + +``` + diff --git a/content/pages/examples/django/django-utils-html-strip-tags.markdown b/content/pages/examples/django/django-utils-html-strip-tags.markdown new file mode 100644 index 000000000..bcc36572c --- /dev/null +++ b/content/pages/examples/django/django-utils-html-strip-tags.markdown @@ -0,0 +1,213 @@ +title: django.utils.html strip_tags Example Code +category: page +slug: django-utils-html-strip-tags-examples +sortorder: 500011468 +toc: False +sidebartitle: django.utils.html strip_tags +meta: Python example code for the strip_tags callable from the django.utils.html module of the Django project. + + +strip_tags is a callable within the django.utils.html module of the Django project. + + +## Example 1 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / utils / highlighting.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/utils/highlighting.py) + +```python +# highlighting.py +~~from django.utils.html import strip_tags + + +class Highlighter(object): + css_class = "highlighted" + html_tag = "span" + max_length = 200 + text_block = "" + + def __init__(self, query, **kwargs): + self.query = query + + if "max_length" in kwargs: + self.max_length = int(kwargs["max_length"]) + + if "html_tag" in kwargs: + self.html_tag = kwargs["html_tag"] + + if "css_class" in kwargs: + self.css_class = kwargs["css_class"] + + self.query_words = set( + [word.lower() for word in self.query.split() if not word.startswith("-")] + ) + + def highlight(self, text_block): +~~ self.text_block = strip_tags(text_block) + highlight_locations = self.find_highlightable_words() + start_offset, end_offset = self.find_window(highlight_locations) + return self.render_html(highlight_locations, start_offset, end_offset) + + def find_highlightable_words(self): + word_positions = {} + + end_offset = len(self.text_block) + lower_text_block = self.text_block.lower() + + for word in self.query_words: + if word not in word_positions: + word_positions[word] = [] + + start_offset = 0 + + while start_offset < end_offset: + next_offset = lower_text_block.find(word, start_offset, end_offset) + + if next_offset == -1: + break + + word_positions[word].append(next_offset) + start_offset = next_offset + len(word) + + +## ... source file continues with no further strip_tags examples... + +``` + + +## Example 2 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / columns / templatecolumn.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/columns/templatecolumn.py) + +```python +# templatecolumn.py +from django.template import Context, Template +from django.template.loader import get_template +~~from django.utils.html import strip_tags + +from .base import Column, library + + +@library.register +class TemplateColumn(Column): + + empty_values = () + + def __init__(self, template_code=None, template_name=None, extra_context=None, **extra): + super().__init__(**extra) + self.template_code = template_code + self.template_name = template_name + self.extra_context = extra_context or {} + + if not self.template_code and not self.template_name: + raise ValueError("A template must be provided") + + def render(self, record, table, value, bound_column, **kwargs): + context = getattr(table, "context", Context()) + context.update(self.extra_context) + context.update( + { + "default": bound_column.default, + "column": bound_column, + "record": record, + "value": value, + "row_counter": kwargs["bound_row"].row_counter, + } + ) + + try: + if self.template_code: + return Template(self.template_code).render(context) + else: + return get_template(self.template_name).render(context.flatten()) + finally: + context.pop() + + def value(self, **kwargs): + html = super().value(**kwargs) +~~ return strip_tags(html) if isinstance(html, str) else html + + + +## ... source file continues with no further strip_tags examples... + +``` + + +## Example 3 from register +[register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is +open source under the +[GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). +This web application makes it easier for people to register as organ donors. +You can see the application live at +[https://register.organize.org/](https://register.organize.org/). + +[**register / registration / bootstrap3_renderers.py**](https://github.com/ORGAN-IZE/register/blob/master/registration/./bootstrap3_renderers.py) + +```python +# bootstrap3_renderers.py +import re + +from django.forms import ( + CheckboxInput, ClearableFileInput, RadioSelect, CheckboxSelectMultiple +) +from django.forms.widgets import SelectDateWidget +~~from django.utils.html import strip_tags + +import bootstrap3.renderers +from bootstrap3.forms import render_label + + +RE_INPUT_TAG = re.compile(r'()()') + + +class FiftyThreeFieldRenderer(bootstrap3.renderers.FieldRenderer): + def post_widget_render(self, html): + if isinstance(self.widget, RadioSelect): + html = self.list_to_class(html, 'radio') + html = self.invert_radio_input(html) + elif isinstance(self.widget, CheckboxSelectMultiple): + html = self.list_to_class(html, 'checkbox') + elif isinstance(self.widget, SelectDateWidget): + html = self.fix_date_select_input(html) + elif isinstance(self.widget, ClearableFileInput): + html = self.fix_clearable_file_input(html) + elif isinstance(self.widget, CheckboxInput): + html = self.put_inside_label(html) + return html + + def put_inside_label(self, html): + return html + render_label( + content=self.field.label, label_for=self.field.id_for_label, +~~ label_title=strip_tags(self.field_help)) + + def invert_radio_input(self, html): + return re.sub(RE_INPUT_TAG, r'\2\1', html) + + + +## ... source file continues with no further strip_tags examples... + +``` + diff --git a/content/pages/examples/django/django-utils-http-base36-to-int.markdown b/content/pages/examples/django/django-utils-http-base36-to-int.markdown new file mode 100644 index 000000000..b5f2eb32c --- /dev/null +++ b/content/pages/examples/django/django-utils-http-base36-to-int.markdown @@ -0,0 +1,105 @@ +title: django.utils.http base36_to_int Example Code +category: page +slug: django-utils-http-base36-to-int-examples +sortorder: 500011469 +toc: False +sidebartitle: django.utils.http base36_to_int +meta: Python example code for the base36_to_int callable from the django.utils.http module of the Django project. + + +base36_to_int is a callable within the django.utils.http module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / tests.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/./tests.py) + +```python +# tests.py +from __future__ import unicode_literals + +import json +import requests +from datetime import date, datetime + +import django +from django.core.files.base import ContentFile +from django.db import models +from django.test import RequestFactory, TestCase +~~from django.utils.http import base36_to_int, int_to_base36 +from django.views import csrf + +from . import utils + + +try: + from unittest.mock import Mock, patch +except ImportError: + from mock import Mock, patch # noqa + + +class MockedResponse(object): + def __init__(self, status_code, content, headers=None): + if headers is None: + headers = {} + + self.status_code = status_code + self.content = content.encode('utf8') + self.headers = headers + + def json(self): + return json.loads(self.text) + + def raise_for_status(self): + + +## ... source file abbreviated to get to base36_to_int examples ... + + + instance = SomeBinaryModel(bb=b'some binary data') + + serialized = utils.serialize_instance(instance) + deserialized = utils.deserialize_instance(SomeBinaryModel, serialized) + + self.assertEqual(serialized['bb'], 'c29tZSBiaW5hcnkgZGF0YQ==') + self.assertEqual(serialized['bb_empty'], '') + self.assertEqual(deserialized.bb, b'some binary data') + self.assertEqual(deserialized.bb_empty, b'') + + def test_build_absolute_uri(self): + self.assertEqual( + utils.build_absolute_uri(None, '/foo'), + 'http://example.com/foo') + self.assertEqual( + utils.build_absolute_uri(None, '/foo', protocol='ftp'), + 'ftp://example.com/foo') + self.assertEqual( + utils.build_absolute_uri(None, 'http://foo.com/bar'), + 'http://foo.com/bar') + + def test_int_to_base36(self): + n = 55798679658823689999 + b36 = 'brxk553wvxbf3' + assert int_to_base36(n) == b36 +~~ assert base36_to_int(b36) == n + + def test_templatetag_with_csrf_failure(self): + request = self.factory.get('/tests/test_403_csrf.html') + response = csrf.csrf_failure( + request, + template_name='tests/test_403_csrf.html' + ) + self.assertEqual(response.status_code, 403) + + + +## ... source file continues with no further base36_to_int examples... + +``` + diff --git a/content/pages/examples/django/django-utils-http-http-date.markdown b/content/pages/examples/django/django-utils-http-http-date.markdown new file mode 100644 index 000000000..8b0002b19 --- /dev/null +++ b/content/pages/examples/django/django-utils-http-http-date.markdown @@ -0,0 +1,154 @@ +title: django.utils.http http_date Example Code +category: page +slug: django-utils-http-http-date-examples +sortorder: 500011470 +toc: False +sidebartitle: django.utils.http http_date +meta: Python example code for the http_date callable from the django.utils.http module of the Django project. + + +http_date is a callable within the django.utils.http module of the Django project. + + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / core / http.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/core/http.py) + +```python +# http.py +import mimetypes +import os +from datetime import datetime + +from django.http import HttpResponse +from django.utils import dateformat +from django.utils.encoding import filepath_to_uri +~~from django.utils.http import http_date +from wiki.conf import settings + + +def django_sendfile_response(request, filepath): + from sendfile import sendfile + + return sendfile(request, filepath) + + +def send_file(request, filepath, last_modified=None, filename=None): + fullpath = filepath + statobj = os.stat(fullpath) + if filename: + mimetype, encoding = mimetypes.guess_type(filename) + else: + mimetype, encoding = mimetypes.guess_type(fullpath) + + mimetype = mimetype or "application/octet-stream" + + if settings.USE_SENDFILE: + response = django_sendfile_response(request, filepath) + else: + response = HttpResponse(open(fullpath, "rb").read(), content_type=mimetype) + + if not last_modified: +~~ response["Last-Modified"] = http_date(statobj.st_mtime) + else: + if isinstance(last_modified, datetime): + last_modified = float(dateformat.format(last_modified, "U")) +~~ response["Last-Modified"] = http_date(epoch_seconds=last_modified) + + response["Content-Length"] = statobj.st_size + + if encoding: + response["Content-Encoding"] = encoding + + if filename: + filename_escaped = filepath_to_uri(filename) + if "pdf" in mimetype.lower(): + response["Content-Disposition"] = "inline; filename=%s" % filename_escaped + else: + response["Content-Disposition"] = ( + "attachment; filename=%s" % filename_escaped + ) + + return response + + + +## ... source file continues with no further http_date examples... + +``` + + +## Example 2 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / utils / sendfile_streaming_backend.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/utils/sendfile_streaming_backend.py) + +```python +# sendfile_streaming_backend.py + +import os +import re +import stat +from email.utils import mktime_tz, parsedate_tz +from wsgiref.util import FileWrapper + +from django.http import HttpResponseNotModified, StreamingHttpResponse +~~from django.utils.http import http_date + + +def sendfile(request, filename, **kwargs): + statobj = os.stat(filename) + + if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'), + statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]): + return HttpResponseNotModified() + + response = StreamingHttpResponse(FileWrapper(open(filename, 'rb'))) + +~~ response["Last-Modified"] = http_date(statobj[stat.ST_MTIME]) + return response + + +def was_modified_since(header=None, mtime=0, size=0): + try: + if header is None: + raise ValueError + matches = re.match(r"^([^;]+)(; length=([0-9]+))?$", header, + re.IGNORECASE) + header_date = parsedate_tz(matches.group(1)) + if header_date is None: + raise ValueError + header_mtime = mktime_tz(header_date) + header_len = matches.group(3) + if header_len and int(header_len) != size: + raise ValueError + if mtime > header_mtime: + raise ValueError + except (AttributeError, ValueError, OverflowError): + return True + return False + + + +## ... source file continues with no further http_date examples... + +``` + diff --git a/content/pages/examples/django/django-utils-http-int-to-base36.markdown b/content/pages/examples/django/django-utils-http-int-to-base36.markdown new file mode 100644 index 000000000..455d6fb47 --- /dev/null +++ b/content/pages/examples/django/django-utils-http-int-to-base36.markdown @@ -0,0 +1,106 @@ +title: django.utils.http int_to_base36 Example Code +category: page +slug: django-utils-http-int-to-base36-examples +sortorder: 500011471 +toc: False +sidebartitle: django.utils.http int_to_base36 +meta: Python example code for the int_to_base36 callable from the django.utils.http module of the Django project. + + +int_to_base36 is a callable within the django.utils.http module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / tests.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/./tests.py) + +```python +# tests.py +from __future__ import unicode_literals + +import json +import requests +from datetime import date, datetime + +import django +from django.core.files.base import ContentFile +from django.db import models +from django.test import RequestFactory, TestCase +~~from django.utils.http import base36_to_int, int_to_base36 +from django.views import csrf + +from . import utils + + +try: + from unittest.mock import Mock, patch +except ImportError: + from mock import Mock, patch # noqa + + +class MockedResponse(object): + def __init__(self, status_code, content, headers=None): + if headers is None: + headers = {} + + self.status_code = status_code + self.content = content.encode('utf8') + self.headers = headers + + def json(self): + return json.loads(self.text) + + def raise_for_status(self): + + +## ... source file abbreviated to get to int_to_base36 examples ... + + + + instance = SomeBinaryModel(bb=b'some binary data') + + serialized = utils.serialize_instance(instance) + deserialized = utils.deserialize_instance(SomeBinaryModel, serialized) + + self.assertEqual(serialized['bb'], 'c29tZSBiaW5hcnkgZGF0YQ==') + self.assertEqual(serialized['bb_empty'], '') + self.assertEqual(deserialized.bb, b'some binary data') + self.assertEqual(deserialized.bb_empty, b'') + + def test_build_absolute_uri(self): + self.assertEqual( + utils.build_absolute_uri(None, '/foo'), + 'http://example.com/foo') + self.assertEqual( + utils.build_absolute_uri(None, '/foo', protocol='ftp'), + 'ftp://example.com/foo') + self.assertEqual( + utils.build_absolute_uri(None, 'http://foo.com/bar'), + 'http://foo.com/bar') + + def test_int_to_base36(self): + n = 55798679658823689999 + b36 = 'brxk553wvxbf3' +~~ assert int_to_base36(n) == b36 + assert base36_to_int(b36) == n + + def test_templatetag_with_csrf_failure(self): + request = self.factory.get('/tests/test_403_csrf.html') + response = csrf.csrf_failure( + request, + template_name='tests/test_403_csrf.html' + ) + self.assertEqual(response.status_code, 403) + + + +## ... source file continues with no further int_to_base36 examples... + +``` + diff --git a/content/pages/examples/django/django-utils-http-is-safe-url.markdown b/content/pages/examples/django/django-utils-http-is-safe-url.markdown new file mode 100644 index 000000000..5f21e019a --- /dev/null +++ b/content/pages/examples/django/django-utils-http-is-safe-url.markdown @@ -0,0 +1,106 @@ +title: django.utils.http is_safe_url Example Code +category: page +slug: django-utils-http-is-safe-url-examples +sortorder: 500011472 +toc: False +sidebartitle: django.utils.http is_safe_url +meta: Python example code for the is_safe_url callable from the django.utils.http module of the Django project. + + +is_safe_url is a callable within the django.utils.http module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / views.py**](https://github.com/divio/django-cms/blob/develop/cms/./views.py) + +```python +# views.py + +from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login +from django.contrib.auth.views import redirect_to_login +from django.http import HttpResponse, HttpResponseRedirect +from django.urls import reverse +from django.utils.cache import patch_cache_control +~~from django.utils.http import is_safe_url, urlquote +from django.utils.timezone import now +from django.utils.translation import get_language_from_request +from django.views.decorators.http import require_POST + +from cms.cache.page import get_page_cache +from cms.exceptions import LanguageError +from cms.forms.login import CMSToolbarLoginForm +from cms.models.pagemodel import TreeNode +from cms.page_rendering import _handle_no_page, render_page, render_object_structure, _render_welcome_page +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils import get_current_site +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import (get_fallback_languages, get_public_languages, + get_redirect_on_fallback, get_language_list, + get_default_language_for_site, + is_language_prefix_patterns_used) +from cms.utils.page import get_page_from_request +from cms.utils.page_permissions import user_can_change_page + + +def _clean_redirect_url(redirect_url, language): + if (redirect_url and is_language_prefix_patterns_used() and redirect_url[0] == "/" + and not redirect_url.startswith('/%s/' % language)): + redirect_url = "/%s/%s" % (language, redirect_url.lstrip("/")) + + +## ... source file abbreviated to get to is_safe_url examples ... + + + redirect_url = _clean_redirect_url(redirect_url, request_language) + + if redirect_url: + if request.user.is_staff and toolbar.edit_mode_active: + toolbar.redirect_url = redirect_url + elif redirect_url not in own_urls: + return HttpResponseRedirect(redirect_url) + + if page.login_required and not request.user.is_authenticated: + return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) + + if hasattr(request, 'toolbar'): + request.toolbar.set_object(page) + + structure_requested = get_cms_setting('CMS_TOOLBAR_URL__BUILD') in request.GET + + if user_can_change_page(request.user, page) and structure_requested: + return render_object_structure(request, page) + return render_page(request, page, current_language=request_language, slug=slug) + + +@require_POST +def login(request): + redirect_to = request.GET.get(REDIRECT_FIELD_NAME) + +~~ if not is_safe_url(url=redirect_to, allowed_hosts=request.get_host()): + redirect_to = reverse("pages-root") + + if request.user.is_authenticated: + return HttpResponseRedirect(redirect_to) + + form = CMSToolbarLoginForm(request=request, data=request.POST) + + if form.is_valid(): + auth_login(request, form.user_cache) + else: + redirect_to += u'?cms_toolbar_login_error=1' + return HttpResponseRedirect(redirect_to) + + + +## ... source file continues with no further is_safe_url examples... + +``` + diff --git a/content/pages/examples/django/django-utils-http-unquote.markdown b/content/pages/examples/django/django-utils-http-unquote.markdown new file mode 100644 index 000000000..e493f3868 --- /dev/null +++ b/content/pages/examples/django/django-utils-http-unquote.markdown @@ -0,0 +1,68 @@ +title: django.utils.http unquote Example Code +category: page +slug: django-utils-http-unquote-examples +sortorder: 500011473 +toc: False +sidebartitle: django.utils.http unquote +meta: Python example code for the unquote callable from the django.utils.http module of the Django project. + + +unquote is a callable within the django.utils.http module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / middleware.py**](https://github.com/jrief/django-angular/blob/master/djng/./middleware.py) + +```python +# middleware.py +from django import http +from django.urls import reverse +~~from django.utils.http import unquote +try: + from django.utils.deprecation import MiddlewareMixin +except ImportError: + MiddlewareMixin = object + + +class AngularUrlMiddleware(MiddlewareMixin): + ANGULAR_REVERSE = '/angular/reverse/' + + def process_request(self, request): + if request.path == self.ANGULAR_REVERSE: + url_name = request.GET.get('djng_url_name') + url_args = request.GET.getlist('djng_url_args', []) + url_kwargs = {} + + url_args = filter(lambda x: x, url_args) + + for param in request.GET: + if param.startswith('djng_url_kwarg_'): + if request.GET[param]: + url_kwargs[param[15:]] = request.GET[param] # [15:] to remove 'djng_url_kwarg' prefix + +~~ url = unquote(reverse(url_name, args=url_args, kwargs=url_kwargs)) + assert not url.startswith(self.ANGULAR_REVERSE), "Prevent recursive requests" + + request.path = request.path_info = url + request.environ['PATH_INFO'] = url + query = request.GET.copy() + for key in request.GET: + if key.startswith('djng_url'): + query.pop(key, None) + request.environ['QUERY_STRING'] = query.urlencode() + + request.GET = http.QueryDict(request.environ['QUERY_STRING']) + + + +## ... source file continues with no further unquote examples... + +``` + diff --git a/content/pages/examples/django/django-utils-http-url-has-allowed-host-and-scheme.markdown b/content/pages/examples/django/django-utils-http-url-has-allowed-host-and-scheme.markdown new file mode 100644 index 000000000..73992bedc --- /dev/null +++ b/content/pages/examples/django/django-utils-http-url-has-allowed-host-and-scheme.markdown @@ -0,0 +1,125 @@ +title: django.utils.http url_has_allowed_host_and_scheme Example Code +category: page +slug: django-utils-http-url-has-allowed-host-and-scheme-examples +sortorder: 500011474 +toc: False +sidebartitle: django.utils.http url_has_allowed_host_and_scheme +meta: Python example code for the url_has_allowed_host_and_scheme callable from the django.utils.http module of the Django project. + + +url_has_allowed_host_and_scheme is a callable within the django.utils.http module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / adapter.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/adapter.py) + +```python +# adapter.py +from __future__ import unicode_literals + +import hashlib +import json +import time +import warnings + +from django import forms +from django.conf import settings +from django.contrib import messages +from django.contrib.auth import ( + authenticate, + get_backends, + login as django_login, + logout as django_logout, +) +from django.contrib.auth.models import AbstractUser +from django.contrib.auth.password_validation import validate_password +from django.contrib.sites.shortcuts import get_current_site +from django.core.cache import cache +from django.core.mail import EmailMessage, EmailMultiAlternatives +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import resolve_url +from django.template import TemplateDoesNotExist +from django.template.loader import render_to_string +from django.urls import reverse +from django.utils import timezone +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +from ..utils import ( + build_absolute_uri, + email_address_exists, + generate_unique_username, + get_user_model, + + +## ... source file abbreviated to get to url_has_allowed_host_and_scheme examples ... + + + backend_path = '.'.join([backend.__module__, + backend.__class__.__name__]) + user.backend = backend_path + django_login(request, user) + + def logout(self, request): + django_logout(request) + + def confirm_email(self, request, email_address): + email_address.verified = True + email_address.set_as_primary(conditional=True) + email_address.save() + + def set_password(self, user, password): + user.set_password(password) + user.save() + + def get_user_search_fields(self): + user = get_user_model()() + return filter(lambda a: a and hasattr(user, a), + [app_settings.USER_MODEL_USERNAME_FIELD, + 'first_name', 'last_name', 'email']) + + def is_safe_url(self, url): + try: +~~ from django.utils.http import url_has_allowed_host_and_scheme + except ImportError: + from django.utils.http import \ + is_safe_url as url_has_allowed_host_and_scheme + +~~ return url_has_allowed_host_and_scheme(url, allowed_hosts=None) + + def get_email_confirmation_url(self, request, emailconfirmation): + url = reverse( + "account_confirm_email", + args=[emailconfirmation.key]) + ret = build_absolute_uri( + request, + url) + return ret + + def send_confirmation_mail(self, request, emailconfirmation, signup): + current_site = get_current_site(request) + activate_url = self.get_email_confirmation_url( + request, + emailconfirmation) + ctx = { + "user": emailconfirmation.email_address.user, + "activate_url": activate_url, + "current_site": current_site, + "key": emailconfirmation.key, + } + if signup: + email_template = 'account/email/email_confirmation_signup' + else: + + +## ... source file continues with no further url_has_allowed_host_and_scheme examples... + +``` + diff --git a/content/pages/examples/django/django-utils-http-urlencode.markdown b/content/pages/examples/django/django-utils-http-urlencode.markdown new file mode 100644 index 000000000..d837e19bc --- /dev/null +++ b/content/pages/examples/django/django-utils-http-urlencode.markdown @@ -0,0 +1,733 @@ +title: django.utils.http urlencode Example Code +category: page +slug: django-utils-http-urlencode-examples +sortorder: 500011475 +toc: False +sidebartitle: django.utils.http urlencode +meta: Python example code for the urlencode callable from the django.utils.http module of the Django project. + + +urlencode is a callable within the django.utils.http module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / utils.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/utils.py) + +```python +# utils.py +import unicodedata +from collections import OrderedDict +from datetime import timedelta + +from django.conf import settings +from django.contrib import messages +from django.contrib.auth import update_session_auth_hash +from django.core.exceptions import FieldDoesNotExist, ValidationError +from django.db import models +from django.db.models import Q +from django.http import HttpResponseRedirect +from django.utils.encoding import force_str +~~from django.utils.http import base36_to_int, int_to_base36, urlencode +from django.utils.timezone import now + +from ..exceptions import ImmediateHttpResponse +from ..utils import ( + get_request_param, + get_user_model, + import_callable, + valid_email_or_none, +) +from . import app_settings, signals +from .adapter import get_adapter +from .app_settings import EmailVerificationMethod + + +def _unicode_ci_compare(s1, s2): + norm_s1 = unicodedata.normalize('NFKC', s1).casefold() + norm_s2 = unicodedata.normalize('NFKC', s2).casefold() + return norm_s1 == norm_s2 + + +def get_next_redirect_url(request, redirect_field_name="next"): + redirect_to = get_request_param(request, redirect_field_name) + if not get_adapter(request).is_safe_url(redirect_to): + redirect_to = None + + +## ... source file abbreviated to get to urlencode examples ... + + + from .models import EmailAddress + User = get_user_model() + mails = EmailAddress.objects.filter(email__iexact=email) + if is_active is not None: + mails = mails.filter(user__is_active=is_active) + users = [] + for e in mails.prefetch_related('user'): + if _unicode_ci_compare(e.email, email): + users.append(e.user) + if app_settings.USER_MODEL_EMAIL_FIELD: + q_dict = {app_settings.USER_MODEL_EMAIL_FIELD + '__iexact': email} + user_qs = User.objects.filter(**q_dict) + if is_active is not None: + user_qs = user_qs.filter(is_active=is_active) + for user in user_qs.iterator(): + user_email = getattr(user, app_settings.USER_MODEL_EMAIL_FIELD) + if _unicode_ci_compare(user_email, email): + users.append(user) + return list(set(users)) + + +def passthrough_next_redirect_url(request, url, redirect_field_name): + assert url.find("?") < 0 # TODO: Handle this case properly + next_url = get_next_redirect_url(request, redirect_field_name) + if next_url: +~~ url = url + '?' + urlencode({redirect_field_name: next_url}) + return url + + +def user_pk_to_url_str(user): + User = get_user_model() + if issubclass(type(User._meta.pk), models.UUIDField): + if isinstance(user.pk, str): + return user.pk + return user.pk.hex + + ret = user.pk + if isinstance(ret, int): + ret = int_to_base36(user.pk) + return str(ret) + + +def url_str_to_user_pk(s): + User = get_user_model() + if getattr(User._meta.pk, 'remote_field', None): + pk_field = User._meta.pk.remote_field.to._meta.pk + else: + pk_field = User._meta.pk + if issubclass(type(pk_field), models.UUIDField): + return pk_field.to_python(s) + + +## ... source file continues with no further urlencode examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / templatetags / cms_tags.py**](https://github.com/divio/django-cms/blob/develop/cms/templatetags/cms_tags.py) + +```python +# cms_tags.py +from collections import namedtuple, OrderedDict +from copy import copy +from datetime import datetime + +from django import template +from django.conf import settings +from django.contrib.sites.models import Site +from django.core.mail import mail_managers +from django.db.models import Model +from django.middleware.common import BrokenLinkEmailsMiddleware +from django.template.loader import render_to_string +from django.urls import reverse +from django.utils.encoding import force_text, smart_text +from django.utils.html import escape +~~from django.utils.http import urlencode +from django.utils.translation import ( + get_language, + override as force_language, + ugettext_lazy as _, +) + +from six import string_types, integer_types + +from classytags.arguments import (Argument, MultiValueArgument, + MultiKeywordArgument) +from classytags.core import Options, Tag +from classytags.helpers import InclusionTag, AsTag +from classytags.parser import Parser +from classytags.utils import flatten_context +from classytags.values import ListValue, StringValue + +from cms.cache.page import get_page_url_cache, set_page_url_cache +from cms.exceptions import PlaceholderNotFound +from cms.models import Page, Placeholder as PlaceholderModel, CMSPlugin, StaticPlaceholder +from cms.plugin_pool import plugin_pool +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils import get_current_site, get_language_from_request, get_site_id +from cms.utils.compat.dj import get_middleware +from cms.utils.moderator import use_draft + + +## ... source file abbreviated to get to urlencode examples ... + + + else: + url_base = method + else: + if not editmode: + view_url = 'admin:%s_%s_add' % ( + opts.app_label, opts.model_name) + url_base = reverse(view_url) + elif not edit_fields: + if not view_url: + view_url = 'admin:%s_%s_change' % ( + opts.app_label, opts.model_name) + if isinstance(instance, Page): + url_base = reverse(view_url, args=(instance.pk, language)) + else: + url_base = reverse(view_url, args=(instance.pk,)) + else: + if not view_url: + view_url = 'admin:%s_%s_edit_field' % ( + opts.app_label, opts.model_name) + if view_url.endswith('_changelist'): + url_base = reverse(view_url) + else: + url_base = reverse(view_url, args=(instance.pk, language)) + querystring['edit_fields'] = ",".join(context['edit_fields']) + if editmode: +~~ extra_context['edit_url'] = "%s?%s" % (url_base, urlencode(querystring)) + else: + extra_context['edit_url'] = "%s" % url_base + extra_context['refresh_page'] = True + if getattr(context['request'], 'current_page', None): + extra_context['redirect_on_close'] = context['request'].current_page.get_absolute_url(language) + else: + extra_context['redirect_on_close'] = '' + return extra_context + + def _get_content(self, context, instance, attribute, language, filters): + extra_context = copy(context) + attr_value = None + if hasattr(instance, 'lazy_translation_getter'): + attr_value = instance.lazy_translation_getter(attribute, '') + if not attr_value: + attr_value = getattr(instance, attribute, '') + extra_context['content'] = attr_value + if callable(extra_context['content']): + if isinstance(instance, Page): + extra_context['content'] = extra_context['content'](language) + else: + extra_context['content'] = extra_context['content'](context['request']) + if filters: + expression = self.parser.compile_filter("content|%s" % (filters)) + + +## ... source file continues with no further urlencode examples... + +``` + + +## Example 3 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / tools.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/tools.py) + +```python +# tools.py +from __future__ import absolute_import, unicode_literals + +from django.contrib.admin.options import IS_POPUP_VAR +from django.core.exceptions import PermissionDenied +~~from django.utils.http import urlencode + + +ALLOWED_PICK_TYPES = ('folder', 'file') + + +def check_files_edit_permissions(request, files): + for f in files: + if not f.has_edit_permission(request): + raise PermissionDenied + + +def check_folder_edit_permissions(request, folders): + for f in folders: + if not f.has_edit_permission(request): + raise PermissionDenied + check_files_edit_permissions(request, f.files) + check_folder_edit_permissions(request, f.children.all()) + + +def check_files_read_permissions(request, files): + for f in files: + if not f.has_read_permission(request): + raise PermissionDenied + + + +## ... source file abbreviated to get to urlencode examples ... + + + IS_POPUP_VAR in request.GET + or 'pop' in request.GET + or IS_POPUP_VAR in request.POST + or 'pop' in request.POST + ) + + +def popup_pick_type(request): + pick_type = request.GET.get('_pick', request.POST.get('_pick')) + if pick_type in ALLOWED_PICK_TYPES: + return pick_type + return None + + +def admin_url_params(request, params=None): + params = params or {} + if popup_status(request): + params[IS_POPUP_VAR] = '1' + pick_type = popup_pick_type(request) + if pick_type: + params['_pick'] = pick_type + return params + + +def admin_url_params_encoded(request, first_separator='?', params=None): +~~ params = urlencode( + sorted(admin_url_params(request, params=params).items()) + ) + if not params: + return '' + return '{0}{1}'.format(first_separator, params) + + +class AdminContext(dict): + def __init__(self, request): + super(AdminContext, self).__init__() + self.update(admin_url_params(request)) + + def __missing__(self, key): + if key == 'popup': + return self.get(IS_POPUP_VAR, False) == '1' + elif key == 'pick': + return self.get('_pick', '') + elif key.startswith('pick_'): + return self.get('_pick', '') == key.split('pick_')[1] + + def __getattr__(self, name): + if name in ('popup', 'pick') or name.startswith('pick_'): + return self.get(name) + raise AttributeError + + +## ... source file continues with no further urlencode examples... + +``` + + +## Example 4 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / widgets.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./widgets.py) + +```python +# widgets.py +from collections.abc import Iterable +from copy import deepcopy +from itertools import chain +from re import search, sub + +from django import forms +from django.db.models.fields import BLANK_CHOICE_DASH +from django.forms.utils import flatatt +from django.utils.datastructures import MultiValueDict +from django.utils.encoding import force_str +~~from django.utils.http import urlencode +from django.utils.safestring import mark_safe +from django.utils.translation import gettext as _ + + +class LinkWidget(forms.Widget): + def __init__(self, attrs=None, choices=()): + super().__init__(attrs) + + self.choices = choices + + def value_from_datadict(self, data, files, name): + value = super().value_from_datadict(data, files, name) + self.data = data + return value + + def render(self, name, value, attrs=None, choices=(), renderer=None): + if not hasattr(self, 'data'): + self.data = {} + if value is None: + value = '' + final_attrs = self.build_attrs(self.attrs, extra_attrs=attrs) + output = ['' % flatatt(final_attrs)] + options = self.render_options(choices, [value], name) + if options: + + +## ... source file abbreviated to get to urlencode examples ... + + + def render_options(self, choices, selected_choices, name): + selected_choices = set(force_str(v) for v in selected_choices) + output = [] + for option_value, option_label in chain(self.choices, choices): + if isinstance(option_label, (list, tuple)): + for option in option_label: + output.append( + self.render_option(name, selected_choices, *option)) + else: + output.append( + self.render_option(name, selected_choices, + option_value, option_label)) + return '\n'.join(output) + + def render_option(self, name, selected_choices, + option_value, option_label): + option_value = force_str(option_value) + if option_label == BLANK_CHOICE_DASH[0][1]: + option_label = _("All") + data = self.data.copy() + data[name] = option_value + selected = data == self.data or option_value in selected_choices + try: + url = data.urlencode() + except AttributeError: +~~ url = urlencode(data) + return self.option_string() % { + 'attrs': selected and ' class="selected"' or '', + 'query_string': url, + 'label': force_str(option_label) + } + + def option_string(self): + return '
  • %(label)s
  • ' + + +class SuffixedMultiWidget(forms.MultiWidget): + suffixes = [] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + assert len(self.widgets) == len(self.suffixes) + assert len(self.suffixes) == len(set(self.suffixes)) + + def suffixed(self, name, suffix): + return '_'.join([name, suffix]) if suffix else name + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + + +## ... source file continues with no further urlencode examples... + +``` + + +## Example 5 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / test.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./test.py) + +```python +# test.py +import io +from importlib import import_module + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.core.handlers.wsgi import WSGIHandler +from django.test import override_settings, testcases +from django.test.client import Client as DjangoClient +from django.test.client import ClientHandler +from django.test.client import RequestFactory as DjangoRequestFactory +from django.utils.encoding import force_bytes +~~from django.utils.http import urlencode + +from rest_framework.compat import coreapi, requests +from rest_framework.settings import api_settings + + +def force_authenticate(request, user=None, token=None): + request._force_auth_user = user + request._force_auth_token = token + + +if requests is not None: + class HeaderDict(requests.packages.urllib3._collections.HTTPHeaderDict): + def get_all(self, key, default): + return self.getheaders(key) + + class MockOriginalResponse: + def __init__(self, headers): + self.msg = HeaderDict(headers) + self.closed = False + + def isclosed(self): + return self.closed + + def close(self): + + +## ... source file abbreviated to get to urlencode examples ... + + + format = format or self.default_format + + assert format in self.renderer_classes, ( + "Invalid format '{}'. Available formats are {}. " + "Set TEST_REQUEST_RENDERER_CLASSES to enable " + "extra request formats.".format( + format, + ', '.join(["'" + fmt + "'" for fmt in self.renderer_classes]) + ) + ) + + renderer = self.renderer_classes[format]() + ret = renderer.render(data) + + content_type = "{}; charset={}".format( + renderer.media_type, renderer.charset + ) + + if isinstance(ret, str): + ret = ret.encode(renderer.charset) + + return ret, content_type + + def get(self, path, data=None, **extra): + r = { +~~ 'QUERY_STRING': urlencode(data or {}, doseq=True), + } + if not data and '?' in path: + query_string = force_bytes(path.split('?')[1]) + query_string = query_string.decode('iso-8859-1') + r['QUERY_STRING'] = query_string + r.update(extra) + return self.generic('GET', path, **r) + + def post(self, path, data=None, format=None, content_type=None, **extra): + data, content_type = self._encode_data(data, format, content_type) + return self.generic('POST', path, data, content_type, **extra) + + def put(self, path, data=None, format=None, content_type=None, **extra): + data, content_type = self._encode_data(data, format, content_type) + return self.generic('PUT', path, data, content_type, **extra) + + def patch(self, path, data=None, format=None, content_type=None, **extra): + data, content_type = self._encode_data(data, format, content_type) + return self.generic('PATCH', path, data, content_type, **extra) + + def delete(self, path, data=None, format=None, content_type=None, **extra): + data, content_type = self._encode_data(data, format, content_type) + return self.generic('DELETE', path, data, content_type, **extra) + + + +## ... source file continues with no further urlencode examples... + +``` + + +## Example 6 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / templatetags / django_tables2.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/templatetags/django_tables2.py) + +```python +# django_tables2.py +import re +from collections import OrderedDict + +from django import template +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.template import Node, TemplateSyntaxError +from django.template.loader import get_template, select_template +from django.templatetags.l10n import register as l10n_register +from django.utils.html import escape +~~from django.utils.http import urlencode + +import django_tables2 as tables +from django_tables2.paginators import LazyPaginator +from django_tables2.utils import AttributeDict + +register = template.Library() +kwarg_re = re.compile(r"(?:(.+)=)?(.+)") +context_processor_error_msg = ( + "Tag {%% %s %%} requires django.template.context_processors.request to be " + "in the template configuration in " + "settings.TEMPLATES[]OPTIONS.context_processors) in order for the included " + "template tags to function correctly." +) + + +def token_kwargs(bits, parser): + if not bits: + return {} + kwargs = OrderedDict() + while bits: + match = kwarg_re.match(bits[0]) + if not match or not match.group(1): + return kwargs + key, value = match.groups() + + +## ... source file abbreviated to get to urlencode examples ... + + + + +class QuerystringNode(Node): + def __init__(self, updates, removals, asvar=None): + super().__init__() + self.updates = updates + self.removals = removals + self.asvar = asvar + + def render(self, context): + if "request" not in context: + raise ImproperlyConfigured(context_processor_error_msg % "querystring") + + params = dict(context["request"].GET) + for key, value in self.updates.items(): + if isinstance(key, str): + params[key] = value + continue + key = key.resolve(context) + value = value.resolve(context) + if key not in ("", None): + params[key] = value + for removal in self.removals: + params.pop(removal.resolve(context), None) + +~~ value = escape("?" + urlencode(params, doseq=True)) + + if self.asvar: + context[str(self.asvar)] = value + return "" + else: + return value + + +@register.tag +def querystring(parser, token): + bits = token.split_contents() + tag = bits.pop(0) + updates = token_kwargs(bits, parser) + + asvar_key = None + for key in updates: + if str(key) == "as": + asvar_key = key + + if asvar_key is not None: + asvar = updates[asvar_key] + del updates[asvar_key] + else: + asvar = None + + +## ... source file continues with no further urlencode examples... + +``` + + +## Example 7 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / users / utils.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/users/utils.py) + +```python +# utils.py +import hashlib +from django.conf import settings +~~from django.utils.http import urlencode + +from wagtail.core.compat import AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME + +delete_user_perm = "{0}.delete_{1}".format(AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME.lower()) + + +def user_can_delete_user(current_user, user_to_delete): + if not current_user.has_perm(delete_user_perm): + return False + + if current_user == user_to_delete: + return False + + if user_to_delete.is_superuser and not current_user.is_superuser: + return False + + return True + + +def get_gravatar_url(email, size=50): + default = "mm" + size = int(size) * 2 # requested at retina size by default and scaled down at point of use with css + gravatar_provider_url = getattr(settings, 'WAGTAIL_GRAVATAR_PROVIDER_URL', '//www.gravatar.com/avatar') + + if (not email) or (gravatar_provider_url is None): + return None + + gravatar_url = "{gravatar_provider_url}/{hash}?{params}".format( + gravatar_provider_url=gravatar_provider_url.rstrip('/'), + hash=hashlib.md5(email.lower().encode('utf-8')).hexdigest(), +~~ params=urlencode({'s': size, 'd': default}) + ) + + return gravatar_url + + + +## ... source file continues with no further urlencode examples... + +``` + diff --git a/content/pages/examples/django/django-utils-http-urlquote.markdown b/content/pages/examples/django/django-utils-http-urlquote.markdown new file mode 100644 index 000000000..990e82a0a --- /dev/null +++ b/content/pages/examples/django/django-utils-http-urlquote.markdown @@ -0,0 +1,413 @@ +title: django.utils.http urlquote Example Code +category: page +slug: django-utils-http-urlquote-examples +sortorder: 500011476 +toc: False +sidebartitle: django.utils.http urlquote +meta: Python example code for the urlquote callable from the django.utils.http module of the Django project. + + +urlquote is a callable within the django.utils.http module of the Django project. + + +## Example 1 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / folderadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/folderadmin.py) + +```python +# folderadmin.py +from __future__ import absolute_import, division, unicode_literals + +import itertools +import os +import re +from collections import OrderedDict + +from django import forms +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import messages +from django.contrib.admin import helpers +from django.contrib.admin.utils import capfirst, quote, unquote +from django.core.exceptions import PermissionDenied, ValidationError +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db import models, router +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils.encoding import force_text +from django.utils.html import escape +~~from django.utils.http import urlquote, urlunquote +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy, ungettext + +from .. import settings +from ..models import ( + File, Folder, FolderPermission, FolderRoot, ImagesWithMissingData, + UnsortedImages, tools, +) +from ..settings import FILER_IMAGE_MODEL, FILER_PAGINATE_BY +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import get_delete_permission +from ..utils.filer_easy_thumbnails import FilerActionThumbnailer +from ..utils.loader import load_model +from . import views +from .forms import CopyFilesAndFoldersForm, RenameFilesForm, ResizeImagesForm +from .patched.admin_utils import get_deleted_objects +from .permissions import PrimitivePermissionAwareModelAdmin +from .tools import ( + AdminContext, admin_url_params_encoded, check_files_edit_permissions, + check_files_read_permissions, check_folder_edit_permissions, + check_folder_read_permissions, popup_status, userperms_for_request, +) + + + +## ... source file abbreviated to get to urlquote examples ... + + + selection_note_all = ungettext('%(total_count)s selected', + 'All %(total_count)s selected', paginator.count) + + try: + paginated_items = paginator.page(request.GET.get('page', 1)) + except PageNotAnInteger: + paginated_items = paginator.page(1) + except EmptyPage: + paginated_items = paginator.page(paginator.num_pages) + + context = self.admin_site.each_context(request) + context.update({ + 'folder': folder, + 'clipboard_files': File.objects.filter( + in_clipboards__clipboarditem__clipboard__user=request.user + ).distinct(), + 'paginator': paginator, + 'paginated_items': paginated_items, + 'virtual_items': virtual_items, + 'uploader_connections': settings.FILER_UPLOADER_CONNECTIONS, + 'permissions': permissions, + 'permstest': userperms_for_request(folder, request), + 'current_url': request.path, + 'title': _('Directory listing for %(folder_name)s') % {'folder_name': folder.name}, + 'search_string': ' '.join(search_terms), +~~ 'q': urlquote(q), + 'show_result_count': show_result_count, + 'folder_children': folder_children, + 'folder_files': folder_files, + 'limit_search_to_folder': limit_search_to_folder, + 'is_popup': popup_status(request), + 'filer_admin_context': AdminContext(request), + 'root_path': reverse('admin:index'), + 'action_form': action_form, + 'actions_on_top': self.actions_on_top, + 'actions_on_bottom': self.actions_on_bottom, + 'actions_selection_counter': self.actions_selection_counter, + 'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(paginated_items.object_list)}, + 'selection_note_all': selection_note_all % {'total_count': paginator.count}, + 'media': self.media, + 'enable_permissions': settings.FILER_ENABLE_PERMISSIONS, + 'can_make_folder': request.user.is_superuser or (folder.is_root and settings.FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS) or permissions.get("has_add_children_permission"), + }) + return render(request, self.directory_listing_template, context) + + def filter_folder(self, qs, terms=()): + def construct_search(field_name): + if field_name.startswith('^'): + return "%s__istartswith" % field_name[1:] + elif field_name.startswith('='): + + +## ... source file continues with no further urlquote examples... + +``` + + +## Example 2 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / sitetreeapp.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./sitetreeapp.py) + +```python +# sitetreeapp.py +import warnings +from collections import defaultdict +from copy import deepcopy +from inspect import getfullargspec +from sys import exc_info +from threading import local +from typing import Callable, List, Optional, Dict, Union, Sequence, Any, Tuple + +from django.conf import settings +from django.core.cache import cache +from django.db.models import signals, QuerySet +from django.template.base import ( + FilterExpression, Lexer, Parser, Token, Variable, VariableDoesNotExist, VARIABLE_TAG_START, Context) +from django.template.defaulttags import url as url_tag +from django.template.loader import get_template +from django.utils import module_loading +~~from django.utils.http import urlquote +from django.utils.translation import get_language + +from .compat import TOKEN_BLOCK, TOKEN_TEXT, TOKEN_VAR +from .exceptions import SiteTreeError +from .settings import ( + ALIAS_TRUNK, ALIAS_THIS_CHILDREN, ALIAS_THIS_SIBLINGS, ALIAS_THIS_PARENT_SIBLINGS, ALIAS_THIS_ANCESTOR_CHILDREN, + UNRESOLVED_ITEM_MARKER, RAISE_ITEMS_ERRORS_ON_DEBUG, CACHE_TIMEOUT, DYNAMIC_ONLY, ADMIN_APP_NAME, SITETREE_CLS) +from .utils import get_tree_model, get_tree_item_model, import_app_sitetree_module, generate_id_for + +if False: # pragma: nocover + from django.contrib.auth.models import User # noqa + from .models import TreeItemBase, TreeBase + +TypeDynamicTrees = Dict[str, Union[Dict[str, List['TreeBase']], List['TreeBase']]] + +MODEL_TREE_CLASS = get_tree_model() +MODEL_TREE_ITEM_CLASS = get_tree_item_model() + + +_ITEMS_PROCESSOR: Optional[Callable] = None + +_ITEMS_PROCESSOR_ARGS_LEN: int = 0 + +_I18N_TREES: List[str] = [] + + +## ... source file abbreviated to get to urlquote examples ... + + + return depth + + def get_item_by_id(self, tree_alias: str, item_id: int) -> 'TreeItemBase': + return self.cache.get_entry('items_by_ids', tree_alias)[item_id] + + def get_tree_current_item(self, tree_alias: str) -> Optional['TreeItemBase']: + current_item = self._current_items.get(tree_alias, _UNSET) + + if current_item is not _UNSET: + + if current_item is not None: + current_item.is_current = True # Could be reset by .get_sitetree() + + return current_item # noqa + + current_item = None + + if self.current_app_is_admin(): + self._current_items[tree_alias] = current_item + return None + + current_url = self.current_request.path + if isinstance(current_url, str): + current_url = current_url.encode('UTF-8') + if current_url: +~~ current_url = urlquote(current_url) + + for url_item, url in self._items_urls.items(): + if url != current_url: + continue + + url_item.is_current = True + if url_item.tree.alias == tree_alias: + current_item = url_item + + if current_item is not None: + self._current_items[tree_alias] = current_item + + return current_item + + def url(self, sitetree_item: Union['TreeItemBase', FilterExpression], context: Context = None) -> str: + context = context or self.current_page_context + resolve_var = self.resolve_var + + if not isinstance(sitetree_item, MODEL_TREE_ITEM_CLASS): + sitetree_item = resolve_var(sitetree_item, context) + + resolved_url = self._items_urls.get(sitetree_item) + if resolved_url is not None: + return resolved_url + + +## ... source file continues with no further urlquote examples... + +``` + + +## Example 3 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / decorators.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./decorators.py) + +```python +# decorators.py +from functools import wraps + +from django.http import HttpResponseForbidden +from django.http import HttpResponseNotFound +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.template.loader import render_to_string +from django.urls import reverse +~~from django.utils.http import urlquote +from wiki.conf import settings +from wiki.core.exceptions import NoRootURL + + +def response_forbidden(request, article, urlpath, read_denied=False): + if request.user.is_anonymous: + qs = request.META.get("QUERY_STRING", "") + if qs: +~~ qs = urlquote("?" + qs) + else: + qs = "" + return redirect(settings.LOGIN_URL + "?next=" + request.path + qs) + else: + return HttpResponseForbidden( + render_to_string( + "wiki/permission_denied.html", + context={ + "article": article, + "urlpath": urlpath, + "read_denied": read_denied, + }, + request=request, + ) + ) + + +def get_article( # noqa: max-complexity=23 + func=None, + can_read=True, + can_write=False, + deleted_contents=False, + not_locked=False, + can_delete=False, + + +## ... source file continues with no further urlquote examples... + +``` + + +## Example 4 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / utils / sendfile.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/utils/sendfile.py) + +```python +# sendfile.py +import os.path +from mimetypes import guess_type + +VERSION = (0, 3, 6) +__version__ = '.'.join(map(str, VERSION)) + + +def _lazy_load(fn): + _cached = [] + + def _decorated(): + if not _cached: + _cached.append(fn()) + return _cached[0] + + def clear(): + while _cached: + _cached.pop() + _decorated.clear = clear + return _decorated + + +@_lazy_load +def _get_sendfile(): + from importlib import import_module + from django.conf import settings + from django.core.exceptions import ImproperlyConfigured + + backend = getattr(settings, 'SENDFILE_BACKEND', None) + if not backend: + raise ImproperlyConfigured('You must specify a value for SENDFILE_BACKEND') + module = import_module(backend) + return module.sendfile + + + + +## ... source file abbreviated to get to urlquote examples ... + + + _sendfile = backend or _get_sendfile() + + if not os.path.exists(filename): + from django.http import Http404 + raise Http404('"%s" does not exist' % filename) + + guessed_mimetype, guessed_encoding = guess_type(filename) + if mimetype is None: + if guessed_mimetype: + mimetype = guessed_mimetype + else: + mimetype = 'application/octet-stream' + + response = _sendfile(request, filename, mimetype=mimetype) + if attachment: + if attachment_filename is None: + attachment_filename = os.path.basename(filename) + parts = ['attachment'] + if attachment_filename: + from unidecode import unidecode + from django.utils.encoding import force_str + attachment_filename = force_str(attachment_filename) + ascii_filename = unidecode(attachment_filename) + parts.append('filename="%s"' % ascii_filename) + if ascii_filename != attachment_filename: +~~ from django.utils.http import urlquote +~~ quoted_filename = urlquote(attachment_filename) + parts.append('filename*=UTF-8\'\'%s' % quoted_filename) + response['Content-Disposition'] = '; '.join(parts) + + response['Content-length'] = os.path.getsize(filename) + response['Content-Type'] = mimetype + response['Content-Encoding'] = encoding or guessed_encoding + + return response + + + +## ... source file continues with no further urlquote examples... + +``` + diff --git a/content/pages/examples/django/django-utils-http-urlunquote.markdown b/content/pages/examples/django/django-utils-http-urlunquote.markdown new file mode 100644 index 000000000..8f4cc418b --- /dev/null +++ b/content/pages/examples/django/django-utils-http-urlunquote.markdown @@ -0,0 +1,130 @@ +title: django.utils.http urlunquote Example Code +category: page +slug: django-utils-http-urlunquote-examples +sortorder: 500011477 +toc: False +sidebartitle: django.utils.http urlunquote +meta: Python example code for the urlunquote callable from the django.utils.http module of the Django project. + + +urlunquote is a callable within the django.utils.http module of the Django project. + + +## Example 1 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / folderadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/folderadmin.py) + +```python +# folderadmin.py +from __future__ import absolute_import, division, unicode_literals + +import itertools +import os +import re +from collections import OrderedDict + +from django import forms +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import messages +from django.contrib.admin import helpers +from django.contrib.admin.utils import capfirst, quote, unquote +from django.core.exceptions import PermissionDenied, ValidationError +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db import models, router +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils.encoding import force_text +from django.utils.html import escape +~~from django.utils.http import urlquote, urlunquote +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy, ungettext + +from .. import settings +from ..models import ( + File, Folder, FolderPermission, FolderRoot, ImagesWithMissingData, + UnsortedImages, tools, +) +from ..settings import FILER_IMAGE_MODEL, FILER_PAGINATE_BY +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import get_delete_permission +from ..utils.filer_easy_thumbnails import FilerActionThumbnailer +from ..utils.loader import load_model +from . import views +from .forms import CopyFilesAndFoldersForm, RenameFilesForm, ResizeImagesForm +from .patched.admin_utils import get_deleted_objects +from .permissions import PrimitivePermissionAwareModelAdmin +from .tools import ( + AdminContext, admin_url_params_encoded, check_files_edit_permissions, + check_files_read_permissions, check_folder_edit_permissions, + check_folder_read_permissions, popup_status, userperms_for_request, +) + + + +## ... source file abbreviated to get to urlunquote examples ... + + + self.get_queryset(request).get(id=last_folder_id) + except self.model.DoesNotExist: + url = reverse('admin:filer-directory_listing-root') + url = "%s%s" % (url, admin_url_params_encoded(request)) + else: + url = reverse('admin:filer-directory_listing', kwargs={'folder_id': last_folder_id}) + url = "%s%s" % (url, admin_url_params_encoded(request)) + return HttpResponseRedirect(url) + elif folder_id is None: + folder = FolderRoot() + else: + folder = get_object_or_404(self.get_queryset(request), id=folder_id) + request.session['filer_last_folder_id'] = folder_id + + actions = self.get_actions(request) + + list_display = list(self.list_display) + if not actions: + try: + list_display.remove('action_checkbox') + except ValueError: + pass + + q = request.GET.get('q', None) + if q: +~~ search_terms = urlunquote(q).split(" ") + search_mode = True + else: + search_terms = [] + q = '' + search_mode = False + limit_search_to_folder = request.GET.get('limit_search_to_folder', + False) in (True, 'on') + + if len(search_terms) > 0: + if folder and limit_search_to_folder and not folder.is_root: + folder_qs = folder.get_descendants(include_self=False) + file_qs = File.objects.filter( + folder__in=folder.get_descendants(include_self=True)) + else: + folder_qs = self.get_queryset(request) + file_qs = File.objects.all() + folder_qs = self.filter_folder(folder_qs, search_terms) + file_qs = self.filter_file(file_qs, search_terms) + + show_result_count = True + else: + folder_qs = folder.children.all() + file_qs = folder.files.all() + show_result_count = False + + +## ... source file continues with no further urlunquote examples... + +``` + diff --git a/content/pages/examples/django/django-utils-ipv6-clean-ipv6-address.markdown b/content/pages/examples/django/django-utils-ipv6-clean-ipv6-address.markdown new file mode 100644 index 000000000..6cde1b274 --- /dev/null +++ b/content/pages/examples/django/django-utils-ipv6-clean-ipv6-address.markdown @@ -0,0 +1,142 @@ +title: django.utils.ipv6 clean_ipv6_address Example Code +category: page +slug: django-utils-ipv6-clean-ipv6-address-examples +sortorder: 500011478 +toc: False +sidebartitle: django.utils.ipv6 clean_ipv6_address +meta: Python example code for the clean_ipv6_address callable from the django.utils.ipv6 module of the Django project. + + +clean_ipv6_address is a callable within the django.utils.ipv6 module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / fields.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./fields.py) + +```python +# fields.py +import functools +import inspect +import re +import uuid +import warnings +from collections import OrderedDict +from collections.abc import Mapping + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import ( + EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator, + MinValueValidator, ProhibitNullCharactersValidator, RegexValidator, + URLValidator, ip_address_validators +) +from django.forms import FilePathField as DjangoFilePathField +from django.forms import ImageField as DjangoImageField +from django.utils import timezone +from django.utils.dateparse import ( + parse_date, parse_datetime, parse_duration, parse_time +) +from django.utils.duration import duration_string +from django.utils.encoding import is_protected_type, smart_str +from django.utils.formats import localize_input, sanitize_separators +~~from django.utils.ipv6 import clean_ipv6_address +from django.utils.timezone import utc +from django.utils.translation import gettext_lazy as _ +from pytz.exceptions import InvalidTimeError + +from rest_framework import ( + ISO_8601, RemovedInDRF313Warning, RemovedInDRF314Warning +) +from rest_framework.exceptions import ErrorDetail, ValidationError +from rest_framework.settings import api_settings +from rest_framework.utils import html, humanize_datetime, json, representation +from rest_framework.utils.formatting import lazy_format +from rest_framework.validators import ProhibitSurrogateCharactersValidator + + +class empty: + pass + + +class BuiltinSignatureError(Exception): + pass + + +def is_simple_callable(obj): + if inspect.isbuiltin(obj): + + +## ... source file abbreviated to get to clean_ipv6_address examples ... + + + return str(value) + else: + return getattr(value, self.uuid_format) + + +class IPAddressField(CharField): + + default_error_messages = { + 'invalid': _('Enter a valid IPv4 or IPv6 address.'), + } + + def __init__(self, protocol='both', **kwargs): + self.protocol = protocol.lower() + self.unpack_ipv4 = (self.protocol == 'both') + super().__init__(**kwargs) + validators, error_message = ip_address_validators(protocol, self.unpack_ipv4) + self.validators.extend(validators) + + def to_internal_value(self, data): + if not isinstance(data, str): + self.fail('invalid', value=data) + + if ':' in data: + try: + if self.protocol in ('both', 'ipv6'): +~~ return clean_ipv6_address(data, self.unpack_ipv4) + except DjangoValidationError: + self.fail('invalid', value=data) + + return super().to_internal_value(data) + + + +class IntegerField(Field): + default_error_messages = { + 'invalid': _('A valid integer is required.'), + 'max_value': _('Ensure this value is less than or equal to {max_value}.'), + 'min_value': _('Ensure this value is greater than or equal to {min_value}.'), + 'max_string_length': _('String value too large.') + } + MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs. + re_decimal = re.compile(r'\.0*\s*$') # allow e.g. '1.0' as an int, but not '1.2' + + def __init__(self, **kwargs): + self.max_value = kwargs.pop('max_value', None) + self.min_value = kwargs.pop('min_value', None) + super().__init__(**kwargs) + if self.max_value is not None: + message = lazy_format(self.error_messages['max_value'], max_value=self.max_value) + self.validators.append( + + +## ... source file continues with no further clean_ipv6_address examples... + +``` + diff --git a/content/pages/examples/django/django-utils-itercompat-is-iterable.markdown b/content/pages/examples/django/django-utils-itercompat-is-iterable.markdown new file mode 100644 index 000000000..ce238d3f7 --- /dev/null +++ b/content/pages/examples/django/django-utils-itercompat-is-iterable.markdown @@ -0,0 +1,123 @@ +title: django.utils.itercompat is_iterable Example Code +category: page +slug: django-utils-itercompat-is-iterable-examples +sortorder: 500011479 +toc: False +sidebartitle: django.utils.itercompat is_iterable +meta: Python example code for the is_iterable callable from the django.utils.itercompat module of the Django project. + + +is_iterable is a callable within the django.utils.itercompat module of the Django project. + + +## Example 1 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / filters.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./filters.py) + +```python +# filters.py +from collections import OrderedDict +from datetime import timedelta + +from django import forms +from django.db.models import Q +from django.db.models.constants import LOOKUP_SEP +from django.forms.utils import pretty_name +~~from django.utils.itercompat import is_iterable +from django.utils.timezone import now +from django.utils.translation import gettext_lazy as _ + +from .conf import settings +from .constants import EMPTY_VALUES +from .fields import ( + BaseCSVField, + BaseRangeField, + ChoiceField, + DateRangeField, + DateTimeRangeField, + IsoDateTimeField, + IsoDateTimeRangeField, + LookupChoiceField, + ModelChoiceField, + ModelMultipleChoiceField, + MultipleChoiceField, + RangeField, + TimeRangeField +) +from .utils import get_model_field, label_for_filter + +__all__ = [ + 'AllValuesFilter', + + +## ... source file abbreviated to get to is_iterable examples ... + + + + kwargs.setdefault('label', _('Ordering')) + kwargs.setdefault('help_text', '') + kwargs.setdefault('null_label', None) + super().__init__(*args, **kwargs) + + def get_ordering_value(self, param): + descending = param.startswith('-') + param = param[1:] if descending else param + field_name = self.param_map.get(param, param) + + return "-%s" % field_name if descending else field_name + + def filter(self, qs, value): + if value in EMPTY_VALUES: + return qs + + ordering = [self.get_ordering_value(param) for param in value] + return qs.order_by(*ordering) + + @classmethod + def normalize_fields(cls, fields): + if isinstance(fields, dict): + return OrderedDict(fields) + +~~ assert is_iterable(fields), \ + "'fields' must be an iterable (e.g., a list, tuple, or mapping)." + + assert all(isinstance(field, str) or +~~ is_iterable(field) and len(field) == 2 # may need to be wrapped in parens + for field in fields), \ + "'fields' must contain strings or (field name, param name) pairs." + + return OrderedDict([ + (f, f) if isinstance(f, str) else f for f in fields + ]) + + def build_choices(self, fields, labels): + ascending = [ + (param, labels.get(field, _(pretty_name(param)))) + for field, param in fields.items() + ] + descending = [ + ('-%s' % param, labels.get('-%s' % param, self.descending_fmt % label)) + for param, label in ascending + ] + + return [val for pair in zip(ascending, descending) for val in pair] + + +class FilterMethod: + def __init__(self, filter_instance): + self.f = filter_instance + + + +## ... source file continues with no further is_iterable examples... + +``` + diff --git a/content/pages/examples/django/django-utils-module-loading-autodiscover-modules.markdown b/content/pages/examples/django/django-utils-module-loading-autodiscover-modules.markdown new file mode 100644 index 000000000..f7287f008 --- /dev/null +++ b/content/pages/examples/django/django-utils-module-loading-autodiscover-modules.markdown @@ -0,0 +1,98 @@ +title: django.utils.module_loading autodiscover_modules Example Code +category: page +slug: django-utils-module-loading-autodiscover-modules-examples +sortorder: 500011480 +toc: False +sidebartitle: django.utils.module_loading autodiscover_modules +meta: Python example code for the autodiscover_modules callable from the django.utils.module_loading module of the Django project. + + +autodiscover_modules is a callable within the django.utils.module_loading module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_pool.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_pool.py) + +```python +# plugin_pool.py +from operator import attrgetter + +from django.core.exceptions import ImproperlyConfigured +from django.conf.urls import url, include +from django.template.defaultfilters import slugify +from django.utils.encoding import force_text +from django.utils.functional import cached_property +~~from django.utils.module_loading import autodiscover_modules +from django.utils.translation import get_language, deactivate_all, activate +from django.template import TemplateDoesNotExist, TemplateSyntaxError + +from six import string_types, text_type + +from cms.exceptions import PluginAlreadyRegistered, PluginNotRegistered +from cms.plugin_base import CMSPluginBase +from cms.utils.conf import get_cms_setting +from cms.utils.helpers import normalize_name + + +class PluginPool(object): + + def __init__(self): + self.plugins = {} + self.discovered = False + + def _clear_cached(self): + if 'registered_plugins' in self.__dict__: + del self.__dict__['registered_plugins'] + + if 'plugins_with_extra_menu' in self.__dict__: + del self.__dict__['plugins_with_extra_menu'] + + if 'plugins_with_extra_placeholder_menu' in self.__dict__: + del self.__dict__['plugins_with_extra_placeholder_menu'] + + def discover_plugins(self): + if self.discovered: + return + from cms.cache import invalidate_cms_page_cache + + if get_cms_setting("PAGE_CACHE"): + invalidate_cms_page_cache() + +~~ autodiscover_modules('cms_plugins') + self.discovered = True + + def clear(self): + self.discovered = False + self.plugins = {} + self._clear_cached() + + def validate_templates(self, plugin=None): + if plugin: + plugins = [plugin] + else: + plugins = self.plugins.values() + for plugin in plugins: + if (plugin.render_plugin and not type(plugin.render_plugin) == property + or hasattr(plugin.model, 'render_template') + or hasattr(plugin, 'get_render_template')): + if (plugin.render_template is None and + not hasattr(plugin, 'get_render_template')): + raise ImproperlyConfigured( + "CMS Plugins must define a render template, " + "a get_render_template method or " + "set render_plugin=False: %s" % plugin + ) + elif not hasattr(plugin, 'get_render_template'): + + +## ... source file continues with no further autodiscover_modules examples... + +``` + diff --git a/content/pages/examples/django/django-utils-module-loading-import-string.markdown b/content/pages/examples/django/django-utils-module-loading-import-string.markdown new file mode 100644 index 000000000..68813b63a --- /dev/null +++ b/content/pages/examples/django/django-utils-module-loading-import-string.markdown @@ -0,0 +1,1081 @@ +title: django.utils.module_loading import_string Example Code +category: page +slug: django-utils-module-loading-import-string-examples +sortorder: 500011481 +toc: False +sidebartitle: django.utils.module_loading import_string +meta: Python example code for the import_string callable from the django.utils.module_loading module of the Django project. + + +import_string is a callable within the django.utils.module_loading module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / forms / angular_base.py**](https://github.com/jrief/django-angular/blob/master/djng/forms/angular_base.py) + +```python +# angular_base.py +from base64 import b64encode +from collections import UserList +import json +import warnings + +from django.forms import forms +from django.http import QueryDict +from django.utils.html import format_html, format_html_join, escape, conditional_escape +from django.utils.encoding import force_text +~~from django.utils.module_loading import import_string +from django.utils.safestring import mark_safe, SafeText, SafeData +from django.core.exceptions import ValidationError, ImproperlyConfigured + +from .fields import DefaultFieldMixin + + +class SafeTuple(SafeData, tuple): + + +class TupleErrorList(UserList, list): + def __init__(self, initlist=None, error_class=None): + super(TupleErrorList, self).__init__(initlist) + + if error_class is None: + self.error_class = 'errorlist' + else: + self.error_class = 'errorlist {}'.format(error_class) + + def as_data(self): + return ValidationError(self.data).error_list + + def get_json_data(self, escape_html=False): + errors = [] + for error in self.as_data(): + + +## ... source file abbreviated to get to import_string examples ... + + + elif isinstance(label_css_classes, dict): + for key in (self.name, '*',): + extra_label_classes = label_css_classes.get(key) + if hasattr(extra_label_classes, 'split'): + extra_label_classes = extra_label_classes.split() + extra_label_classes = set(extra_label_classes or []) + css_classes.update(extra_label_classes) + if css_classes: + attrs.update({'class': ' '.join(css_classes)}) + return super(NgBoundField, self).label_tag(contents, attrs, label_suffix='') + + +class BaseFieldsModifierMetaclass(type): + def __new__(cls, name, bases, attrs): + attrs.update(formfield_callback=cls.formfield_callback) + new_class = super(BaseFieldsModifierMetaclass, cls).__new__(cls, name, bases, attrs) + cls.validate_formfields(new_class) + return new_class + + @classmethod + def formfield_callback(cls, modelfield, **kwargs): + formfield = modelfield.formfield(**kwargs) + + if formfield: + try: +~~ formfield_class = import_string('djng.forms.fields.' + formfield.__class__.__name__) + except ImportError: # form field not declared by Django + formfield_class = type(str(formfield.__class__.__name__), (DefaultFieldMixin, formfield.__class__), {}) + + if hasattr(formfield, 'choices'): + kwargs.update(choices_form_class=formfield_class) + kwargs.update(form_class=formfield_class) + formfield = modelfield.formfield(**kwargs) + return formfield + + @classmethod + def validate_formfields(cls, new_class): + msg = "Please use the corresponding form fields from 'djng.forms.fields' for field '{} = {}(...)' " \ + "in form '{}', which inherits from 'NgForm' or 'NgModelForm'." + for name, field in new_class.base_fields.items(): + if not isinstance(field, DefaultFieldMixin): + raise ImproperlyConfigured(msg.format(name, field.__class__.__name__, new_class)) + + +class NgFormBaseMixin(object): + form_error_css_classes = 'djng-form-errors' + field_error_css_classes = 'djng-field-errors' + + def __init__(self, *args, **kwargs): + try: + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 2 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / checks.py**](https://github.com/jazzband/django-axes/blob/master/axes/./checks.py) + +```python +# checks.py +from django.core.checks import ( # pylint: disable=redefined-builtin + Tags, + Warning, + register, +) +~~from django.utils.module_loading import import_string + +from axes.backends import AxesBackend +from axes.conf import settings + + +class Messages: + CACHE_INVALID = ( + "You are using the django-axes cache handler for login attempt tracking." + " Your cache configuration is however invalid and will not work correctly with django-axes." + " This can leave security holes in your login systems as attempts are not tracked correctly." + " Reconfigure settings.AXES_CACHE and settings.CACHES per django-axes configuration documentation." + ) + MIDDLEWARE_INVALID = ( + "You do not have 'axes.middleware.AxesMiddleware' in your settings.MIDDLEWARE." + ) + BACKEND_INVALID = "You do not have 'axes.backends.AxesBackend' or a subclass in your settings.AUTHENTICATION_BACKENDS." + SETTING_DEPRECATED = "You have a deprecated setting {deprecated_setting} configured in your project settings" + + +class Hints: + CACHE_INVALID = None + MIDDLEWARE_INVALID = None + BACKEND_INVALID = ( + "AxesModelBackend was renamed to AxesBackend in django-axes version 5.0." + + +## ... source file abbreviated to get to import_string examples ... + + + + +@register(Tags.security, Tags.compatibility) +def axes_middleware_check(app_configs, **kwargs): # pylint: disable=unused-argument + warnings = [] + + if "axes.middleware.AxesMiddleware" not in settings.MIDDLEWARE: + warnings.append( + Warning( + msg=Messages.MIDDLEWARE_INVALID, + hint=Hints.MIDDLEWARE_INVALID, + id=Codes.MIDDLEWARE_INVALID, + ) + ) + + return warnings + + +@register(Tags.security, Tags.compatibility) +def axes_backend_check(app_configs, **kwargs): # pylint: disable=unused-argument + warnings = [] + + found = False + for name in settings.AUTHENTICATION_BACKENDS: + try: +~~ backend = import_string(name) + except ModuleNotFoundError as e: + raise ModuleNotFoundError( + "Can not find module path defined in settings.AUTHENTICATION_BACKENDS" + ) from e + except ImportError as e: + raise ImportError( + "Can not import backend class defined in settings.AUTHENTICATION_BACKENDS" + ) from e + + if issubclass(backend, AxesBackend): + found = True + break + + if not found: + warnings.append( + Warning( + msg=Messages.BACKEND_INVALID, + hint=Hints.BACKEND_INVALID, + id=Codes.BACKEND_INVALID, + ) + ) + + return warnings + + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 3 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / toolbar_pool.py**](https://github.com/divio/django-cms/blob/develop/cms/./toolbar_pool.py) + +```python +# toolbar_pool.py +from collections import OrderedDict + +from django.core.exceptions import ImproperlyConfigured +~~from django.utils.module_loading import autodiscover_modules, import_string + +from cms.exceptions import ToolbarAlreadyRegistered, ToolbarNotRegistered +from cms.utils.conf import get_cms_setting + + +class ToolbarPool(object): + def __init__(self): + self.toolbars = OrderedDict() + self._discovered = False + self.force_register = False + + def discover_toolbars(self): + if self._discovered: + return + toolbars = get_cms_setting('TOOLBARS') + if toolbars: + for path in toolbars: +~~ cls = import_string(path) + self.force_register = True + self.register(cls) + self.force_register = False + else: + autodiscover_modules('cms_toolbars') + self._discovered = True + + def clear(self): + self.toolbars = OrderedDict() + self._discovered = False + + def register(self, toolbar): + if not self.force_register and get_cms_setting('TOOLBARS'): + return toolbar + from cms.toolbar_base import CMSToolbar + if not issubclass(toolbar, CMSToolbar): + raise ImproperlyConfigured('CMS Toolbar must inherit ' + 'cms.toolbar_base.CMSToolbar, %r does not' % toolbar) + name = "%s.%s" % (toolbar.__module__, toolbar.__name__) + if name in self.toolbars.keys(): + raise ToolbarAlreadyRegistered("[%s] a toolbar with this name is already registered" % name) + self.toolbars[name] = toolbar + return toolbar + + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 4 from django-debug-toolbar +[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar) +([project documentation](https://github.com/jazzband/django-debug-toolbar) +and [PyPI page](https://pypi.org/project/django-debug-toolbar/)) +grants a developer detailed request-response cycle information while +developing a [Django](/django.html) web application. +The code for django-debug-toolbar is +[open source](https://github.com/jazzband/django-debug-toolbar/blob/master/LICENSE) +and maintained by the developer community group known as +[Jazzband](https://jazzband.co/). + +[**django-debug-toolbar / debug_toolbar / apps.py**](https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/./apps.py) + +```python +# apps.py +import inspect + +from django.apps import AppConfig +from django.conf import settings +from django.core.checks import Warning, register +from django.middleware.gzip import GZipMiddleware +~~from django.utils.module_loading import import_string +from django.utils.translation import gettext_lazy as _ + + +class DebugToolbarConfig(AppConfig): + name = "debug_toolbar" + verbose_name = _("Debug Toolbar") + + +@register +def check_middleware(app_configs, **kwargs): + from debug_toolbar.middleware import DebugToolbarMiddleware + + errors = [] + gzip_index = None + debug_toolbar_indexes = [] + + if settings.is_overridden("MIDDLEWARE_CLASSES"): + errors.append( + Warning( + "debug_toolbar is incompatible with MIDDLEWARE_CLASSES setting.", + hint="Use MIDDLEWARE instead of MIDDLEWARE_CLASSES", + id="debug_toolbar.W004", + ) + ) + + +## ... source file abbreviated to get to import_string examples ... + + + errors.append( + Warning( + "debug_toolbar.middleware.DebugToolbarMiddleware occurs " + "multiple times in MIDDLEWARE.", + hint="Load debug_toolbar.middleware.DebugToolbarMiddleware only " + "once in MIDDLEWARE.", + id="debug_toolbar.W002", + ) + ) + elif gzip_index is not None and debug_toolbar_indexes[0] < gzip_index: + errors.append( + Warning( + "debug_toolbar.middleware.DebugToolbarMiddleware occurs before " + "django.middleware.gzip.GZipMiddleware in MIDDLEWARE.", + hint="Move debug_toolbar.middleware.DebugToolbarMiddleware to " + "after django.middleware.gzip.GZipMiddleware in MIDDLEWARE.", + id="debug_toolbar.W003", + ) + ) + + return errors + + +def is_middleware_class(middleware_class, middleware_path): + try: +~~ middleware_cls = import_string(middleware_path) + except ImportError: + return + return inspect.isclass(middleware_cls) and issubclass( + middleware_cls, middleware_class + ) + + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 5 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / collision_resolvers.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/./collision_resolvers.py) + +```python +# collision_resolvers.py +import inspect +import sys +from abc import abstractmethod, ABCMeta +from typing import ( # NOQA + Dict, + List, + Optional, + Tuple, +) + +~~from django.utils.module_loading import import_string +from six import add_metaclass + + +@add_metaclass(ABCMeta) +class BaseCR: + + @classmethod + def get_app_name_and_model(cls, full_model_path): # type: (str) -> Tuple[str, str] +~~ model_class = import_string(full_model_path) + return model_class._meta.app_config.name, model_class.__name__ + + @abstractmethod + def resolve_collisions(self, namespace): # type: (Dict[str, List[str]]) -> Dict[str, str] + pass + + +class LegacyCR(BaseCR): + + def resolve_collisions(self, namespace): + result = {} + for name, models in namespace.items(): + result[name] = models[-1] + return result + + +@add_metaclass(ABCMeta) +class AppsOrderCR(LegacyCR): + APP_PRIORITIES = None # type: List[str] + + def resolve_collisions(self, namespace): + assert self.APP_PRIORITIES is not None, "You must define APP_PRIORITIES in your resolver class!" + result = {} + for name, models in namespace.items(): + + +## ... source file abbreviated to get to import_string examples ... + + + MODIFICATION_STRING = "{model_name}_{app_name}" + + +class AppNamePrefixCustomOrderCR(AppNamePrefixCR, InstalledAppsOrderCR): + + pass + + +class AppNameSuffixCustomOrderCR(AppNameSuffixCR, InstalledAppsOrderCR): + + pass + + +class FullPathCustomOrderCR(FullPathCR, InstalledAppsOrderCR): + + pass + + +@add_metaclass(ABCMeta) +class AppLabelCR(PathBasedCR): + + MODIFICATION_STRING = None # type: Optional[str] + + def transform_import(self, module_path): + assert self.MODIFICATION_STRING is not None, "You must define MODIFICATION_STRING in your resolver class!" +~~ model_class = import_string(module_path) + app_label, model_name = model_class._meta.app_label, model_class.__name__ + return self.MODIFICATION_STRING.format(app_label=app_label, model_name=model_name) + + +class AppLabelPrefixCR(AppLabelCR): + + MODIFICATION_STRING = "{app_label}_{model_name}" + + +class AppLabelSuffixCR(AppLabelCR): + + MODIFICATION_STRING = "{model_name}_{app_label}" + + +class CollisionResolvingRunner: + def __init__(self): + pass + + def run_collision_resolver(self, models_to_import): + dictionary_of_names = self._get_dictionary_of_names(models_to_import) # type: Dict[str, str] + return self._get_dictionary_of_modules(dictionary_of_names) + + @classmethod + def _get_dictionary_of_names(cls, models_to_import): # type: (Dict[str, List[str]]) -> (Dict[str, str]) + from django.conf import settings +~~ collision_resolver_class = import_string(getattr( + settings, 'SHELL_PLUS_MODEL_IMPORTS_RESOLVER', + 'django_extensions.collision_resolvers.LegacyCR' + )) + + cls._assert_is_collision_resolver_class_correct(collision_resolver_class) + result = collision_resolver_class().resolve_collisions(models_to_import) + cls._assert_is_collision_resolver_result_correct(result) + + return result + + @classmethod + def _assert_is_collision_resolver_result_correct(cls, result): + assert isinstance(result, dict), "Result of resolve_collisions function must be a dict!" + for key, value in result.items(): + assert isinstance(key, str), "key in collision resolver result should be str not %s" % key + assert isinstance(value, str), "value in collision resolver result should be str not %s" % value + + @classmethod + def _assert_is_collision_resolver_class_correct(cls, collision_resolver_class): + assert inspect.isclass(collision_resolver_class) and issubclass( + collision_resolver_class, BaseCR), "SHELL_PLUS_MODEL_IMPORTS_RESOLVER " \ + "must be subclass of BaseCR!" + assert len(inspect.getfullargspec(collision_resolver_class.resolve_collisions).args) == 2, \ + "resolve_collisions function must take one argument!" + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 6 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / ctypes.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./ctypes.py) + +```python +# ctypes.py +from django.contrib.contenttypes.models import ContentType +~~from django.utils.module_loading import import_string + +from guardian.conf import settings as guardian_settings + + +def get_content_type(obj): +~~ get_content_type_function = import_string( + guardian_settings.GET_CONTENT_TYPE) + return get_content_type_function(obj) + + +def get_default_content_type(obj): + return ContentType.objects.get_for_model(obj) + + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 7 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / admin.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./admin.py) + +```python +# admin.py +from datetime import datetime + +import django +from django import forms +from django.conf import settings +from django.conf.urls import url +from django.contrib import admin, messages +from django.contrib.admin.models import ADDITION, CHANGE, DELETION, LogEntry +from django.contrib.auth import get_permission_codename +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import PermissionDenied +from django.http import HttpResponse, HttpResponseRedirect +from django.template.response import TemplateResponse +from django.urls import reverse +from django.utils.decorators import method_decorator +from django.utils.encoding import force_str +~~from django.utils.module_loading import import_string +from django.utils.translation import gettext_lazy as _ +from django.views.decorators.http import require_POST + +from .formats.base_formats import DEFAULT_FORMATS +from .forms import ConfirmImportForm, ExportForm, ImportForm, export_action_form_factory +from .resources import modelresource_factory +from .results import RowResult +from .signals import post_export, post_import +from .tmp_storages import TempFolderStorage + +SKIP_ADMIN_LOG = getattr(settings, 'IMPORT_EXPORT_SKIP_ADMIN_LOG', False) +TMP_STORAGE_CLASS = getattr(settings, 'IMPORT_EXPORT_TMP_STORAGE_CLASS', + TempFolderStorage) + + +if isinstance(TMP_STORAGE_CLASS, str): +~~ TMP_STORAGE_CLASS = import_string(TMP_STORAGE_CLASS) + + +class ImportExportMixinBase: + def get_model_info(self): + app_label = self.model._meta.app_label + return (app_label, self.model._meta.model_name) + + +class ImportMixin(ImportExportMixinBase): + + change_list_template = 'admin/import_export/change_list_import.html' + import_template_name = 'admin/import_export/import.html' + resource_class = None + formats = DEFAULT_FORMATS + from_encoding = "utf-8" + skip_admin_log = None + tmp_storage_class = None + + def get_skip_admin_log(self): + if self.skip_admin_log is None: + return SKIP_ADMIN_LOG + else: + return self.skip_admin_log + + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 8 from django-push-notifications +[django-push-notifications](https://github.com/jazzband/django-push-notifications) +is a [Django](/django.html) app for storing and interacting with +push notification services such as +[Google's Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/) +and +[Apple Notifications](https://developer.apple.com/notifications/). +The django-push-notification project's source code is available +open source under the +[MIT license](https://github.com/jazzband/django-push-notifications/blob/master/LICENSE). + +[**django-push-notifications / push_notifications / conf / __init__.py**](https://github.com/jazzband/django-push-notifications/blob/master/push_notifications/conf/__init__.py) + +```python +# __init__.py +~~from django.utils.module_loading import import_string + +from .app import AppConfig # noqa: F401 +from .appmodel import AppModelConfig # noqa: F401 +from .legacy import LegacyConfig # noqa: F401 +from ..settings import PUSH_NOTIFICATIONS_SETTINGS as SETTINGS # noqa: I001 + + +manager = None + + +def get_manager(reload=False): + global manager + + if not manager or reload is True: +~~ manager = import_string(SETTINGS["CONFIG"])() + + return manager + + +get_manager() + + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 9 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / settings.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./settings.py) + +```python +# settings.py +from django.conf import settings +from django.test.signals import setting_changed +~~from django.utils.module_loading import import_string + +from rest_framework import ISO_8601 + +DEFAULTS = { + 'DEFAULT_RENDERER_CLASSES': [ + 'rest_framework.renderers.JSONRenderer', + 'rest_framework.renderers.BrowsableAPIRenderer', + ], + 'DEFAULT_PARSER_CLASSES': [ + 'rest_framework.parsers.JSONParser', + 'rest_framework.parsers.FormParser', + 'rest_framework.parsers.MultiPartParser' + ], + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rest_framework.authentication.SessionAuthentication', + 'rest_framework.authentication.BasicAuthentication' + ], + 'DEFAULT_PERMISSION_CLASSES': [ + 'rest_framework.permissions.AllowAny', + ], + 'DEFAULT_THROTTLE_CLASSES': [], + 'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'rest_framework.negotiation.DefaultContentNegotiation', + 'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata', + 'DEFAULT_VERSIONING_CLASS': None, + + +## ... source file abbreviated to get to import_string examples ... + + + 'TEST_REQUEST_RENDERER_CLASSES', + 'UNAUTHENTICATED_USER', + 'UNAUTHENTICATED_TOKEN', + 'VIEW_NAME_FUNCTION', + 'VIEW_DESCRIPTION_FUNCTION' +] + + +REMOVED_SETTINGS = [ + 'PAGINATE_BY', 'PAGINATE_BY_PARAM', 'MAX_PAGINATE_BY', +] + + +def perform_import(val, setting_name): + if val is None: + return None + elif isinstance(val, str): + return import_from_string(val, setting_name) + elif isinstance(val, (list, tuple)): + return [import_from_string(item, setting_name) for item in val] + return val + + +def import_from_string(val, setting_name): + try: +~~ return import_string(val) + except ImportError as e: + msg = "Could not import '%s' for API setting '%s'. %s: %s." % (val, setting_name, e.__class__.__name__, e) + raise ImportError(msg) + + +class APISettings: + def __init__(self, user_settings=None, defaults=None, import_strings=None): + if user_settings: + self._user_settings = self.__check_user_settings(user_settings) + self.defaults = defaults or DEFAULTS + self.import_strings = import_strings or IMPORT_STRINGS + self._cached_attrs = set() + + @property + def user_settings(self): + if not hasattr(self, '_user_settings'): + self._user_settings = getattr(settings, 'REST_FRAMEWORK', {}) + return self._user_settings + + def __getattr__(self, attr): + if attr not in self.defaults: + raise AttributeError("Invalid API setting: '%s'" % attr) + + try: + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 10 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / exporters.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./exporters.py) + +```python +# exporters.py +from django.db import DatabaseError +from django.core.serializers.json import DjangoJSONEncoder +import json +import uuid +import string +import sys +from datetime import datetime +PY3 = sys.version_info[0] == 3 +if PY3: + import csv +else: + import unicodecsv as csv + +~~from django.utils.module_loading import import_string +from django.utils.text import slugify +from explorer import app_settings +from six import StringIO, BytesIO + + +def get_exporter_class(format): + class_str = dict(getattr(app_settings, 'EXPLORER_DATA_EXPORTERS'))[format] +~~ return import_string(class_str) + + +class BaseExporter(object): + + name = '' + content_type = '' + file_extension = '' + + def __init__(self, query): + self.query = query + + def get_output(self, **kwargs): + value = self.get_file_output(**kwargs).getvalue() + if PY3: + return value + else: + return str(value) + + def get_file_output(self, **kwargs): + res = self.query.execute_query_only() + return self._get_output(res, **kwargs) + + def _get_output(self, res, **kwargs): + raise NotImplementedError + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 11 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / utils.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./utils.py) + +```python +# utils.py +from django.conf import settings +from django.utils.functional import wraps +~~from django.utils.module_loading import import_string + + +def _parse_tags(tagstring): + if not tagstring: + return [] + + if "," not in tagstring and '"' not in tagstring: + words = list(set(split_strip(tagstring, " "))) + words.sort() + return words + + words = [] + buffer = [] + to_be_split = [] + saw_loose_comma = False + open_quote = False + i = iter(tagstring) + try: + while True: + c = next(i) + if c == '"': + if buffer: + to_be_split.append("".join(buffer)) + buffer = [] + + +## ... source file abbreviated to get to import_string examples ... + + + + +def _edit_string_for_tags(tags): + names = [] + for tag in tags: + name = tag.name + if "," in name or " " in name: + names.append('"%s"' % name) + else: + names.append(name) + return ", ".join(sorted(names)) + + +def require_instance_manager(func): + @wraps(func) + def inner(self, *args, **kwargs): + if self.instance is None: + raise TypeError("Can't call %s with a non-instance manager" % func.__name__) + return func(self, *args, **kwargs) + + return inner + + +def get_func(key, default): + func_path = getattr(settings, key, None) +~~ return default if func_path is None else import_string(func_path) + + +def parse_tags(tagstring): + func = get_func("TAGGIT_TAGS_FROM_STRING", _parse_tags) + return func(tagstring) + + +def edit_string_for_tags(tags): + func = get_func("TAGGIT_STRING_FROM_TAGS", _edit_string_for_tags) + return func(tags) + + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 12 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / sites.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./sites.py) + +```python +# sites.py +from django.apps import apps +from django.urls import include +from django.urls import re_path +from django.utils.functional import LazyObject +~~from django.utils.module_loading import import_string +from wiki.conf import settings +from wiki.core.plugins import registry + + +class WikiSite: + + def __init__(self, name="wiki"): + from wiki.views import accounts, article, deleted_list + + self.name = name + + self.root_view = getattr(self, "root_view", article.CreateRootView.as_view()) + self.root_missing_view = getattr( + self, "root_missing_view", article.MissingRootView.as_view() + ) + + self.article_view = getattr(self, "article_view", article.ArticleView.as_view()) + self.article_create_view = getattr( + self, "article_create_view", article.Create.as_view() + ) + self.article_delete_view = getattr( + self, "article_delete_view", article.Delete.as_view() + ) + self.article_deleted_view = getattr( + + +## ... source file abbreviated to get to import_string examples ... + + + def get_plugin_urls(self): + urlpatterns = [] + for plugin in registry.get_plugins().values(): + slug = getattr(plugin, "slug", None) + if slug: + article_urlpatterns = plugin.urlpatterns.get("article", []) + urlpatterns += [ + re_path( + r"^(?P[0-9]+)/plugin/" + slug + "/", + include(article_urlpatterns), + ), + re_path( + r"^(?P.+/|)_plugin/" + slug + "/", + include(article_urlpatterns), + ), + ] + root_urlpatterns = plugin.urlpatterns.get("root", []) + urlpatterns += [ + re_path(r"^_plugin/" + slug + "/", include(root_urlpatterns)), + ] + return urlpatterns + + +class DefaultWikiSite(LazyObject): + def _setup(self): +~~ WikiSiteClass = import_string(apps.get_app_config("wiki").default_site) + self._wrapped = WikiSiteClass() + + +site = DefaultWikiSite() + + + +## ... source file continues with no further import_string examples... + +``` + + +## Example 13 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / utils / loading.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/utils/loading.py) + +```python +# loading.py +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +~~from django.utils.module_loading import import_string + + +def get_custom_form(form_setting): + try: +~~ return import_string(getattr(settings, form_setting)) + except ImportError: + raise ImproperlyConfigured( + "%s refers to a form '%s' that is not available" % + (form_setting, getattr(settings, form_setting)) + ) + + + +## ... source file continues with no further import_string examples... + +``` + diff --git a/content/pages/examples/django/django-utils-module-loading-module-has-submodule.markdown b/content/pages/examples/django/django-utils-module-loading-module-has-submodule.markdown new file mode 100644 index 000000000..e0708ccb7 --- /dev/null +++ b/content/pages/examples/django/django-utils-module-loading-module-has-submodule.markdown @@ -0,0 +1,268 @@ +title: django.utils.module_loading module_has_submodule Example Code +category: page +slug: django-utils-module-loading-module-has-submodule-examples +sortorder: 500011482 +toc: False +sidebartitle: django.utils.module_loading module_has_submodule +meta: Python example code for the module_has_submodule callable from the django.utils.module_loading module of the Django project. + + +module_has_submodule is a callable within the django.utils.module_loading module of the Django project. + + +## Example 1 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / utils / loading.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/utils/loading.py) + +```python +# loading.py +import copy +import inspect +import threading +import warnings +from collections import OrderedDict + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +~~from django.utils.module_loading import module_has_submodule + +from haystack import constants +from haystack.exceptions import NotHandled, SearchFieldError +from haystack.utils import importlib +from haystack.utils.app_loading import haystack_get_app_modules + + +def import_class(path): + path_bits = path.split(".") + class_name = path_bits.pop() + module_path = ".".join(path_bits) + module_itself = importlib.import_module(module_path) + + if not hasattr(module_itself, class_name): + raise ImportError( + "The Python module '%s' has no '%s' class." % (module_path, class_name) + ) + + return getattr(module_itself, class_name) + + +def load_backend(full_backend_path): + path_bits = full_backend_path.split(".") + + + +## ... source file abbreviated to get to module_has_submodule examples ... + + + self._indexes = {} + self.fields = OrderedDict() + self._built = False + self.excluded_indexes = excluded_indexes or [] + self.excluded_indexes_ids = {} + self.document_field = constants.DOCUMENT_FIELD + self._fieldnames = {} + self._facet_fieldnames = {} + + @property + def indexes(self): + warnings.warn( + "'UnifiedIndex.indexes' was deprecated in Haystack v2.3.0. Please use UnifiedIndex.get_indexes()." + ) + return self._indexes + + def collect_indexes(self): + indexes = [] + + for app_mod in haystack_get_app_modules(): + try: + search_index_module = importlib.import_module( + "%s.search_indexes" % app_mod.__name__ + ) + except ImportError: +~~ if module_has_submodule(app_mod, "search_indexes"): + raise + + continue + + for item_name, item in inspect.getmembers( + search_index_module, inspect.isclass + ): + if getattr(item, "haystack_use_for_indexing", False) and getattr( + item, "get_model", None + ): + class_path = "%s.search_indexes.%s" % (app_mod.__name__, item_name) + + if class_path in self.excluded_indexes or self.excluded_indexes_ids.get( + item_name + ) == id( + item + ): + self.excluded_indexes_ids[str(item_name)] = id(item) + continue + + indexes.append(item()) + + return indexes + + + +## ... source file continues with no further module_has_submodule examples... + +``` + + +## Example 2 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / utils.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./utils.py) + +```python +# utils.py +from importlib import import_module +from types import ModuleType +from typing import Any, Sequence, Type, Union, List, Optional, Tuple + +from django.apps import apps +from django.contrib.auth.models import Permission +from django.core.exceptions import ImproperlyConfigured +~~from django.utils.module_loading import module_has_submodule + +from . import settings + +if False: # pragma: nocover + from .models import TreeItemBase, TreeBase # noqa + + +TypePermission = Union[str, int, Permission] + +apps_get_model = apps.get_model + + +def generate_id_for(obj: Any): + return id(obj) + + +def tree(alias: str, title: str = '', items: Sequence['TreeItemBase'] = None, **kwargs) -> 'TreeBase': + tree_obj = get_tree_model()(alias=alias, title=title, **kwargs) + tree_obj.id = generate_id_for(tree_obj) + tree_obj.is_dynamic = True + + if items is not None: + tree_obj.dynamic_items = [] + + + +## ... source file abbreviated to get to module_has_submodule examples ... + + + cleaned_permissions.append(perm) + + item_obj.permissions = cleaned_permissions or [] + item_obj.access_perm_type = item_obj.PERM_TYPE_ALL if perms_mode_all else item_obj.PERM_TYPE_ANY + + if item_obj.permissions: + item_obj.access_restricted = True + + if children is not None: + for child in children: + child.parent = item_obj + item_obj.dynamic_children.append(child) + + return item_obj + + +def import_app_sitetree_module(app: str) -> Optional[ModuleType]: + module_name = settings.APP_MODULE_NAME + module = import_module(app) + + try: + sub_module = import_module(f'{app}.{module_name}') + return sub_module + + except ImportError: +~~ if module_has_submodule(module, module_name): + raise + return None + + +def import_project_sitetree_modules() -> List[ModuleType]: + from django.conf import settings as django_settings + + submodules = [] + for app in django_settings.INSTALLED_APPS: + module = import_app_sitetree_module(app) + if module is not None: + submodules.append(module) + + return submodules + + +def get_app_n_model(settings_entry_name: str) -> Tuple[str, str]: + try: + app_name, model_name = getattr(settings, settings_entry_name).split('.') + + except ValueError: + raise ImproperlyConfigured( + f'`SITETREE_{settings_entry_name}` must have the following format: `app_name.model_name`.') + + + +## ... source file continues with no further module_has_submodule examples... + +``` + + +## Example 3 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / utils / apps.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/utils/apps.py) + +```python +# apps.py +from importlib import import_module + +from django.apps import apps +~~from django.utils.module_loading import module_has_submodule + + +def get_app_modules(): + for app in apps.get_app_configs(): + yield app.name, app.module + + +def get_app_submodules(submodule_name): + for name, module in get_app_modules(): +~~ if module_has_submodule(module, submodule_name): + yield name, import_module('%s.%s' % (name, submodule_name)) + + + +## ... source file continues with no further module_has_submodule examples... + +``` + diff --git a/content/pages/examples/django/django-utils-module-loading.markdown b/content/pages/examples/django/django-utils-module-loading.markdown new file mode 100644 index 000000000..14b42141c --- /dev/null +++ b/content/pages/examples/django/django-utils-module-loading.markdown @@ -0,0 +1,106 @@ +title: django.utils module_loading Example Code +category: page +slug: django-utils-module-loading-examples +sortorder: 500011419 +toc: False +sidebartitle: django.utils module_loading +meta: Python example code for the module_loading callable from the django.utils module of the Django project. + + +module_loading is a callable within the django.utils module of the Django project. + + +## Example 1 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / sitetreeapp.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./sitetreeapp.py) + +```python +# sitetreeapp.py +import warnings +from collections import defaultdict +from copy import deepcopy +from inspect import getfullargspec +from sys import exc_info +from threading import local +from typing import Callable, List, Optional, Dict, Union, Sequence, Any, Tuple + +from django.conf import settings +from django.core.cache import cache +from django.db.models import signals, QuerySet +from django.template.base import ( + FilterExpression, Lexer, Parser, Token, Variable, VariableDoesNotExist, VARIABLE_TAG_START, Context) +from django.template.defaulttags import url as url_tag +from django.template.loader import get_template +~~from django.utils import module_loading +from django.utils.http import urlquote +from django.utils.translation import get_language + +from .compat import TOKEN_BLOCK, TOKEN_TEXT, TOKEN_VAR +from .exceptions import SiteTreeError +from .settings import ( + ALIAS_TRUNK, ALIAS_THIS_CHILDREN, ALIAS_THIS_SIBLINGS, ALIAS_THIS_PARENT_SIBLINGS, ALIAS_THIS_ANCESTOR_CHILDREN, + UNRESOLVED_ITEM_MARKER, RAISE_ITEMS_ERRORS_ON_DEBUG, CACHE_TIMEOUT, DYNAMIC_ONLY, ADMIN_APP_NAME, SITETREE_CLS) +from .utils import get_tree_model, get_tree_item_model, import_app_sitetree_module, generate_id_for + +if False: # pragma: nocover + from django.contrib.auth.models import User # noqa + from .models import TreeItemBase, TreeBase + +TypeDynamicTrees = Dict[str, Union[Dict[str, List['TreeBase']], List['TreeBase']]] + +MODEL_TREE_CLASS = get_tree_model() +MODEL_TREE_ITEM_CLASS = get_tree_item_model() + + +_ITEMS_PROCESSOR: Optional[Callable] = None + +_ITEMS_PROCESSOR_ARGS_LEN: int = 0 + + + +## ... source file abbreviated to get to module_loading examples ... + + + base_item.in_current_branch = True + if hasattr(base_item, 'parent') and base_item.parent is not None: + self.tree_climber(tree_alias, self.get_item_by_id(tree_alias, base_item.parent.id)) + + def resolve_var( + self, + varname: Union[str, 'TreeItemBase', FilterExpression], + context: Context = None + ) -> Any: + context = context or self.current_page_context + + if isinstance(varname, FilterExpression): + varname = varname.resolve(context) + + else: + varname = varname.strip() + + try: + varname = Variable(varname).resolve(context) + except VariableDoesNotExist: + varname = varname + + return varname + + +~~_SITETREE_CLS = module_loading.import_string(SITETREE_CLS) if SITETREE_CLS else SiteTree + + + +## ... source file continues with no further module_loading examples... + +``` + diff --git a/content/pages/examples/django/django-utils-numberformat-format.markdown b/content/pages/examples/django/django-utils-numberformat-format.markdown new file mode 100644 index 000000000..ec382753b --- /dev/null +++ b/content/pages/examples/django/django-utils-numberformat-format.markdown @@ -0,0 +1,125 @@ +title: django.utils.numberformat format Example Code +category: page +slug: django-utils-numberformat-format-examples +sortorder: 500011483 +toc: False +sidebartitle: django.utils.numberformat format +meta: Python example code for the format callable from the django.utils.numberformat module of the Django project. + + +format is a callable within the django.utils.numberformat module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / tests / test_placeholder.py**](https://github.com/divio/django-cms/blob/develop/cms/tests/test_placeholder.py) + +```python +# test_placeholder.py +from django.conf import settings +from django.contrib.auth import get_user_model +from django.core.cache import cache +from django.core.exceptions import ImproperlyConfigured +from django.template import TemplateSyntaxError, Template +from django.template.loader import get_template +from django.test import TestCase +from django.test.utils import override_settings +from django.utils.encoding import force_text +~~from django.utils.numberformat import format +from sekizai.context import SekizaiContext + +from cms import constants +from cms.api import add_plugin, create_page, create_title +from cms.exceptions import DuplicatePlaceholderWarning +from cms.models.fields import PlaceholderField +from cms.models.placeholdermodel import Placeholder +from cms.models.pluginmodel import CMSPlugin +from cms.plugin_pool import plugin_pool +from cms.tests.test_toolbar import ToolbarTestBase +from cms.test_utils.fixtures.fakemlng import FakemlngFixtures +from cms.test_utils.project.fakemlng.models import Translations +from cms.test_utils.project.placeholderapp.models import ( + DynamicPlaceholderSlotExample, + Example1, + TwoPlaceholderExample, +) +from cms.test_utils.project.sampleapp.models import Category +from cms.test_utils.testcases import CMSTestCase, TransactionCMSTestCase +from cms.test_utils.util.mock import AttributeObject +from cms.toolbar.toolbar import CMSToolbar +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils.compat.tests import UnittestCompatMixin +from cms.utils.conf import get_cms_setting + + +## ... source file abbreviated to get to format examples ... + + + self.assertEqual(plugins[0].plugin_type, 'TextPlugin') + self.assertEqual(plugins[1].plugin_type, 'LinkPlugin') + self.assertEqual(plugins[2].plugin_type, 'LinkPlugin') + self.assertTrue(plugins[1].parent == plugins[2].parent and plugins[1].parent == plugins[0]) + + def test_placeholder_pk_thousands_format(self): + page = create_page("page", "nav_playground.html", "en", published=True) + for placeholder in page.placeholders.all(): + page.placeholders.remove(placeholder) + placeholder.pk += 1000 + placeholder.save() + page.placeholders.add(placeholder) + page.reload() + for placeholder in page.placeholders.all(): + add_plugin(placeholder, "TextPlugin", "en", body="body") + with self.settings(USE_THOUSAND_SEPARATOR=True, USE_L10N=True): + user = self.get_superuser() + self.client.login(username=getattr(user, get_user_model().USERNAME_FIELD), + password=getattr(user, get_user_model().USERNAME_FIELD)) + endpoint = page.get_absolute_url() + '?' + get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON') + response = self.client.get(endpoint) + for placeholder in page.placeholders.all(): + self.assertContains( + response, '"placeholder_id": "%s"' % placeholder.pk) + self.assertNotContains( +~~ response, '"placeholder_id": "%s"' % format( + placeholder.pk, ".", grouping=3, thousand_sep=",")) + self.assertNotContains( +~~ response, '"plugin_id": "%s"' % format( + placeholder.pk, ".", grouping=3, thousand_sep=",")) + self.assertNotContains( +~~ response, '"clipboard": "%s"' % format( + response.context['request'].toolbar.clipboard.pk, ".", + grouping=3, thousand_sep=",")) + + def test_placeholder_languages_model(self): + avail_langs = set([u'en', u'de', u'fr']) + ex = Example1( + char_1='one', + char_2='two', + char_3='tree', + char_4='four' + ) + ex.save() + for lang in avail_langs: + add_plugin(ex.placeholder, u"EmptyPlugin", lang) + ex = Example1.objects.get(pk=ex.pk) + langs = [lang['code'] for lang in ex.placeholder.get_filled_languages()] + self.assertEqual(avail_langs, set(langs)) + + def test_placeholder_languages_page(self): + avail_langs = set([u'en', u'de', u'fr']) + page = create_page('test page', 'col_two.html', u'en') + for lang in avail_langs: + if lang != u'en': + create_title(lang, 'test page %s' % lang, page) + + +## ... source file continues with no further format examples... + +``` + diff --git a/content/pages/examples/django/django-utils-safestring-mark-safe.markdown b/content/pages/examples/django/django-utils-safestring-mark-safe.markdown new file mode 100644 index 000000000..ba71e864b --- /dev/null +++ b/content/pages/examples/django/django-utils-safestring-mark-safe.markdown @@ -0,0 +1,2391 @@ +title: django.utils.safestring mark_safe Example Code +category: page +slug: django-utils-safestring-mark-safe-examples +sortorder: 500011486 +toc: False +sidebartitle: django.utils.safestring mark_safe +meta: Python example code for the mark_safe callable from the django.utils.safestring module of the Django project. + + +mark_safe is a callable within the django.utils.safestring module of the Django project. + + +## Example 1 from AuditLog +[Auditlog](https://github.com/jjkester/django-auditlog) +([project documentation](https://django-auditlog.readthedocs.io/en/latest/)) +is a [Django](/django.html) app that logs changes to Python objects, +similar to the Django admin's logs but with more details and +output formats. Auditlog's source code is provided as open source under the +[MIT license](https://github.com/jjkester/django-auditlog/blob/master/LICENSE). + +[**AuditLog / src / auditlog / mixins.py**](https://github.com/jjkester/django-auditlog/blob/master/src/auditlog/mixins.py) + +```python +# mixins.py +import json + +from django.conf import settings +try: + from django.core import urlresolvers +except ImportError: + from django import urls as urlresolvers +try: + from django.urls.exceptions import NoReverseMatch +except ImportError: + from django.core.urlresolvers import NoReverseMatch +from django.utils.html import format_html +~~from django.utils.safestring import mark_safe + +MAX = 75 + + +class LogEntryAdminMixin(object): + + def created(self, obj): + return obj.timestamp.strftime('%Y-%m-%d %H:%M:%S') + created.short_description = 'Created' + + def user_url(self, obj): + if obj.actor: + app_label, model = settings.AUTH_USER_MODEL.split('.') + viewname = 'admin:%s_%s_change' % (app_label, model.lower()) + try: + link = urlresolvers.reverse(viewname, args=[obj.actor.id]) + except NoReverseMatch: + return u'%s' % (obj.actor) + return format_html(u'{}', link, obj.actor) + + return 'system' + user_url.short_description = 'User' + + def resource_url(self, obj): + + +## ... source file abbreviated to get to mark_safe examples ... + + + return format_html(u'{}', link, obj.object_repr) + resource_url.short_description = 'Resource' + + def msg_short(self, obj): + if obj.action == 2: + return '' # delete + changes = json.loads(obj.changes) + s = '' if len(changes) == 1 else 's' + fields = ', '.join(changes.keys()) + if len(fields) > MAX: + i = fields.rfind(' ', 0, MAX) + fields = fields[:i] + ' ..' + return '%d change%s: %s' % (len(changes), s, fields) + msg_short.short_description = 'Changes' + + def msg(self, obj): + if obj.action == 2: + return '' # delete + changes = json.loads(obj.changes) + msg = '' + for i, field in enumerate(sorted(changes), 1): + value = [i, field] + (['***', '***'] if field == 'password' else changes[field]) + msg += format_html('', *value) + + msg += '
    #FieldFromTo
    {}{}{}{}
    ' +~~ return mark_safe(msg) + msg.short_description = 'Changes' + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 2 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / templatetags / djng_tags.py**](https://github.com/jrief/django-angular/blob/master/djng/templatetags/djng_tags.py) + +```python +# djng_tags.py +import json + +from django.template import Library +from django.template.base import Node, NodeList, TextNode, VariableNode +from django.utils.html import format_html +~~from django.utils.safestring import mark_safe +from django.utils.translation import get_language_from_request + +from djng.core.urlresolvers import get_all_remote_methods, get_current_remote_methods + + +register = Library() + + +@register.simple_tag(name='djng_all_rmi') +def djng_all_rmi(): +~~ return mark_safe(json.dumps(get_all_remote_methods())) + + +@register.simple_tag(name='djng_current_rmi', takes_context=True) +def djng_current_rmi(context): +~~ return mark_safe(json.dumps(get_current_remote_methods(context.get('view')))) + + +@register.simple_tag(name='load_djng_urls', takes_context=True) +def djng_urls(context, *namespaces): + raise DeprecationWarning( + "load_djng_urls templatetag is deprecated and has been removed from this version of django-angular." + "Please refer to documentation for updated way to manage django urls in angular.") + + +class AngularJsNode(Node): + def __init__(self, django_nodelist, angular_nodelist, variable): + self.django_nodelist = django_nodelist + self.angular_nodelist = angular_nodelist + self.variable = variable + + def render(self, context): + if self.variable.resolve(context): + return self.angular_nodelist.render(context) + return self.django_nodelist.render(context) + + +@register.tag +def angularjs(parser, token): + bits = token.contents.split() + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 3 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_rendering.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_rendering.py) + +```python +# plugin_rendering.py +from __future__ import unicode_literals +from collections import OrderedDict + +from functools import partial + +from classytags.utils import flatten_context + +from django.contrib.sites.models import Site +from django.template import Context +from django.utils.functional import cached_property +from django.utils.module_loading import import_string +~~from django.utils.safestring import mark_safe + +from cms.cache.placeholder import get_placeholder_cache, set_placeholder_cache +from cms.toolbar.utils import ( + get_placeholder_toolbar_js, + get_plugin_toolbar_js, + get_toolbar_from_request, +) +from cms.utils import get_language_from_request +from cms.utils.conf import get_cms_setting +from cms.utils.permissions import has_plugin_permission +from cms.utils.placeholder import get_toolbar_plugin_struct, restore_sekizai_context +from cms.utils.plugins import get_plugin_restrictions + + +def _unpack_plugins(parent_plugin): + found_plugins = [] + + for plugin in parent_plugin.child_plugin_instances or []: + found_plugins.append(plugin) + + if plugin.child_plugin_instances: + found_plugins.extend(_unpack_plugins(plugin)) + return found_plugins + + + +## ... source file abbreviated to get to mark_safe examples ... + + + return False + return not self._placeholders_are_editable + + def render_placeholder(self, placeholder, context, language=None, page=None, + editable=False, use_cache=False, nodelist=None, width=None): + from sekizai.helpers import Watcher + + language = language or self.request_language + editable = editable and self._placeholders_are_editable + + if use_cache and not editable and placeholder.cache_placeholder: + use_cache = self.placeholder_cache_is_enabled() + else: + use_cache = False + + if use_cache: + cached_value = self._get_cached_placeholder_content( + placeholder=placeholder, + language=language, + ) + else: + cached_value = None + + if cached_value is not None: + restore_sekizai_context(context, cached_value['sekizai']) +~~ return mark_safe(cached_value['content']) + + context.push() + + width = width or placeholder.default_width + template = page.get_template() if page else None + + if width: + context['width'] = width + + for key, value in placeholder.get_extra_context(template).items(): + if key not in context: + context[key] = value + + if use_cache: + watcher = Watcher(context) + + plugin_content = self.render_plugins( + placeholder, + language=language, + context=context, + editable=editable, + template=template, + ) + placeholder_content = ''.join(plugin_content) + + +## ... source file abbreviated to get to mark_safe examples ... + + + site_id=self.current_site.pk, + content=content, + request=self.request, + ) + + rendered_placeholder = RenderedPlaceholder( + placeholder=placeholder, + language=language, + site_id=self.current_site.pk, + cached=use_cache, + editable=editable, + has_content=bool(placeholder_content), + ) + + if placeholder.pk not in self._rendered_placeholders: + if not self.toolbar._cache_disabled: + self.toolbar._cache_disabled = not use_cache + self._rendered_placeholders[placeholder.pk] = rendered_placeholder + + if editable: + data = self.get_editable_placeholder_context(placeholder, page=page) + data['content'] = placeholder_content + placeholder_content = self.placeholder_edit_template.format(**data) + + context.pop() +~~ return mark_safe(placeholder_content) + + def get_editable_placeholder_context(self, placeholder, page=None): + placeholder_cache = self.get_rendered_plugins_cache(placeholder) + placeholder_toolbar_js = self.get_placeholder_toolbar_js(placeholder, page) + plugin_toolbar_js_bits = (self.get_plugin_toolbar_js(plugin, page=page) + for plugin in placeholder_cache['plugins']) + context = { + 'plugin_js': ''.join(plugin_toolbar_js_bits), + 'placeholder_js': placeholder_toolbar_js, + 'placeholder_id': placeholder.pk, + } + return context + + def render_page_placeholder(self, slot, context, inherit, + page=None, nodelist=None, editable=True): + if not self.current_page: + return '' + + current_page = page or self.current_page + placeholder_cache = self._placeholders_by_page_cache + + if current_page.pk not in placeholder_cache: + self._preload_placeholders_for_page(current_page) + + + +## ... source file abbreviated to get to mark_safe examples ... + + + if not placeholder: + placeholder = instance.placeholder + + instance, plugin = instance.get_plugin_instance() + + if not instance or not plugin.render_plugin: + return '' + + context = PluginContext(context, instance, placeholder) + context = plugin.render(context, instance, placeholder.slot) + context = flatten_context(context) + + template = plugin._get_render_template(context, instance, placeholder) + template = self.templates.get_cached_template(template) + + content = template.render(context) + + for path in get_cms_setting('PLUGIN_PROCESSORS'): + processor = import_string(path) + content = processor(instance, placeholder, content, context) + + if editable: + content = self.plugin_edit_template.format(pk=instance.pk, content=content) + placeholder_cache = self._rendered_plugins_by_placeholder.setdefault(placeholder.pk, {}) + placeholder_cache.setdefault('plugins', []).append(instance) +~~ return mark_safe(content) + + def render_plugins(self, placeholder, language, context, editable=False, template=None): + plugins = self.get_plugins_to_render( + placeholder=placeholder, + template=template, + language=language, + ) + + for plugin in plugins: + plugin._placeholder_cache = placeholder + yield self.render_plugin(plugin, context, placeholder, editable) + + def _get_cached_placeholder_content(self, placeholder, language): + site_id = self.current_site.pk + site_cache = self._placeholders_content_cache.setdefault(site_id, {}) + language_cache = site_cache.setdefault(language, {}) + + if placeholder.pk not in language_cache: + cached_value = get_placeholder_cache( + placeholder, + lang=language, + site_id=site_id, + request=self.request, + ) + + +## ... source file abbreviated to get to mark_safe examples ... + + + for plugin in _unpack_plugins(plugin): + yield plugin + + def render_placeholder(self, placeholder, language, page=None): + rendered_plugins = self.render_plugins(placeholder, language=language, page=page) + plugin_js_output = ''.join(rendered_plugins) + + placeholder_toolbar_js = self.get_placeholder_toolbar_js(placeholder, page) + rendered_placeholder = RenderedPlaceholder( + placeholder=placeholder, + language=language, + site_id=self.current_site.pk, + cached=False, + editable=True, + ) + + if placeholder.pk not in self._rendered_placeholders: + self._rendered_placeholders[placeholder.pk] = rendered_placeholder + + placeholder_structure_is = self.placeholder_edit_template.format( + placeholder_id=placeholder.pk, + plugin_js=plugin_js_output, + plugin_menu_js=self.get_placeholder_plugin_menu(placeholder, page=page), + placeholder_js=placeholder_toolbar_js, + ) +~~ return mark_safe(placeholder_structure_is) + + def render_page_placeholder(self, page, placeholder, language=None): + return self.render_placeholder(placeholder, language=language, page=page) + + def render_static_placeholder(self, static_placeholder, language=None): + user = self.request.user + + if not user.has_perm('cms.edit_static_placeholder'): + return '' + + language = language or self.request_language + + placeholder = static_placeholder.draft + placeholder.is_static = True + + content = self.render_placeholder(placeholder, language=language) + + if static_placeholder.pk not in self._rendered_static_placeholders: + self._rendered_static_placeholders[static_placeholder.pk] = static_placeholder + return content + + def render_plugin(self, instance, page=None): + placeholder_cache = self._rendered_plugins_by_placeholder.setdefault(instance.placeholder_id, {}) + placeholder_cache.setdefault('plugins', []).append(instance) + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 4 from django-debug-toolbar +[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar) +([project documentation](https://github.com/jazzband/django-debug-toolbar) +and [PyPI page](https://pypi.org/project/django-debug-toolbar/)) +grants a developer detailed request-response cycle information while +developing a [Django](/django.html) web application. +The code for django-debug-toolbar is +[open source](https://github.com/jazzband/django-debug-toolbar/blob/master/LICENSE) +and maintained by the developer community group known as +[Jazzband](https://jazzband.co/). + +[**django-debug-toolbar / debug_toolbar / utils.py**](https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/./utils.py) + +```python +# utils.py +import inspect +import os.path +import re +import sys +from importlib import import_module +from itertools import chain + +import django +from django.core.exceptions import ImproperlyConfigured +from django.template import Node +from django.template.loader import render_to_string +~~from django.utils.safestring import mark_safe + +from debug_toolbar import settings as dt_settings + +try: + import threading +except ImportError: + threading = None + + +django_path = os.path.realpath(os.path.dirname(django.__file__)) + + +def get_module_path(module_name): + try: + module = import_module(module_name) + except ImportError as e: + raise ImproperlyConfigured("Error importing HIDE_IN_STACKTRACES: {}".format(e)) + else: + source_path = inspect.getsourcefile(module) + if source_path.endswith("__init__.py"): + source_path = os.path.dirname(source_path) + return os.path.realpath(source_path) + + + + +## ... source file abbreviated to get to mark_safe examples ... + + +def tidy_stacktrace(stack): + trace = [] + for frame, path, line_no, func_name, text in (f[:5] for f in stack): + if omit_path(os.path.realpath(path)): + continue + text = "".join(text).strip() if text else "" + frame_locals = ( + frame.f_locals + if dt_settings.get_config()["ENABLE_STACKTRACES_LOCALS"] + else None + ) + trace.append((path, line_no, func_name, text, frame_locals)) + return trace + + +def render_stacktrace(trace): + stacktrace = [] + for frame in trace: + params = (v for v in chain(frame[0].rsplit(os.path.sep, 1), frame[1:])) + params_dict = {str(idx): v for idx, v in enumerate(params)} + try: + stacktrace.append(params_dict) + except KeyError: + continue + +~~ return mark_safe( + render_to_string( + "debug_toolbar/panels/sql_stacktrace.html", + { + "stacktrace": stacktrace, + "show_locals": dt_settings.get_config()["ENABLE_STACKTRACES_LOCALS"], + }, + ) + ) + + +def get_template_info(): + template_info = None + cur_frame = sys._getframe().f_back + try: + while cur_frame is not None: + in_utils_module = cur_frame.f_code.co_filename.endswith( + "/debug_toolbar/utils.py" + ) + is_get_template_context = ( + cur_frame.f_code.co_name == get_template_context.__name__ + ) + if in_utils_module and is_get_template_context: + break + elif cur_frame.f_code.co_name == "render": + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 5 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / templatetags / highlighting.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/templatetags/highlighting.py) + +```python +# highlighting.py + +from django import template +from django.template import ( + Context, Node, Template, TemplateSyntaxError, Variable, +) +from django.template.defaultfilters import stringfilter +~~from django.utils.safestring import mark_safe + +try: + from pygments import highlight as pyghighlight + from pygments.lexers import get_lexer_by_name + from pygments.formatters import HtmlFormatter + HAS_PYGMENTS = True +except ImportError: # pragma: no cover + HAS_PYGMENTS = False + +register = template.Library() + + +@register.filter(is_safe=True) +@stringfilter +def parse_template(value): +~~ return mark_safe(Template(value).render(Context())) + + +class CodeNode(Node): + def __init__(self, language, nodelist, name=''): + self.language = Variable(language) + self.nodelist = nodelist + if name: + self.name = Variable(name) + else: + self.name = None + + def render(self, context): + code = self.nodelist.render(context).strip() + lexer = get_lexer_by_name(self.language.resolve(context)) + formatter = HtmlFormatter(linenos=False) + html = "" + if self.name: + name = self.name.resolve(context) + html = '
    %s
    ' % name + return html + pyghighlight(code, lexer, formatter) + + +@register.tag +def highlight(parser, token): + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 6 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / fileadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/fileadmin.py) + +```python +# fileadmin.py +from __future__ import absolute_import + +from django import forms +from django.contrib.admin.utils import unquote +from django.http import HttpResponseRedirect +from django.urls import reverse +~~from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _ + +from .. import settings +from ..models import File +from .permissions import PrimitivePermissionAwareModelAdmin +from .tools import AdminContext, admin_url_params_encoded, popup_status + + +class FileAdminChangeFrom(forms.ModelForm): + class Meta(object): + model = File + exclude = () + + +class FileAdmin(PrimitivePermissionAwareModelAdmin): + list_display = ('label',) + list_per_page = 10 + search_fields = ['name', 'original_filename', 'sha1', 'description'] + raw_id_fields = ('owner',) + readonly_fields = ('sha1', 'display_canonical') + + form = FileAdminChangeFrom + + @classmethod + + +## ... source file abbreviated to get to mark_safe examples ... + + + if parent_folder: + url = reverse('admin:filer-directory_listing', + kwargs={'folder_id': parent_folder.id}) + else: + url = reverse('admin:filer-directory_listing-unfiled_images') + url = "{0}{1}".format( + url, + admin_url_params_encoded(request) + ) + return HttpResponseRedirect(url) + + return super(FileAdmin, self).delete_view( + request=request, object_id=object_id, + extra_context=extra_context) + + def get_model_perms(self, request): + return { + 'add': False, + 'change': False, + 'delete': False, + } + + def display_canonical(self, instance): + canonical = instance.canonical_url + if canonical: +~~ return mark_safe('%s' % (canonical, canonical)) + else: + return '-' + display_canonical.allow_tags = True + display_canonical.short_description = _('canonical URL') + + +FileAdmin.fieldsets = FileAdmin.build_fieldsets() + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 7 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / widgets.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./widgets.py) + +```python +# widgets.py +from collections.abc import Iterable +from copy import deepcopy +from itertools import chain +from re import search, sub + +from django import forms +from django.db.models.fields import BLANK_CHOICE_DASH +from django.forms.utils import flatatt +from django.utils.datastructures import MultiValueDict +from django.utils.encoding import force_str +from django.utils.http import urlencode +~~from django.utils.safestring import mark_safe +from django.utils.translation import gettext as _ + + +class LinkWidget(forms.Widget): + def __init__(self, attrs=None, choices=()): + super().__init__(attrs) + + self.choices = choices + + def value_from_datadict(self, data, files, name): + value = super().value_from_datadict(data, files, name) + self.data = data + return value + + def render(self, name, value, attrs=None, choices=(), renderer=None): + if not hasattr(self, 'data'): + self.data = {} + if value is None: + value = '' + final_attrs = self.build_attrs(self.attrs, extra_attrs=attrs) + output = ['' % flatatt(final_attrs)] + options = self.render_options(choices, [value], name) + if options: + output.append(options) + output.append('') +~~ return mark_safe('\n'.join(output)) + + def render_options(self, choices, selected_choices, name): + selected_choices = set(force_str(v) for v in selected_choices) + output = [] + for option_value, option_label in chain(self.choices, choices): + if isinstance(option_label, (list, tuple)): + for option in option_label: + output.append( + self.render_option(name, selected_choices, *option)) + else: + output.append( + self.render_option(name, selected_choices, + option_value, option_label)) + return '\n'.join(output) + + def render_option(self, name, selected_choices, + option_value, option_label): + option_value = force_str(option_value) + if option_label == BLANK_CHOICE_DASH[0][1]: + option_label = _("All") + data = self.data.copy() + data[name] = option_value + selected = data == self.data or option_value in selected_choices + try: + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 8 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / widgets.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./widgets.py) + +```python +# widgets.py +import datetime +import re +from itertools import chain + +import django +from django import forms +from django.conf import settings +from django.forms.widgets import FILE_INPUT_CONTRADICTION +from django.template import loader +from django.utils import datetime_safe, formats +from django.utils.dates import MONTHS +from django.utils.encoding import force_str +from django.utils.html import conditional_escape +~~from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + +from .compat import MULTIVALUE_DICT_TYPES, flatten_contexts + + +from django.forms.utils import to_current_timezone + + +RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$') + + +__all__ = ( + 'TextInput', 'PasswordInput', 'HiddenInput', 'ClearableFileInput', + 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', + 'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple', + 'RadioSelect', 'CheckboxSelectMultiple', 'SearchInput', 'RangeInput', + 'ColorInput', 'EmailInput', 'URLInput', 'PhoneNumberInput', 'NumberInput', + 'IPAddressInput', 'MultiWidget', 'Widget', 'SplitDateTimeWidget', + 'SplitHiddenDateTimeWidget', 'MultipleHiddenInput', 'SelectDateWidget', + 'SlugInput', +) + + +class Widget(forms.Widget): + + +## ... source file abbreviated to get to mark_safe examples ... + + + +class HiddenInput(Input): + template_name = 'floppyforms/hidden.html' + input_type = 'hidden' + + +class MultipleHiddenInput(HiddenInput): + def __init__(self, attrs=None, choices=()): + super(MultipleHiddenInput, self).__init__(attrs) + self.choices = choices + + def render(self, name, value, attrs=None, choices=(), renderer=None): + if value is None: + value = [] + + final_attrs = self.build_attrs(attrs) + id_ = final_attrs.get('id', None) + inputs = [] + for i, v in enumerate(value): + input_attrs = final_attrs.copy() + if id_: + input_attrs['id'] = '%s_%s' % (id_, i) + input_ = HiddenInput() + input_.is_required = self.is_required + inputs.append(input_.render(name, force_str(v), input_attrs, renderer=renderer)) +~~ return mark_safe("\n".join(inputs)) + + def value_from_datadict(self, data, files, name): + if isinstance(data, MULTIVALUE_DICT_TYPES): + return data.getlist(name) + return data.get(name, None) + + +class SlugInput(TextInput): + template_name = 'floppyforms/slug.html' + + def get_context(self, name, value, attrs): + context = super(SlugInput, self).get_context(name, value, attrs) + context['attrs']['pattern'] = r"[-\w]+" + return context + + +class IPAddressInput(TextInput): + template_name = 'floppyforms/ipaddress.html' + + ip_pattern = (r"(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25" + r"[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}") + + def get_context(self, name, value, attrs): + context = super(IPAddressInput, self).get_context(name, value, attrs) + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 9 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / resources.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./resources.py) + +```python +# resources.py +import functools +import logging +import tablib +import traceback +from collections import OrderedDict +from copy import deepcopy + +from diff_match_patch import diff_match_patch + +import django +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.core.management.color import no_style +from django.core.paginator import Paginator +from django.db import DEFAULT_DB_ALIAS, connections +from django.db.models.fields.related import ForeignObjectRel +from django.db.models.query import QuerySet +from django.db.transaction import ( + TransactionManagementError, + atomic, + savepoint, + savepoint_commit, + savepoint_rollback +) +from django.utils.encoding import force_str +~~from django.utils.safestring import mark_safe + +from . import widgets +from .fields import Field +from .instance_loaders import ModelInstanceLoader +from .results import Error, Result, RowResult +from .utils import atomic_if_using_transaction + +if django.VERSION[0] >= 3: + from django.core.exceptions import FieldDoesNotExist +else: + from django.db.models.fields import FieldDoesNotExist + + +logger = logging.getLogger(__name__) +logger.addHandler(logging.NullHandler()) + +USE_TRANSACTIONS = getattr(settings, 'IMPORT_EXPORT_USE_TRANSACTIONS', True) +CHUNK_SIZE = getattr(settings, 'IMPORT_EXPORT_CHUNK_SIZE', 1) + + +def get_related_model(field): + if hasattr(field, 'related_model'): + return field.related_model + if field.rel: + + +## ... source file abbreviated to get to mark_safe examples ... + + + if not option.startswith('_')]: + setattr(meta, option, getattr(options, option)) + new_class._meta = meta + + return new_class + + +class Diff: + def __init__(self, resource, instance, new): + self.left = self._export_resource_fields(resource, instance) + self.right = [] + self.new = new + + def compare_with(self, resource, instance, dry_run=False): + self.right = self._export_resource_fields(resource, instance) + + def as_html(self): + data = [] + dmp = diff_match_patch() + for v1, v2 in zip(self.left, self.right): + if v1 != v2 and self.new: + v1 = "" + diff = dmp.diff_main(force_str(v1), force_str(v2)) + dmp.diff_cleanupSemantic(diff) + html = dmp.diff_prettyHtml(diff) +~~ html = mark_safe(html) + data.append(html) + return data + + def _export_resource_fields(self, resource, instance): + return [resource.export_field(f, instance) if instance else "" for f in resource.get_user_visible_fields()] + + +class Resource(metaclass=DeclarativeMetaclass): + + def __init__(self): + self.fields = deepcopy(self.fields) + + self.create_instances = list() + self.update_instances = list() + self.delete_instances = list() + + @classmethod + def get_result_class(self): + return Result + + @classmethod + def get_row_result_class(self): + return RowResult + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 10 from django-inline-actions +[django-inline-actions](https://github.com/escaped/django-inline-actions) +([PyPI package information](https://pypi.org/project/django-inline-actions/)) +is an extension that adds actions to the [Django](/django.html) +Admin InlineModelAdmin and ModelAdmin changelists. The project is open +sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/escaped/django-inline-actions/blob/master/LICENSE). + +[**django-inline-actions / inline_actions / admin.py**](https://github.com/escaped/django-inline-actions/blob/master/inline_actions/./admin.py) + +```python +# admin.py +from django.apps import apps +from django.contrib import admin +from django.http import HttpResponse +from django.shortcuts import redirect +from django.urls import reverse +~~from django.utils.safestring import mark_safe +from django.utils.text import capfirst +from django.utils.translation import ugettext_lazy as _ + + +class InlineActionException(Exception): + pass + + +class ActionNotCallable(InlineActionException): + def __init__(self, model_admin, action, *args, **kwargs): + super().__init__(*args, **kwargs) + self.model_admin = model_admin + self.action = action + + +class BaseInlineActionsMixin: + INLINE_MODEL_ADMIN = 'inline' + MODEL_ADMIN = 'admin' + + inline_actions = [] + + def get_inline_actions(self, request, obj=None): + if self.inline_actions is None: + return [] + + +## ... source file abbreviated to get to mark_safe examples ... + + + css_handler = getattr( + self, 'get_{}_css'.format(action_name), None) + if callable(css_handler): + css_classes = css_handler(obj=obj) + else: + try: + css_classes = action_func.css_classes + except AttributeError: + css_classes = '' + + action_data = [ + self.__class__.__name__.lower(), + self._get_admin_type(), + action_name, + obj._meta.app_label, + obj._meta.model_name, + str(obj.pk), + ] + buttons.append( + ''.format( + '_action__{}'.format('__'.join(action_data)), + description, + css_classes, + ) + ) +~~ return mark_safe('
    {}
    '.format( + ''.join(buttons) + )) + render_inline_actions.short_description = _("Actions") + render_inline_actions.allow_tags = True + + +class InlineActionsMixin(BaseInlineActionsMixin): + def render_inline_actions(self, obj=None): + html = super().render_inline_actions(obj=obj) +~~ return mark_safe('

    {}

    '.format(html)) + + render_inline_actions.short_description = _("Actions") + render_inline_actions.allow_tags = True + + def get_fields(self, request, obj=None): + self._request = request + + fields = super().get_fields(request, obj) + if self.inline_actions is not None: # is it explicitly disabled? + fields = list(fields) + if 'render_inline_actions' not in fields: + fields.append('render_inline_actions') + return fields + + +class InlineActionsModelAdminMixin(BaseInlineActionsMixin): + class Media: + css = { + "all": ( + "inline_actions/css/inline_actions.css", + ) + } + + def get_list_display(self, request): + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 11 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / templatetags / jet_tags.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/templatetags/jet_tags.py) + +```python +# jet_tags.py +from __future__ import unicode_literals +import json +import os +from django import template +try: + from django.core.urlresolvers import reverse +except ImportError: # Django 1.11 + from django.urls import reverse + +from django.forms import CheckboxInput, ModelChoiceField, Select, ModelMultipleChoiceField, SelectMultiple +from django.contrib.admin.widgets import RelatedFieldWidgetWrapper +from django.utils.formats import get_format +~~from django.utils.safestring import mark_safe +from django.utils.encoding import smart_text +from jet import settings, VERSION +from jet.models import Bookmark +from jet.utils import get_model_instance_label, get_model_queryset, get_possible_language_codes, \ + get_admin_site, get_menu_items + +try: + from urllib.parse import parse_qsl +except ImportError: + from urlparse import parse_qsl + + +register = template.Library() +assignment_tag = register.assignment_tag if hasattr(register, 'assignment_tag') else register.simple_tag + + +@assignment_tag +def jet_get_date_format(): + return get_format('DATE_INPUT_FORMATS')[0] + + +@assignment_tag +def jet_get_time_format(): + return get_format('TIME_INPUT_FORMATS')[0] + + +## ... source file abbreviated to get to mark_safe examples ... + + + return jet_sibling_object(context, False) + + +@assignment_tag(takes_context=True) +def jet_next_object(context): + return jet_sibling_object(context, True) + + +@assignment_tag(takes_context=True) +def jet_popup_response_data(context): + if context.get('popup_response_data'): + return context['popup_response_data'] + + return json.dumps({ + 'action': context.get('action'), + 'value': context.get('value') or context.get('pk_value'), + 'obj': smart_text(context.get('obj')), + 'new_value': context.get('new_value') + }) + + +@assignment_tag(takes_context=True) +def jet_delete_confirmation_context(context): + if context.get('deletable_objects') is None and context.get('deleted_objects') is None: + return '' +~~ return mark_safe('

    ') + + +@assignment_tag +def jet_static_translation_urls(): + language_codes = get_possible_language_codes() + + urls = [] + url_templates = [ + 'jet/js/i18n/jquery-ui/datepicker-__LANGUAGE_CODE__.js', + 'jet/js/i18n/jquery-ui-timepicker/jquery.ui.timepicker-__LANGUAGE_CODE__.js', + 'jet/js/i18n/select2/__LANGUAGE_CODE__.js' + ] + + static_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'static') + + for tpl in url_templates: + for language_code in language_codes: + url = tpl.replace('__LANGUAGE_CODE__', language_code) + path = os.path.join(static_dir, url) + + if os.path.exists(path): + urls.append(url) + break + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 12 from django-markdown-view +[django-markdown-view](https://github.com/rgs258/django-markdown-view) +([PyPI package information](https://pypi.org/project/django-markdown-view/)) +is a Django extension for serving [Markdown](/markdown.html) files as +[Django templates](/django-templates.html). The project is open +sourced under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/rgs258/django-markdown-view/blob/master/LICENSE). + +[**django-markdown-view / markdown_view / views.py**](https://github.com/rgs258/django-markdown-view/blob/master/markdown_view/./views.py) + +```python +# views.py +import logging + +import markdown +from django.conf import settings +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin +from django.template import Engine, Template, Context +from django.template.loader import render_to_string +~~from django.utils.safestring import mark_safe +from django.views.generic import TemplateView +from markdown_view.constants import ( + DEFAULT_MARKDOWN_VIEW_LOADERS, + DEFAULT_MARKDOWN_VIEW_EXTENSIONS, DEFAULT_MARKDOWN_VIEW_TEMPLATE, + DEFAULT_MARKDOWN_VIEW_USE_REQUEST_CONTEXT, DEFAULT_MARKDOWN_VIEW_EXTRA_CONTEXT, +) + +logger = logging.getLogger(__name__) + + +class MarkdownView(TemplateView): + file_name = None + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + if self.file_name: + engine = Engine(loaders=getattr( + settings, "MARKDOWN_VIEW_LOADERS", DEFAULT_MARKDOWN_VIEW_LOADERS) + ) + template = engine.get_template(self.file_name) + md = markdown.Markdown(extensions=getattr( + settings, + "MARKDOWN_VIEW_EXTENSIONS", + DEFAULT_MARKDOWN_VIEW_EXTENSIONS + )) + template = Template( + "{{% load static %}}{}".format(md.convert(template.source)) + ) + render_context_base = {} + if getattr( + settings, + "MARKDOWN_VIEW_USE_REQUEST_CONTEXT", + DEFAULT_MARKDOWN_VIEW_USE_REQUEST_CONTEXT + ): + render_context_base = context + render_context = Context({ + **render_context_base, + **(getattr( + settings, + "MARKDOWN_VIEW_EXTRA_CONTEXT", + DEFAULT_MARKDOWN_VIEW_EXTRA_CONTEXT + )) + }) + context.update({ +~~ "markdown_content": mark_safe(template.render(render_context)), +~~ "markdown_toc": mark_safe(md.toc), +~~ "page_title": mark_safe(md.toc_tokens[0]['name']), + }) + return context + + template_name = getattr( + settings, + "MARKDOWN_VIEW_TEMPLATE", + DEFAULT_MARKDOWN_VIEW_TEMPLATE + ) + + +class LoggedInMarkdownView(LoginRequiredMixin, MarkdownView): + pass + + +class StaffMarkdownView(UserPassesTestMixin, MarkdownView): + def test_func(self): + return self.request.user.is_active and self.request.user.is_staff + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 13 from django-mongonaut +[django-mongonaut](https://github.com/jazzband/django-mongonaut) +([project documentation](https://django-mongonaut.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-mongonaut/)) +provides an introspective interface for working with +[MongoDB](/mongodb.html) via mongoengine. The project has its own new code +to map MongoDB to the [Django](/django.html) Admin interface. + +django-mongonaut's highlighted features include automatic introspection of +mongoengine documents, the ability to constrain who sees what and what +they can do and full control for adding, editing and deleting documents. + +The django-mongonaut project is open sourced under the +[MIT License](https://github.com/jazzband/django-mongonaut/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-mongonaut / mongonaut / templatetags / mongonaut_tags.py**](https://github.com/jazzband/django-mongonaut/blob/master/mongonaut/templatetags/mongonaut_tags.py) + +```python +# mongonaut_tags.py + +from django import template +from django.urls import reverse +~~from django.utils.safestring import mark_safe + +from bson.objectid import ObjectId +from mongoengine import Document +from mongoengine.fields import URLField + +register = template.Library() + + +@register.simple_tag() +def get_document_value(document, key): + value = getattr(document, key) + if isinstance(value, ObjectId): + return value + + if isinstance(document._fields.get(key), URLField): +~~ return mark_safe("""{1}""".format(value, value)) + + if isinstance(value, Document): + app_label = value.__module__.replace(".models", "") + document_name = value._class_name + url = reverse( + "document_detail", + kwargs={'app_label': app_label, 'document_name': document_name, + 'id': value.id}) +~~ return mark_safe("""{1}""".format(url, value)) + + return value + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 14 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / templatetags / pipeline.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/templatetags/pipeline.py) + +```python +# pipeline.py +import logging +import subprocess + +from django.contrib.staticfiles.storage import staticfiles_storage + +from django import template +from django.template.base import Context, VariableDoesNotExist +from django.template.loader import render_to_string +~~from django.utils.safestring import mark_safe + +from ..collector import default_collector +from ..conf import settings +from ..exceptions import CompilerError +from ..packager import Packager, PackageNotFound +from ..utils import guess_type + +logger = logging.getLogger(__name__) + +register = template.Library() + + +class PipelineMixin(object): + request = None + _request_var = None + + @property + def request_var(self): + if not self._request_var: + self._request_var = template.Variable('request') + return self._request_var + + def package_for(self, package_name, package_type): + package = { + + +## ... source file abbreviated to get to mark_safe examples ... + + + 'command': subprocess.list2cmdline(e.command), + 'errors': e.error_output, + }) + + +class StylesheetNode(PipelineMixin, template.Node): + def __init__(self, name): + self.name = name + + def render(self, context): + super(StylesheetNode, self).render(context) + package_name = template.Variable(self.name).resolve(context) + + try: + package = self.package_for(package_name, 'css') + except PackageNotFound: + logger.warn("Package %r is unknown. Check PIPELINE['STYLESHEETS'] in your settings.", package_name) + return '' # fail silently, do not return anything if an invalid group is specified + return self.render_compressed(package, package_name, 'css') + + def render_css(self, package, path): + template_name = package.template_name or "pipeline/css.html" + context = package.extra_context + context.update({ + 'type': guess_type(path, 'text/css'), +~~ 'url': mark_safe(staticfiles_storage.url(path)) + }) + return render_to_string(template_name, context) + + def render_individual_css(self, package, paths, **kwargs): + tags = [self.render_css(package, path) for path in paths] + return '\n'.join(tags) + + def render_error_css(self, package_name, e): + return super(StylesheetNode, self).render_error( + 'CSS', package_name, e) + + +class JavascriptNode(PipelineMixin, template.Node): + def __init__(self, name): + self.name = name + + def render(self, context): + super(JavascriptNode, self).render(context) + package_name = template.Variable(self.name).resolve(context) + + try: + package = self.package_for(package_name, 'js') + except PackageNotFound: + logger.warn("Package %r is unknown. Check PIPELINE['JAVASCRIPT'] in your settings.", package_name) + return '' # fail silently, do not return anything if an invalid group is specified + return self.render_compressed(package, package_name, 'js') + + def render_js(self, package, path): + template_name = package.template_name or "pipeline/js.html" + context = package.extra_context + context.update({ + 'type': guess_type(path, 'text/javascript'), +~~ 'url': mark_safe(staticfiles_storage.url(path)) + }) + return render_to_string(template_name, context) + + def render_inline(self, package, js): + context = package.extra_context + context.update({ + 'source': js + }) + return render_to_string("pipeline/inline_js.html", context) + + def render_individual_js(self, package, paths, templates=None): + tags = [self.render_js(package, js) for js in paths] + if templates: + tags.append(self.render_inline(package, templates)) + return '\n'.join(tags) + + def render_error_js(self, package_name, e): + return super(JavascriptNode, self).render_error( + 'JavaScript', package_name, e) + + +@register.tag +def stylesheet(parser, token): + try: + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 15 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / templatetags / rest_framework.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/templatetags/rest_framework.py) + +```python +# rest_framework.py +import re +from collections import OrderedDict + +from django import template +from django.template import loader +from django.urls import NoReverseMatch, reverse +from django.utils.encoding import force_str, iri_to_uri +from django.utils.html import escape, format_html, smart_urlquote +~~from django.utils.safestring import SafeData, mark_safe + +from rest_framework.compat import apply_markdown, pygments_highlight +from rest_framework.renderers import HTMLFormRenderer +from rest_framework.utils.urls import replace_query_param + +register = template.Library() + +class_re = re.compile(r'(?<=class=["\'])(.*)(?=["\'])') + + +@register.tag(name='code') +def highlight_code(parser, token): + code = token.split_contents()[-1] + nodelist = parser.parse(('endcode',)) + parser.delete_first_token() + return CodeNode(code, nodelist) + + +class CodeNode(template.Node): + style = 'emacs' + + def __init__(self, lang, code): + self.lang = lang + self.nodelist = code + + +## ... source file abbreviated to get to mark_safe examples ... + + + text = self.nodelist.render(context) + return pygments_highlight(text, self.lang, self.style) + + +@register.filter() +def with_location(fields, location): + return [ + field for field in fields + if field.location == location + ] + + +@register.simple_tag +def form_for_link(link): + import coreschema + properties = OrderedDict([ + (field.name, field.schema or coreschema.String()) + for field in link.fields + ]) + required = [ + field.name + for field in link.fields + if field.required + ] + schema = coreschema.Object(properties=properties, required=required) +~~ return mark_safe(coreschema.render_to_form(schema)) + + +@register.simple_tag +def render_markdown(markdown_text): + if apply_markdown is None: + return markdown_text +~~ return mark_safe(apply_markdown(markdown_text)) + + +@register.simple_tag +def get_pagination_html(pager): + return pager.to_html() + + +@register.simple_tag +def render_form(serializer, template_pack=None): + style = {'template_pack': template_pack} if template_pack else {} + renderer = HTMLFormRenderer() + return renderer.render(serializer.data, None, {'style': style}) + + +@register.simple_tag +def render_field(field, style): + renderer = style.get('renderer', HTMLFormRenderer()) + return renderer.render_field(field, style) + + +@register.simple_tag +def optional_login(request): + try: + login_url = reverse('rest_framework:login') + except NoReverseMatch: + return '' + + snippet = "
  • Log in
  • " + snippet = format_html(snippet, href=login_url, next=escape(request.path)) + +~~ return mark_safe(snippet) + + +@register.simple_tag +def optional_docs_login(request): + try: + login_url = reverse('rest_framework:login') + except NoReverseMatch: + return 'log in' + + snippet = "log in" + snippet = format_html(snippet, href=login_url, next=escape(request.path)) + +~~ return mark_safe(snippet) + + +@register.simple_tag +def optional_logout(request, user): + try: + logout_url = reverse('rest_framework:logout') + except NoReverseMatch: + snippet = format_html('', user=escape(user)) +~~ return mark_safe(snippet) + + snippet = """""" + snippet = format_html(snippet, user=escape(user), href=logout_url, next=escape(request.path)) + +~~ return mark_safe(snippet) + + +@register.simple_tag +def add_query_param(request, key, val): + iri = request.get_full_path() + uri = iri_to_uri(iri) + return escape(replace_query_param(uri, key, val)) + + +@register.filter +def as_string(value): + if value is None: + return '' + return '%s' % value + + +@register.filter +def as_list_of_strings(value): + return [ + '' if (item is None) else ('%s' % item) + for item in value + ] + + +@register.filter +def add_class(value, css_class): + html = str(value) + match = class_re.search(html) + if match: + m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class, + css_class, css_class), + match.group(1)) + if not m: +~~ return mark_safe(class_re.sub(match.group(1) + " " + css_class, + html)) + else: +~~ return mark_safe(html.replace('>', ' class="%s">' % css_class, 1)) + return value + + +@register.filter +def format_value(value): + if getattr(value, 'is_hyperlink', False): + name = str(value.obj) +~~ return mark_safe('%s' % (value, escape(name))) + if value is None or isinstance(value, bool): +~~ return mark_safe('%s' % {True: 'true', False: 'false', None: 'null'}[value]) + elif isinstance(value, list): + if any([isinstance(item, (list, dict)) for item in value]): + template = loader.get_template('rest_framework/admin/list_value.html') + else: + template = loader.get_template('rest_framework/admin/simple_list_value.html') + context = {'value': value} + return template.render(context) + elif isinstance(value, dict): + template = loader.get_template('rest_framework/admin/dict_value.html') + context = {'value': value} + return template.render(context) + elif isinstance(value, str): + if ( + (value.startswith('http:') or value.startswith('https:')) and not + re.search(r'\s', value) + ): +~~ return mark_safe('{value}'.format(value=escape(value))) + elif '@' in value and not re.search(r'\s', value): +~~ return mark_safe('{value}'.format(value=escape(value))) + elif '\n' in value: +~~ return mark_safe('
    %s
    ' % escape(value)) + return str(value) + + +@register.filter +def items(value): + if value is None: + return [] + return value.items() + + +@register.filter +def data(value): + return value.data + + +@register.filter +def schema_links(section, sec_key=None): + NESTED_FORMAT = '%s > %s' # this format is used in docs/js/api.js:normalizeKeys + links = section.links + if section.data: + data = section.data.items() + for sub_section_key, sub_section in data: + new_links = schema_links(sub_section, sec_key=sub_section_key) + links.update(new_links) + + +## ... source file abbreviated to get to mark_safe examples ... + + + url = None + nofollow_attr = ' rel="nofollow"' if nofollow else '' + if simple_url_re.match(middle): + url = smart_urlquote_wrapper(middle) + elif simple_url_2_re.match(middle): + url = smart_urlquote_wrapper('http://%s' % middle) + elif ':' not in middle and simple_email_re.match(middle): + local, domain = middle.rsplit('@', 1) + try: + domain = domain.encode('idna').decode('ascii') + except UnicodeError: + continue + url = 'mailto:%s@%s' % (local, domain) + nofollow_attr = '' + + if url: + trimmed = trim_url(middle) + lead, trail = conditional_escape(lead), conditional_escape(trail) + url, trimmed = conditional_escape(url), conditional_escape(trimmed) + middle = '%s' % (url, nofollow_attr, trimmed) + words[i] = '%s%s%s' % (lead, middle, trail) + else: + words[i] = conditional_escape(word) + else: + words[i] = conditional_escape(word) +~~ return mark_safe(''.join(words)) + + +@register.filter +def break_long_headers(header): + if len(header) > 160 and ',' in header: +~~ header = mark_safe('
    ' + ',
    '.join(header.split(','))) + return header + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 16 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / fields.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./fields.py) + +```python +# fields.py +from typing import Optional + +from django import template +from django.template.base import Parser, Token +from django.forms import ChoiceField +~~from django.utils.safestring import mark_safe + +from .compat import TOKEN_BLOCK +from .templatetags.sitetree import sitetree_tree +from .utils import get_tree_model, get_tree_item_model +from .settings import ITEMS_FIELD_ROOT_ID + +if False: # pragma: nocover + from .models import TreeItemBase, TreeBase # noqa + + +MODEL_TREE_CLASS = get_tree_model() +MODEL_TREE_ITEM_CLASS = get_tree_item_model() + + +class TreeItemChoiceField(ChoiceField): + template: str = 'admin/sitetree/tree/tree_combo.html' + root_title: str = '---------' + + def __init__( + self, + tree: 'TreeBase' = None, + required: bool = True, + widget=None, + label=None, + + +## ... source file abbreviated to get to mark_safe examples ... + + + if not tree: + return + + if isinstance(tree, MODEL_TREE_CLASS): + tree = tree.alias + + self.tree = tree + self.choices = self._build_choices() + + def _build_choices(self): + tree_token = f'sitetree_tree from "{self.tree}" template "{self.template}"' + + context_kwargs = {'current_app': 'admin'} + context = template.Context(context_kwargs) + context.update({'request': object()}) + + choices_str = sitetree_tree( + Parser(None), Token(token_type=TOKEN_BLOCK, contents=tree_token) + ).render(context) + + tree_choices = [(ITEMS_FIELD_ROOT_ID, self.root_title)] + + for line in choices_str.splitlines(): + if line.strip(): + splitted = line.split(':::') +~~ tree_choices.append((splitted[0], mark_safe(splitted[1]))) + + return tree_choices + + def clean(self, value): + if not value: + return None + + try: + return MODEL_TREE_ITEM_CLASS.objects.get(pk=value) + + except MODEL_TREE_ITEM_CLASS.DoesNotExist: + return None + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 17 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / columns / checkboxcolumn.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/columns/checkboxcolumn.py) + +```python +# checkboxcolumn.py +~~from django.utils.safestring import mark_safe + +from django_tables2.utils import Accessor, AttributeDict + +from .base import Column, library + + +@library.register +class CheckBoxColumn(Column): + + def __init__(self, attrs=None, checked=None, **extra): + self.checked = checked + kwargs = {"orderable": False, "attrs": attrs} + kwargs.update(extra) + super().__init__(**kwargs) + + @property + def header(self): + default = {"type": "checkbox"} + general = self.attrs.get("input") + specific = self.attrs.get("th__input") + attrs = AttributeDict(default, **(specific or general or {})) +~~ return mark_safe("" % attrs.as_html()) + + def render(self, value, bound_column, record): + default = {"type": "checkbox", "name": bound_column.name, "value": value} + if self.is_checked(value, record): + default.update({"checked": "checked"}) + + general = self.attrs.get("input") + specific = self.attrs.get("td__input") + attrs = AttributeDict(default, **(specific or general or {})) +~~ return mark_safe("" % attrs.as_html()) + + def is_checked(self, value, record): + if self.checked is None: + return False + if self.checked is True: + return True + + if callable(self.checked): + return bool(self.checked(value, record)) + + checked = Accessor(self.checked) + if checked in record: + return bool(record[checked]) + return False + + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 18 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / forms.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./forms.py) + +```python +# forms.py + "WikiSlugField", + "SpamProtectionMixin", + "CreateRootForm", + "MoveForm", + "EditForm", + "SelectWidgetBootstrap", + "TextInputPrepend", + "CreateForm", + "DeleteForm", + "PermissionsForm", + "DirFilterForm", + "SearchForm", +] + +from datetime import timedelta + +from django import forms +from django.apps import apps +from django.contrib.auth import get_user_model +from django.core import validators +from django.core.validators import RegexValidator +from django.forms.widgets import HiddenInput +from django.shortcuts import get_object_or_404 +from django.urls import Resolver404, resolve +from django.utils import timezone +~~from django.utils.safestring import mark_safe +from django.utils.translation import gettext, gettext_lazy as _, pgettext_lazy +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.plugins.base import PluginSettingsFormMixin +from wiki.editors import getEditor + +from .forms_account_handling import UserCreationForm, UserUpdateForm + +validate_slug_numbers = RegexValidator( + r"^[0-9]+$", + _("A 'slug' cannot consist solely of numbers."), + "invalid", + inverse_match=True, +) + + +class WikiSlugField(forms.CharField): + + default_validators = [validators.validate_slug, validate_slug_numbers] + + def __init__(self, *args, **kwargs): + self.allow_unicode = kwargs.pop("allow_unicode", False) + + +## ... source file abbreviated to get to mark_safe examples ... + + + self.check_spam() + return self.cleaned_data + + +class SelectWidgetBootstrap(forms.Select): + + def __init__(self, attrs=None, choices=()): + if attrs is None: + attrs = {"class": ""} + elif "class" not in attrs: + attrs["class"] = "" + attrs["class"] += " form-control" + + super().__init__(attrs, choices) + + +class TextInputPrepend(forms.TextInput): + template_name = "wiki/forms/text.html" + + def __init__(self, *args, **kwargs): + self.prepend = kwargs.pop("prepend", "") + super().__init__(*args, **kwargs) + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) +~~ context["prepend"] = mark_safe(self.prepend) + return context + + +class CreateForm(forms.Form, SpamProtectionMixin): + def __init__(self, request, urlpath_parent, *args, **kwargs): + super().__init__(*args, **kwargs) + self.request = request + self.urlpath_parent = urlpath_parent + + title = forms.CharField(label=_("Title"),) + slug = WikiSlugField( + label=_("Slug"), + help_text=_( + "This will be the address where your article can be found. Use only alphanumeric characters and - or _.
    Note: If you change the slug later on, links pointing to this article are not updated." + ), + max_length=models.URLPath.SLUG_MAX_LENGTH, + ) + content = forms.CharField( + label=_("Contents"), required=False, widget=getEditor().get_widget() + ) # @UndefinedVariable + + summary = forms.CharField( + label=pgettext_lazy("Revision comment", "Summary"), + help_text=_("Write a brief message for the article's history log."), + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 19 from elasticsearch-django +[elasticsearch-django](https://github.com/yunojuno/elasticsearch-django) +([PyPI package information](https://pypi.org/project/elasticsearch-django/)) +is a [Django](/django.html) app for managing +[ElasticSearch](https://github.com/elastic/elasticsearch) indexes +populated by [Django ORM](/django-orm.html) models. The project is +available as open source under the +[MIT license](https://github.com/yunojuno/elasticsearch-django/blob/master/LICENSE). + +[**elasticsearch-django / elasticsearch_django / admin.py**](https://github.com/yunojuno/elasticsearch-django/blob/master/elasticsearch_django/./admin.py) + +```python +# admin.py +import logging + +import simplejson as json # simplejson supports Decimal serialization +from django.contrib import admin +from django.template.defaultfilters import truncatechars, truncatewords +~~from django.utils.safestring import mark_safe + +from .models import SearchQuery + +logger = logging.getLogger(__name__) + + +def pprint(data: dict) -> str: + pretty = json.dumps(data, sort_keys=True, indent=4, separators=(",", ": ")) + html = pretty.replace(" ", " ").replace("\n", "
    ") +~~ return mark_safe("%s" % html) + + +class SearchQueryAdmin(admin.ModelAdmin): + + list_display = ( + "id", + "user", + "search_terms_", + "total_hits", + "returned_", + "min_", + "max_", + "reference", + "executed_at", + ) + list_filter = ("index", "query_type") + search_fields = ("search_terms", "user__first_name", "user__last_name", "reference") + exclude = ("hits", "query", "page") + readonly_fields = ( + "user", + "index", + "search_terms", + "query_type", + "total_hits", + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 20 from register +[register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is +open source under the +[GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). +This web application makes it easier for people to register as organ donors. +You can see the application live at +[https://register.organize.org/](https://register.organize.org/). + +[**register / registration / forms.py**](https://github.com/ORGAN-IZE/register/blob/master/registration/./forms.py) + +```python +# forms.py +from __future__ import unicode_literals + +import logging +import re +import collections +import datetime + +import django.forms +import django.forms.utils +import django.forms.widgets +import django.core.validators +import django.core.exceptions +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ +~~from django.utils.safestring import mark_safe + +import form_utils.forms +import requests +import dateutil.parser +import validate_email + +logger = logging.getLogger(__name__) + + +REGISTRATION_CONFIGURATION_NAME = 'registration_configuration' + +RE_NON_DECIMAL = re.compile(r'[^\d]+') +RE_NON_ALPHA = re.compile('[\W]+') +RE_POSTAL_CODE = re.compile(r'^[0-9]{5}$') +validate_postal_code = django.core.validators.RegexValidator( + RE_POSTAL_CODE, _("Enter a valid postal code consisting 5 numbers."), 'invalid') + + +CHOICES_GENDER = ( + ('M', _('Male')), + ('F', _('Female')), +) + + + + +## ... source file abbreviated to get to mark_safe examples ... + + + + d = { + 'label': label, + } + + if field_type == 'string': + d['required'] = is_required + d['initial'] = initial + if choices and is_editable: + d['help_text'] = help_text + d['choices'] = choices + d['widget'] = django.forms.RadioSelect + field_class = django.forms.ChoiceField + elif field_name == 'email': + d['max_length'] = max_length + d['help_text'] = help_text + field_class = django.forms.EmailField + elif field_name == 'license_id' \ + and 'license_id_formats' in conf: + d['max_length'] = max_length + license_id_formats = '{}{}{}'.format( + _('

    Valid state License IDs should look like: '), + ', '.join(map(unicode, conf['license_id_formats'])), '

    ') + help_text = '{}{}{}'.format('

    ', unicode(help_text), '

    ') + license_id_formats = '{}{}'.format(license_id_formats, help_text) +~~ d['help_text'] = mark_safe(license_id_formats) + field_class = django.forms.CharField + else: + d['max_length'] = max_length + d['help_text'] = help_text + field_class = django.forms.CharField + elif field_type == 'date': + d['required'] = is_required + d['initial'] = initial + d['help_text'] = help_text + if min_value: + d['validators'] = [validate_date_generator(min_value), ] + field_class = django.forms.DateField + elif field_type == 'boolean': + has_booleans = True + d['initial'] = initial + if field_name == 'agree_to_tos': +~~ d['help_text'] = mark_safe(help_text) +~~ d['label'] = mark_safe(label) + else: + d['required'] = False + d['help_text'] = help_text + field_class = django.forms.BooleanField + else: + raise Exception('Unknown field type: {}'.format(field_type)) + + fields[field_name] = field_class(**d) + fieldset[1]['fields'].append(field_name) + + widget = fields[field_name].widget + if not is_editable: + if isinstance(widget, django.forms.Select): + widget.attrs['disabled'] = 'disabled' + else: + widget.attrs['readonly'] = 'readonly' + if field_type == 'date': + widget.attrs['placeholder'] = '__/__/____' + widget.attrs['class'] = 'date' + if field_name == 'phone_number': + widget.attrs['placeholder'] = '(___) ___-____' + widget.attrs['class'] = 'phonenumber' + if field_name == 'ssn': + widget.attrs['placeholder'] = '____' + + +## ... source file continues with no further mark_safe examples... + +``` + + +## Example 21 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / snippets / edit_handlers.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/snippets/edit_handlers.py) + +```python +# edit_handlers.py +from django.template.loader import render_to_string +~~from django.utils.safestring import mark_safe + +from wagtail.admin.edit_handlers import BaseChooserPanel + +from .widgets import AdminSnippetChooser + + +class SnippetChooserPanel(BaseChooserPanel): + object_type_name = 'item' + + def widget_overrides(self): + return {self.field_name: AdminSnippetChooser(model=self.target_model)} + + def render_as_field(self): + instance_obj = self.get_chosen_item() +~~ return mark_safe(render_to_string(self.field_template, { + 'field': self.bound_field, + self.object_type_name: instance_obj, + })) + + def on_model_bound(self): + super().on_model_bound() + self.target_model = self.db_field.remote_field.model + + + +## ... source file continues with no further mark_safe examples... + +``` + diff --git a/content/pages/examples/django/django-utils-safestring-safedata.markdown b/content/pages/examples/django/django-utils-safestring-safedata.markdown new file mode 100644 index 000000000..c271f8d28 --- /dev/null +++ b/content/pages/examples/django/django-utils-safestring-safedata.markdown @@ -0,0 +1,238 @@ +title: django.utils.safestring SafeData Example Code +category: page +slug: django-utils-safestring-safedata-examples +sortorder: 500011484 +toc: False +sidebartitle: django.utils.safestring SafeData +meta: Python example code for the SafeData class from the django.utils.safestring module of the Django project. + + +SafeData is a class within the django.utils.safestring module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / forms / angular_base.py**](https://github.com/jrief/django-angular/blob/master/djng/forms/angular_base.py) + +```python +# angular_base.py +from base64 import b64encode +from collections import UserList +import json +import warnings + +from django.forms import forms +from django.http import QueryDict +from django.utils.html import format_html, format_html_join, escape, conditional_escape +from django.utils.encoding import force_text +from django.utils.module_loading import import_string +~~from django.utils.safestring import mark_safe, SafeText, SafeData +from django.core.exceptions import ValidationError, ImproperlyConfigured + +from .fields import DefaultFieldMixin + + +~~class SafeTuple(SafeData, tuple): + + +class TupleErrorList(UserList, list): + def __init__(self, initlist=None, error_class=None): + super(TupleErrorList, self).__init__(initlist) + + if error_class is None: + self.error_class = 'errorlist' + else: + self.error_class = 'errorlist {}'.format(error_class) + + def as_data(self): + return ValidationError(self.data).error_list + + def get_json_data(self, escape_html=False): + errors = [] + for error in self.as_data(): + message = list(error)[0] + errors.append({ + 'message': escape(message) if escape_html else message, + 'code': error.code or '', + }) + return errors + + + +## ... source file continues with no further SafeData examples... + +``` + + +## Example 2 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / templatetags / rest_framework.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/templatetags/rest_framework.py) + +```python +# rest_framework.py +import re +from collections import OrderedDict + +from django import template +from django.template import loader +from django.urls import NoReverseMatch, reverse +from django.utils.encoding import force_str, iri_to_uri +from django.utils.html import escape, format_html, smart_urlquote +~~from django.utils.safestring import SafeData, mark_safe + +from rest_framework.compat import apply_markdown, pygments_highlight +from rest_framework.renderers import HTMLFormRenderer +from rest_framework.utils.urls import replace_query_param + +register = template.Library() + +class_re = re.compile(r'(?<=class=["\'])(.*)(?=["\'])') + + +@register.tag(name='code') +def highlight_code(parser, token): + code = token.split_contents()[-1] + nodelist = parser.parse(('endcode',)) + parser.delete_first_token() + return CodeNode(code, nodelist) + + +class CodeNode(template.Node): + style = 'emacs' + + def __init__(self, lang, code): + self.lang = lang + self.nodelist = code + + +## ... source file continues with no further SafeData examples... + +``` + + +## Example 3 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / columns / base.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/columns/base.py) + +```python +# base.py +from collections import OrderedDict +from itertools import islice + +from django.core.exceptions import ImproperlyConfigured +from django.urls import reverse +from django.utils.html import format_html +~~from django.utils.safestring import SafeData +from django.utils.text import capfirst + +from ..utils import ( + Accessor, + AttributeDict, + OrderBy, + OrderByTuple, + call_with_appropriate, + computed_values, +) + + +class Library: + + def __init__(self): + self.columns = [] + + def register(self, column): + if not hasattr(column, "from_field"): + raise ImproperlyConfigured( + "{} is not a subclass of Column".format(column.__class__.__name__) + ) + self.columns.append(column) + return column + + +## ... source file abbreviated to get to SafeData examples ... + + + def is_ordered(self): + return self.name in (self._table.order_by or ()) + + @property + def orderable(self): + if self.column.orderable is not None: + return self.column.orderable + return self._table.orderable + + @property + def verbose_name(self): + if self.column.verbose_name is not None: + return self.column.verbose_name + + name = self.name.replace("_", " ") + + model = self._table.data.model + if model: + field = Accessor(self.accessor).get_field(model) + if field: + if hasattr(field, "field"): + name = field.field.verbose_name + else: + name = getattr(field, "verbose_name", field.name) + +~~ if isinstance(name, SafeData): + return name + + return capfirst(name) + + @property + def visible(self): + return self.column.visible + + @property + def localize(self): + return self.column.localize + + +class BoundColumns: + + def __init__(self, table, base_columns): + self._table = table + self.columns = OrderedDict() + for name, column in base_columns.items(): + self.columns[name] = bound_column = BoundColumn(table, column, name) + bound_column.render = getattr(table, "render_" + name, column.render) + bound_column.value = getattr( + table, "value_" + name, getattr(table, "render_" + name, column.value) + ) + + +## ... source file continues with no further SafeData examples... + +``` + diff --git a/content/pages/examples/django/django-utils-safestring-safetext.markdown b/content/pages/examples/django/django-utils-safestring-safetext.markdown new file mode 100644 index 000000000..705923248 --- /dev/null +++ b/content/pages/examples/django/django-utils-safestring-safetext.markdown @@ -0,0 +1,107 @@ +title: django.utils.safestring SafeText Example Code +category: page +slug: django-utils-safestring-safetext-examples +sortorder: 500011485 +toc: False +sidebartitle: django.utils.safestring SafeText +meta: Python example code for the SafeText class from the django.utils.safestring module of the Django project. + + +SafeText is a class within the django.utils.safestring module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / forms / angular_base.py**](https://github.com/jrief/django-angular/blob/master/djng/forms/angular_base.py) + +```python +# angular_base.py +from base64 import b64encode +from collections import UserList +import json +import warnings + +from django.forms import forms +from django.http import QueryDict +from django.utils.html import format_html, format_html_join, escape, conditional_escape +from django.utils.encoding import force_text +from django.utils.module_loading import import_string +~~from django.utils.safestring import mark_safe, SafeText, SafeData +from django.core.exceptions import ValidationError, ImproperlyConfigured + +from .fields import DefaultFieldMixin + + +class SafeTuple(SafeData, tuple): + + +class TupleErrorList(UserList, list): + def __init__(self, initlist=None, error_class=None): + super(TupleErrorList, self).__init__(initlist) + + if error_class is None: + self.error_class = 'errorlist' + else: + self.error_class = 'errorlist {}'.format(error_class) + + def as_data(self): + return ValidationError(self.data).error_list + + def get_json_data(self, escape_html=False): + errors = [] + for error in self.as_data(): + message = list(error)[0] + errors.append({ + 'message': escape(message) if escape_html else message, + 'code': error.code or '', + }) + return errors + + def as_json(self, escape_html=False): + return json.dumps(self.get_json_data(escape_html)) + + def extend(self, iterable): + for item in iterable: + if not isinstance(item, str): + self.append(item) + return None + + def as_ul(self): + if not self: +~~ return SafeText() + first = self[0] + if isinstance(first, tuple): + error_lists = {'$pristine': [], '$dirty': []} + for e in self: + if e[5] == '$message': + li_format = '
  • ' + else: + li_format = '
  • {3}
  • ' + err_tuple = (e[0], e[3], e[4], force_text(e[5])) + error_lists[e[2]].append(format_html(li_format, *err_tuple)) + dirty_errors, pristine_errors = '', '' + if len(error_lists['$dirty']) > 0: + dirty_errors = format_html( + '
      {2}
    ', # duck typing: !...$untouched + first[0], first[1], mark_safe(''.join(error_lists['$dirty'])) + ) + if len(error_lists['$pristine']) > 0: + pristine_errors = format_html( + '
      {2}
    ', + first[0], first[1], mark_safe(''.join(error_lists['$pristine'])) + ) + return format_html('{}{}', dirty_errors, pristine_errors) + return format_html('
      {0}
    ', + format_html_join('', '
  • {0}
  • ', ((force_text(e),) for e in self))) + + +## ... source file continues with no further SafeText examples... + +``` + diff --git a/content/pages/examples/django/django-utils-termcolors-colorize.markdown b/content/pages/examples/django/django-utils-termcolors-colorize.markdown new file mode 100644 index 000000000..212495b15 --- /dev/null +++ b/content/pages/examples/django/django-utils-termcolors-colorize.markdown @@ -0,0 +1,89 @@ +title: django.utils.termcolors colorize Example Code +category: page +slug: django-utils-termcolors-colorize-examples +sortorder: 500011487 +toc: False +sidebartitle: django.utils.termcolors colorize +meta: Python example code for the colorize callable from the django.utils.termcolors module of the Django project. + + +colorize is a callable within the django.utils.termcolors module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / utils / check.py**](https://github.com/divio/django-cms/blob/develop/cms/utils/check.py) + +```python +# check.py +from contextlib import contextmanager +import inspect +from itertools import chain + +from django.conf import settings +from django.utils.decorators import method_decorator +~~from django.utils.termcolors import colorize +from sekizai.helpers import validate_template + +from cms import constants +from cms.models import AliasPluginModel +from cms.utils.conf import get_cms_setting +from cms.utils.compat.dj import is_installed + + +SUCCESS = 1 +WARNING = 2 +ERROR = 3 +SKIPPED = 4 + +CHECKERS = [] + + +class FileOutputWrapper(object): + def __init__(self, stdout, stderr): + self.stdout = stdout + self.stderr = stderr + self.section_wrapper = FileSectionWrapper + self.errors = 0 + self.successes = 0 + self.warnings = 0 + self.skips = 0 + +~~ def colorize(self, msg, opts=(), **kwargs): +~~ return colorize(msg, opts=opts, **kwargs) + + def write_line(self, message=''): + self.write(u'%s\n' % message) + + def write(self, message): + self.stdout.write(message) + + def write_stderr_line(self, message=''): + self.write_stderr(u'%s\n' % message) + + def write_stderr(self, message): + self.stderr.write(message) + + def success(self, message): + self.successes += 1 + self.write_line(u'%s %s' % (message, self.colorize('[OK]', fg='green', opts=['bold']))) + + def error(self, message): + self.errors += 1 + self.write_stderr_line(u'%s %s' % (message, self.colorize('[ERROR]', fg='red', opts=['bold']))) + + def warn(self, message): + self.warnings += 1 + self.write_stderr_line(u'%s %s' % (message, self.colorize('[WARNING]', fg='yellow', opts=['bold']))) + + +## ... source file continues with no further colorize examples... + +``` + diff --git a/content/pages/examples/django/django-utils-termcolors.markdown b/content/pages/examples/django/django-utils-termcolors.markdown new file mode 100644 index 000000000..6754d5cdf --- /dev/null +++ b/content/pages/examples/django/django-utils-termcolors.markdown @@ -0,0 +1,65 @@ +title: django.utils termcolors Example Code +category: page +slug: django-utils-termcolors-examples +sortorder: 500011420 +toc: False +sidebartitle: django.utils termcolors +meta: Python example code for the termcolors callable from the django.utils module of the Django project. + + +termcolors is a callable within the django.utils module of the Django project. + + +## Example 1 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / management / color.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/management/color.py) + +```python +# color.py + +from django.core.management import color +~~from django.utils import termcolors + + +def _dummy_style_func(msg): + return msg + + +def no_style(): + style = color.no_style() + for role in ('INFO', 'WARN', 'BOLD', 'URL', 'MODULE', 'MODULE_NAME', 'URL_NAME'): + setattr(style, role, _dummy_style_func) + return style + + +def color_style(): + if color.supports_color(): + style = color.color_style() +~~ style.INFO = termcolors.make_style(fg='green') +~~ style.WARN = termcolors.make_style(fg='yellow') +~~ style.BOLD = termcolors.make_style(opts=('bold',)) +~~ style.URL = termcolors.make_style(fg='green', opts=('bold',)) +~~ style.MODULE = termcolors.make_style(fg='yellow') +~~ style.MODULE_NAME = termcolors.make_style(opts=('bold',)) +~~ style.URL_NAME = termcolors.make_style(fg='red') + else: + style = no_style() + return style + + + +## ... source file continues with no further termcolors examples... + +``` + diff --git a/content/pages/examples/django/django-utils-text-capfirst.markdown b/content/pages/examples/django/django-utils-text-capfirst.markdown new file mode 100644 index 000000000..f40a7e5ca --- /dev/null +++ b/content/pages/examples/django/django-utils-text-capfirst.markdown @@ -0,0 +1,990 @@ +title: django.utils.text capfirst Example Code +category: page +slug: django-utils-text-capfirst-examples +sortorder: 500011489 +toc: False +sidebartitle: django.utils.text capfirst +meta: Python example code for the capfirst callable from the django.utils.text module of the Django project. + + +capfirst is a callable within the django.utils.text module of the Django project. + + +## Example 1 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / utils.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./utils.py) + +```python +# utils.py +import warnings +from collections import OrderedDict + +from django.conf import settings +from django.core.exceptions import FieldDoesNotExist, FieldError +from django.db import models +from django.db.models.constants import LOOKUP_SEP +from django.db.models.expressions import Expression +from django.db.models.fields.related import ForeignObjectRel, RelatedField +from django.utils import timezone +from django.utils.encoding import force_str +~~from django.utils.text import capfirst +from django.utils.translation import gettext as _ + +from .exceptions import FieldLookupError + + +def deprecate(msg, level_modifier=0): + warnings.warn(msg, MigrationNotice, stacklevel=3 + level_modifier) + + +class MigrationNotice(DeprecationWarning): + url = 'https://django-filter.readthedocs.io/en/master/guide/migration.html' + + def __init__(self, message): + super().__init__('%s See: %s' % (message, self.url)) + + +class RenameAttributesBase(type): + renamed_attributes = () + + def __new__(metacls, name, bases, attrs): + old_names = [r[0] for r in metacls.renamed_attributes] + old_names = [name for name in old_names if name in attrs] + old_attrs = {name: attrs.pop(name) for name in old_names} + + + +## ... source file abbreviated to get to capfirst examples ... + + + names.append(force_str(part.verbose_name)) + + return ' '.join(names) + + +def verbose_lookup_expr(lookup_expr): + from .conf import settings as app_settings + + VERBOSE_LOOKUPS = app_settings.VERBOSE_LOOKUPS or {} + lookups = [ + force_str(VERBOSE_LOOKUPS.get(lookup, _(lookup))) + for lookup in lookup_expr.split(LOOKUP_SEP) + ] + + return ' '.join(lookups) + + +def label_for_filter(model, field_name, lookup_expr, exclude=False): + name = verbose_field_name(model, field_name) + verbose_expression = [_('exclude'), name] if exclude else [name] + + if isinstance(lookup_expr, str): + verbose_expression += [verbose_lookup_expr(lookup_expr)] + + verbose_expression = [force_str(part) for part in verbose_expression if part] +~~ verbose_expression = capfirst(' '.join(verbose_expression)) + + return verbose_expression + + +def translate_validation(error_dict): + from rest_framework.exceptions import ValidationError, ErrorDetail + + exc = OrderedDict( + (key, [ErrorDetail(e.message % (e.params or ()), code=e.code) + for e in error_list]) + for key, error_list in error_dict.as_data().items() + ) + + return ValidationError(exc) + + + +## ... source file continues with no further capfirst examples... + +``` + + +## Example 2 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / forms.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./forms.py) + +```python +# forms.py +from django import forms +from django.utils.encoding import smart_text +~~from django.utils.text import capfirst +from django.utils.translation import ugettext_lazy as _ + +from haystack import connections +from haystack.constants import DEFAULT_ALIAS +from haystack.query import EmptySearchQuerySet, SearchQuerySet +from haystack.utils import get_model_ct +from haystack.utils.app_loading import haystack_get_model + + +def model_choices(using=DEFAULT_ALIAS): + choices = [ +~~ (get_model_ct(m), capfirst(smart_text(m._meta.verbose_name_plural))) + for m in connections[using].get_unified_index().get_indexed_models() + ] + return sorted(choices, key=lambda x: x[1]) + + +class SearchForm(forms.Form): + q = forms.CharField( + required=False, + label=_("Search"), + widget=forms.TextInput(attrs={"type": "search"}), + ) + + def __init__(self, *args, **kwargs): + self.searchqueryset = kwargs.pop("searchqueryset", None) + self.load_all = kwargs.pop("load_all", False) + + if self.searchqueryset is None: + self.searchqueryset = SearchQuerySet() + + super(SearchForm, self).__init__(*args, **kwargs) + + def no_query_found(self): + return EmptySearchQuerySet() + + + +## ... source file continues with no further capfirst examples... + +``` + + +## Example 3 from django-inline-actions +[django-inline-actions](https://github.com/escaped/django-inline-actions) +([PyPI package information](https://pypi.org/project/django-inline-actions/)) +is an extension that adds actions to the [Django](/django.html) +Admin InlineModelAdmin and ModelAdmin changelists. The project is open +sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/escaped/django-inline-actions/blob/master/LICENSE). + +[**django-inline-actions / inline_actions / admin.py**](https://github.com/escaped/django-inline-actions/blob/master/inline_actions/./admin.py) + +```python +# admin.py +from django.apps import apps +from django.contrib import admin +from django.http import HttpResponse +from django.shortcuts import redirect +from django.urls import reverse +from django.utils.safestring import mark_safe +~~from django.utils.text import capfirst +from django.utils.translation import ugettext_lazy as _ + + +class InlineActionException(Exception): + pass + + +class ActionNotCallable(InlineActionException): + def __init__(self, model_admin, action, *args, **kwargs): + super().__init__(*args, **kwargs) + self.model_admin = model_admin + self.action = action + + +class BaseInlineActionsMixin: + INLINE_MODEL_ADMIN = 'inline' + MODEL_ADMIN = 'admin' + + inline_actions = [] + + def get_inline_actions(self, request, obj=None): + if self.inline_actions is None: + return [] + + + +## ... source file abbreviated to get to capfirst examples ... + + + + if isinstance(model_admin, admin.options.InlineModelAdmin): + return self.INLINE_MODEL_ADMIN + return self.MODEL_ADMIN + + def render_inline_actions(self, obj=None): # NOQA: C901 + if not (obj and obj.pk): + return '' + + buttons = [] + for action_name in self.get_inline_actions(self._request, obj): + action_func = getattr(self, action_name, None) + if not action_func: + raise RuntimeError( + "Could not find action `{}`".format(action_name)) + + action_name = action_func.__name__ + label_handler = getattr( + self, 'get_{}_label'.format(action_name), None) + if callable(label_handler): + description = label_handler(obj=obj) + else: + try: + description = action_func.short_description + except AttributeError: +~~ description = capfirst(action_name.replace('_', ' ')) + + css_handler = getattr( + self, 'get_{}_css'.format(action_name), None) + if callable(css_handler): + css_classes = css_handler(obj=obj) + else: + try: + css_classes = action_func.css_classes + except AttributeError: + css_classes = '' + + action_data = [ + self.__class__.__name__.lower(), + self._get_admin_type(), + action_name, + obj._meta.app_label, + obj._meta.model_name, + str(obj.pk), + ] + buttons.append( + ''.format( + '_action__{}'.format('__'.join(action_data)), + description, + css_classes, + + +## ... source file continues with no further capfirst examples... + +``` + + +## Example 4 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / utils.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./utils.py) + +```python +# utils.py +import datetime +import json +from django.template import Context +from django.utils import translation +from jet import settings +from jet.models import PinnedApplication + +try: + from django.apps.registry import apps +except ImportError: + try: + from django.apps import apps # Fix Django 1.7 import issue + except ImportError: + pass +from django.core.serializers.json import DjangoJSONEncoder +from django.http import HttpResponse +try: + from django.core.urlresolvers import reverse, resolve, NoReverseMatch +except ImportError: # Django 1.11 + from django.urls import reverse, resolve, NoReverseMatch + +from django.contrib.admin import AdminSite +from django.utils.encoding import smart_text +~~from django.utils.text import capfirst +from django.contrib import messages +from django.utils.encoding import force_text +from django.utils.functional import Promise +from django.contrib.admin.options import IncorrectLookupParameters +from django.contrib import admin +from django.utils.translation import ugettext_lazy as _ +from django.utils.text import slugify + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # Python 2.6 + + +class JsonResponse(HttpResponse): + + def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs): + if safe and not isinstance(data, dict): + raise TypeError('In order to allow non-dict objects to be ' + 'serialized set the safe parameter to False') + kwargs.setdefault('content_type', 'application/json') + data = json.dumps(data, cls=encoder) + super(JsonResponse, self).__init__(content=data, **kwargs) + + +def get_app_list(context, order=True): + admin_site = get_admin_site(context) + request = context['request'] + + app_dict = {} + for model, model_admin in admin_site._registry.items(): + app_label = model._meta.app_label + try: + has_module_perms = model_admin.has_module_permission(request) + except AttributeError: + has_module_perms = request.user.has_module_perms(app_label) # Fix Django < 1.8 issue + + if has_module_perms: + perms = model_admin.get_model_perms(request) + + if True in perms.values(): + info = (app_label, model._meta.model_name) + model_dict = { +~~ 'name': capfirst(model._meta.verbose_name_plural), + 'object_name': model._meta.object_name, + 'perms': perms, + 'model_name': model._meta.model_name + } + if perms.get('change', False): + try: + model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=admin_site.name) + except NoReverseMatch: + pass + if perms.get('add', False): + try: + model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=admin_site.name) + except NoReverseMatch: + pass + if app_label in app_dict: + app_dict[app_label]['models'].append(model_dict) + else: + try: + name = apps.get_app_config(app_label).verbose_name + except NameError: + name = app_label.title() + app_dict[app_label] = { + 'name': name, + 'app_label': app_label, + + +## ... source file abbreviated to get to capfirst examples ... + + + + split = language_code.split('-', 2) + if len(split) == 2: + language_code = '%s-%s' % (split[0].lower(), split[1].upper()) if split[0] != split[1] else split[0] + + language_codes.append(language_code) + + if len(split) == 2: + language_codes.append(split[0].lower()) + + return language_codes + + +def get_original_menu_items(context): + if context.get('user') and user_is_authenticated(context['user']): + pinned_apps = PinnedApplication.objects.filter(user=context['user'].pk).values_list('app_label', flat=True) + else: + pinned_apps = [] + + original_app_list = get_app_list(context) + + return map(lambda app: { + 'app_label': app['app_label'], + 'url': app['app_url'], + 'url_blank': False, +~~ 'label': app.get('name', capfirst(_(app['app_label']))), + 'has_perms': app.get('has_module_perms', False), + 'models': list(map(lambda model: { + 'url': model.get('admin_url'), + 'url_blank': False, + 'name': model['model_name'], + 'object_name': model['object_name'], + 'label': model.get('name', model['object_name']), + 'has_perms': any(model.get('perms', {}).values()), + }, app['models'])), + 'pinned': app['app_label'] in pinned_apps, + 'custom': False + }, original_app_list) + + +def get_menu_item_url(url, original_app_list): + if isinstance(url, dict): + url_type = url.get('type') + + if url_type == 'app': + return original_app_list[url['app_label']]['url'] + elif url_type == 'model': + models = dict(map( + lambda x: (x['name'], x['url']), + original_app_list[url['app_label']]['models'] + + +## ... source file continues with no further capfirst examples... + +``` + + +## Example 5 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / utils / field_mapping.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/utils/field_mapping.py) + +```python +# field_mapping.py +import inspect + +from django.core import validators +from django.db import models +~~from django.utils.text import capfirst + +from rest_framework.compat import postgres_fields +from rest_framework.validators import UniqueValidator + +NUMERIC_FIELD_TYPES = ( + models.IntegerField, models.FloatField, models.DecimalField, models.DurationField, +) + + +class ClassLookupDict: + def __init__(self, mapping): + self.mapping = mapping + + def __getitem__(self, key): + if hasattr(key, '_proxy_class'): + base_class = key._proxy_class + else: + base_class = key.__class__ + + for cls in inspect.getmro(base_class): + if cls in self.mapping: + return self.mapping[cls] + raise KeyError('Class %s not found in lookup.' % base_class.__name__) + + def __setitem__(self, key, value): + self.mapping[key] = value + + +def needs_label(model_field, field_name): + default_label = field_name.replace('_', ' ').capitalize() +~~ return capfirst(model_field.verbose_name) != default_label + + +def get_detail_view_name(model): + return '%(model_name)s-detail' % { + 'app_label': model._meta.app_label, + 'model_name': model._meta.object_name.lower() + } + + +def get_field_kwargs(field_name, model_field): + kwargs = {} + validator_kwarg = list(model_field.validators) + + kwargs['model_field'] = model_field + + if model_field.verbose_name and needs_label(model_field, field_name): +~~ kwargs['label'] = capfirst(model_field.verbose_name) + + if model_field.help_text: + kwargs['help_text'] = model_field.help_text + + max_digits = getattr(model_field, 'max_digits', None) + if max_digits is not None: + kwargs['max_digits'] = max_digits + + decimal_places = getattr(model_field, 'decimal_places', None) + if decimal_places is not None: + kwargs['decimal_places'] = decimal_places + + if isinstance(model_field, models.SlugField): + kwargs['allow_unicode'] = model_field.allow_unicode + + if isinstance(model_field, models.TextField) and not model_field.choices or \ + (postgres_fields and isinstance(model_field, postgres_fields.JSONField)): + kwargs['style'] = {'base_template': 'textarea.html'} + + if isinstance(model_field, models.AutoField) or not model_field.editable: + kwargs['read_only'] = True + return kwargs + + if model_field.has_default() or model_field.blank or model_field.null: + + +## ... source file abbreviated to get to capfirst examples ... + + +def get_relation_kwargs(field_name, relation_info): + model_field, related_model, to_many, to_field, has_through_model, reverse = relation_info + kwargs = { + 'queryset': related_model._default_manager, + 'view_name': get_detail_view_name(related_model) + } + + if to_many: + kwargs['many'] = True + + if to_field: + kwargs['to_field'] = to_field + + limit_choices_to = model_field and model_field.get_limit_choices_to() + if limit_choices_to: + if not isinstance(limit_choices_to, models.Q): + limit_choices_to = models.Q(**limit_choices_to) + kwargs['queryset'] = kwargs['queryset'].filter(limit_choices_to) + + if has_through_model: + kwargs['read_only'] = True + kwargs.pop('queryset', None) + + if model_field: + if model_field.verbose_name and needs_label(model_field, field_name): +~~ kwargs['label'] = capfirst(model_field.verbose_name) + help_text = model_field.help_text + if help_text: + kwargs['help_text'] = help_text + if not model_field.editable: + kwargs['read_only'] = True + kwargs.pop('queryset', None) + if kwargs.get('read_only', False): + return kwargs + + if model_field.has_default() or model_field.blank or model_field.null: + kwargs['required'] = False + if model_field.null: + kwargs['allow_null'] = True + if model_field.validators: + kwargs['validators'] = model_field.validators + if getattr(model_field, 'unique', False): + validator = UniqueValidator(queryset=model_field.model._default_manager) + kwargs['validators'] = kwargs.get('validators', []) + [validator] + if to_many and not model_field.blank: + kwargs['allow_empty'] = False + + return kwargs + + + + +## ... source file continues with no further capfirst examples... + +``` + + +## Example 6 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / columns / base.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/columns/base.py) + +```python +# base.py +from collections import OrderedDict +from itertools import islice + +from django.core.exceptions import ImproperlyConfigured +from django.urls import reverse +from django.utils.html import format_html +from django.utils.safestring import SafeData +~~from django.utils.text import capfirst + +from ..utils import ( + Accessor, + AttributeDict, + OrderBy, + OrderByTuple, + call_with_appropriate, + computed_values, +) + + +class Library: + + def __init__(self): + self.columns = [] + + def register(self, column): + if not hasattr(column, "from_field"): + raise ImproperlyConfigured( + "{} is not a subclass of Column".format(column.__class__.__name__) + ) + self.columns.append(column) + return column + + def column_for_field(self, field, **kwargs): + if field is None: + return self.columns[0](**kwargs) + + for candidate in reversed(self.columns): + if hasattr(field, "get_related_field"): + verbose_name = field.get_related_field().verbose_name + else: + verbose_name = getattr(field, "verbose_name", field.name) +~~ kwargs["verbose_name"] = capfirst(verbose_name) + column = candidate.from_field(field, **kwargs) + if column is None: + continue + return column + + +library = Library() + + +class LinkTransform: + + viewname = None + accessor = None + attrs = None + + def __init__(self, url=None, accessor=None, attrs=None, reverse_args=None): + self.url = url + self.attrs = attrs + self.accessor = accessor + + if isinstance(reverse_args, (list, tuple)): + viewname, args = reverse_args + reverse_args = {"viewname": viewname} + reverse_args["kwargs" if isinstance(args, dict) else "args"] = args + + +## ... source file abbreviated to get to capfirst examples ... + + + @property + def orderable(self): + if self.column.orderable is not None: + return self.column.orderable + return self._table.orderable + + @property + def verbose_name(self): + if self.column.verbose_name is not None: + return self.column.verbose_name + + name = self.name.replace("_", " ") + + model = self._table.data.model + if model: + field = Accessor(self.accessor).get_field(model) + if field: + if hasattr(field, "field"): + name = field.field.verbose_name + else: + name = getattr(field, "verbose_name", field.name) + + if isinstance(name, SafeData): + return name + +~~ return capfirst(name) + + @property + def visible(self): + return self.column.visible + + @property + def localize(self): + return self.column.localize + + +class BoundColumns: + + def __init__(self, table, base_columns): + self._table = table + self.columns = OrderedDict() + for name, column in base_columns.items(): + self.columns[name] = bound_column = BoundColumn(table, column, name) + bound_column.render = getattr(table, "render_" + name, column.render) + bound_column.value = getattr( + table, "value_" + name, getattr(table, "render_" + name, column.value) + ) + bound_column.order = getattr(table, "order_" + name, column.order) + + def iternames(self): + + +## ... source file continues with no further capfirst examples... + +``` + + +## Example 7 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / managers.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./managers.py) + +```python +# managers.py +import uuid +from operator import attrgetter + +from django import VERSION +from django.conf import settings +from django.contrib.contenttypes.fields import GenericRelation +from django.contrib.contenttypes.models import ContentType +from django.db import connections, models, router +from django.db.models import signals +from django.db.models.fields.related import ( + ManyToManyRel, + OneToOneRel, + RelatedField, + lazy_related_operation, +) +from django.db.models.query_utils import PathInfo +~~from django.utils.text import capfirst +from django.utils.translation import gettext_lazy as _ + +from taggit.forms import TagField +from taggit.models import ( + CommonGenericTaggedItemBase, + GenericUUIDTaggedItemBase, + TaggedItem, +) +from taggit.utils import require_instance_manager + + +class ExtraJoinRestriction: + + contains_aggregate = False + + def __init__(self, alias, col, content_types): + self.alias = alias + self.col = col + self.content_types = content_types + + def as_sql(self, compiler, connection): + qn = compiler.quote_name_unless_alias + if len(self.content_types) == 1: + extra_where = "{}.{} = %s".format(qn(self.alias), qn(self.col)) + + +## ... source file abbreviated to get to capfirst examples ... + + + ) + + if not self.remote_field.model: + self.remote_field.model = self.through._meta.get_field( + "tag" + ).remote_field.model + + if self.use_gfk: + tagged_items = GenericRelation(self.through) + tagged_items.contribute_to_class(cls, "tagged_items") + + for rel in cls._meta.local_many_to_many: + if rel == self or not isinstance(rel, TaggableManager): + continue + if rel.through == self.through: + raise ValueError( + "You can't have two TaggableManagers with the" + " same through model." + ) + + def save_form_data(self, instance, value): + getattr(instance, self.name).set(*value) + + def formfield(self, form_class=TagField, **kwargs): + defaults = { +~~ "label": capfirst(self.verbose_name), + "help_text": self.help_text, + "required": not self.blank, + } + defaults.update(kwargs) + return form_class(**defaults) + + def value_from_object(self, obj): + if obj.pk is None: + return [] + qs = self.through.objects.select_related("tag").filter( + **self.through.lookup_kwargs(obj) + ) + return [ti.tag for ti in qs] + + def m2m_reverse_name(self): + return self.through._meta.get_field("tag").column + + def m2m_reverse_field_name(self): + return self.through._meta.get_field("tag").name + + def m2m_target_field_name(self): + return self.model._meta.pk.name + + def m2m_reverse_target_field_name(self): + + +## ... source file continues with no further capfirst examples... + +``` + + +## Example 8 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / models.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/models.py) + +```python +# models.py +import json +import logging +from collections import defaultdict +from io import StringIO +from urllib.parse import urlparse + +from django.conf import settings +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core import checks +from django.core.cache import cache +from django.core.exceptions import ValidationError +from django.core.handlers.base import BaseHandler +from django.core.handlers.wsgi import WSGIRequest +from django.db import models, transaction +from django.db.models import Case, Q, Value, When +from django.db.models.functions import Concat, Lower, Substr +from django.http import Http404 +from django.http.request import split_domain_port +from django.template.response import TemplateResponse +from django.urls import NoReverseMatch, reverse +from django.utils import timezone +from django.utils.cache import patch_cache_control +from django.utils.functional import cached_property +~~from django.utils.text import capfirst, slugify +from django.utils.translation import gettext_lazy as _ +from modelcluster.models import ( + ClusterableModel, get_all_child_m2m_relations, get_all_child_relations) +from treebeard.mp_tree import MP_Node + +from wagtail.core.query import PageQuerySet, TreeQuerySet +from wagtail.core.signals import page_published, page_unpublished, post_page_move, pre_page_move +from wagtail.core.sites import get_site_for_hostname +from wagtail.core.url_routing import RouteResult +from wagtail.core.utils import WAGTAIL_APPEND_SLASH, camelcase_to_underscore, resolve_model_string +from wagtail.search import index + + +logger = logging.getLogger('wagtail.core') + +PAGE_TEMPLATE_VAR = 'page' + + +class SiteManager(models.Manager): + def get_queryset(self): + return super(SiteManager, self).get_queryset().order_by(Lower("hostname")) + + def get_by_natural_key(self, hostname, port): + return self.get(hostname=hostname, port=port) + + +## ... source file abbreviated to get to capfirst examples ... + + + page_model for page_model in cls.allowed_subpage_models() + if page_model.is_creatable + ] + + @classmethod + def can_exist_under(cls, parent): + return cls in parent.specific_class.allowed_subpage_models() + + @classmethod + def can_create_at(cls, parent): + can_create = cls.is_creatable and cls.can_exist_under(parent) + + if cls.max_count is not None: + can_create = can_create and cls.objects.count() < cls.max_count + + if cls.max_count_per_parent is not None: + can_create = can_create and parent.get_children().type(cls).count() < cls.max_count_per_parent + + return can_create + + def can_move_to(self, parent): + return self.can_exist_under(parent) + + @classmethod + def get_verbose_name(cls): +~~ return capfirst(cls._meta.verbose_name) + + @property + def status_string(self): + if not self.live: + if self.expired: + return _("expired") + elif self.approved_schedule: + return _("scheduled") + else: + return _("draft") + else: + if self.approved_schedule: + return _("live + scheduled") + elif self.has_unpublished_changes: + return _("live + draft") + else: + return _("live") + + @property + def approved_schedule(self): + return self.revisions.exclude(approved_go_live_at__isnull=True).exists() + + def has_unpublished_subtree(self): + return (not self.live) and (not self.get_descendants().filter(live=True).exists()) + + +## ... source file continues with no further capfirst examples... + +``` + diff --git a/content/pages/examples/django/django-utils-text-format-lazy.markdown b/content/pages/examples/django/django-utils-text-format-lazy.markdown new file mode 100644 index 000000000..4480fe6c2 --- /dev/null +++ b/content/pages/examples/django/django-utils-text-format-lazy.markdown @@ -0,0 +1,64 @@ +title: django.utils.text format_lazy Example Code +category: page +slug: django-utils-text-format-lazy-examples +sortorder: 500011490 +toc: False +sidebartitle: django.utils.text format_lazy +meta: Python example code for the format_lazy callable from the django.utils.text module of the Django project. + + +format_lazy is a callable within the django.utils.text module of the Django project. + + +## Example 1 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / utils / compatibility.py**](https://github.com/divio/django-filer/blob/develop/filer/utils/compatibility.py) + +```python +# compatibility.py +from __future__ import absolute_import, unicode_literals + +import sys + +from django.utils import six +from django.utils.functional import keep_lazy +~~from django.utils.text import Truncator, format_lazy + + +def string_concat(*strings): +~~ return format_lazy('{}' * len(strings), *strings) + + +def truncate_words(s, num, end_text='...'): + truncate = end_text and ' %s' % end_text or '' + return Truncator(s).words(num, truncate=truncate) + + +truncate_words = keep_lazy(truncate_words, six.text_type) + + +if not six.PY3: + fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() + + +def upath(path): + if six.PY2 and not isinstance(path, six.text_type): + return path.decode(fs_encoding) + return path + + +def get_delete_permission(opts): + from django.contrib.auth import get_permission_codename # noqa + return '%s.%s' % (opts.app_label, get_permission_codename('delete', opts)) + + + +## ... source file continues with no further format_lazy examples... + +``` + diff --git a/content/pages/examples/django/django-utils-text-get-text-list.markdown b/content/pages/examples/django/django-utils-text-get-text-list.markdown new file mode 100644 index 000000000..ff9b4f286 --- /dev/null +++ b/content/pages/examples/django/django-utils-text-get-text-list.markdown @@ -0,0 +1,128 @@ +title: django.utils.text get_text_list Example Code +category: page +slug: django-utils-text-get-text-list-examples +sortorder: 500011491 +toc: False +sidebartitle: django.utils.text get_text_list +meta: Python example code for the get_text_list callable from the django.utils.text module of the Django project. + + +get_text_list is a callable within the django.utils.text module of the Django project. + + +## Example 1 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / admin / __init__.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/admin/__init__.py) + +```python +# __init__.py +import six +import operator +from functools import update_wrapper +from six.moves import reduce +from typing import Tuple, Dict, Callable # NOQA + +from django.apps import apps +from django.http import HttpResponse, HttpResponseNotFound +from django.conf import settings +from django.db import models +from django.db.models.query import QuerySet +from django.utils.encoding import smart_str +from django.utils.translation import gettext as _ +~~from django.utils.text import get_text_list +from django.contrib import admin + +from django_extensions.admin.widgets import ForeignKeySearchInput + + +class ForeignKeyAutocompleteAdminMixin: + + related_search_fields = {} # type: Dict[str, Tuple[str]] + related_string_functions = {} # type: Dict[str, Callable] + autocomplete_limit = getattr(settings, 'FOREIGNKEY_AUTOCOMPLETE_LIMIT', None) + + def get_urls(self): + from django.urls import path + + def wrap(view): + def wrapper(*args, **kwargs): + return self.admin_site.admin_view(view)(*args, **kwargs) + return update_wrapper(wrapper, view) + + return [ + path('foreignkey_autocomplete/', wrap(self.foreignkey_autocomplete), + name='%s_%s_autocomplete' % (self.model._meta.app_label, self.model._meta.model_name)) + ] + super().get_urls() + + + +## ... source file abbreviated to get to get_text_list examples ... + + + if additional_filter: + queryset = queryset.filter(additional_filter) + + if self.autocomplete_limit: + queryset = queryset[:self.autocomplete_limit] + + data = ''.join([six.u('%s|%s\n') % (to_string_function(f), f.pk) for f in queryset]) + elif object_pk: + try: + obj = queryset.get(pk=object_pk) + except Exception: # FIXME: use stricter exception checking + pass + else: + data = to_string_function(obj) + return HttpResponse(data, content_type='text/plain') + return HttpResponseNotFound() + + def get_related_filter(self, model, request): + return None + + def get_help_text(self, field_name, model_name): + searchable_fields = self.related_search_fields.get(field_name, None) + if searchable_fields: + help_kwargs = { + 'model_name': model_name, +~~ 'field_list': get_text_list(searchable_fields, _('and')), + } + return _('Use the left field to do %(model_name)s lookups in the fields %(field_list)s.') % help_kwargs + return '' + + def formfield_for_dbfield(self, db_field, **kwargs): + if isinstance(db_field, models.ForeignKey) and db_field.name in self.related_search_fields: + help_text = self.get_help_text(db_field.name, db_field.remote_field.model._meta.object_name) + if kwargs.get('help_text'): + help_text = six.u('%s %s' % (kwargs['help_text'], help_text)) + kwargs['widget'] = ForeignKeySearchInput(db_field.remote_field, self.related_search_fields[db_field.name]) + kwargs['help_text'] = help_text + return super().formfield_for_dbfield(db_field, **kwargs) + + +class ForeignKeyAutocompleteAdmin(ForeignKeyAutocompleteAdminMixin, admin.ModelAdmin): + pass + + +class ForeignKeyAutocompleteTabularInline(ForeignKeyAutocompleteAdminMixin, admin.TabularInline): + pass + + +class ForeignKeyAutocompleteStackedInline(ForeignKeyAutocompleteAdminMixin, admin.StackedInline): + pass + + +## ... source file continues with no further get_text_list examples... + +``` + diff --git a/content/pages/examples/django/django-utils-text-get-valid-filename.markdown b/content/pages/examples/django/django-utils-text-get-valid-filename.markdown new file mode 100644 index 000000000..ccc590d50 --- /dev/null +++ b/content/pages/examples/django/django-utils-text-get-valid-filename.markdown @@ -0,0 +1,103 @@ +title: django.utils.text get_valid_filename Example Code +category: page +slug: django-utils-text-get-valid-filename-examples +sortorder: 500011492 +toc: False +sidebartitle: django.utils.text get_valid_filename +meta: Python example code for the get_valid_filename callable from the django.utils.text module of the Django project. + + +get_valid_filename is a callable within the django.utils.text module of the Django project. + + +## Example 1 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / utils / files.py**](https://github.com/divio/django-filer/blob/develop/filer/utils/files.py) + +```python +# files.py +from __future__ import absolute_import, unicode_literals + +import os + +from django.http.multipartparser import ( + ChunkIter, SkipFile, StopFutureHandlers, StopUpload, exhaust, +) +from django.template.defaultfilters import slugify as slugify_django +from django.utils.encoding import force_text +~~from django.utils.text import get_valid_filename as get_valid_filename_django + +from unidecode import unidecode + + +class UploadException(Exception): + pass + + +def handle_upload(request): + if not request.method == "POST": + raise UploadException("AJAX request not valid: must be POST") + if request.is_ajax(): + is_raw = True + filename = request.GET.get('qqfile', False) or request.GET.get('filename', False) or '' + + try: + content_length = int(request.META['CONTENT_LENGTH']) + except (IndexError, TypeError, ValueError): + content_length = None + + if content_length < 0: + raise UploadException("Invalid content length: %r" % content_length) + + upload_handlers = request.upload_handlers + + +## ... source file abbreviated to get to get_valid_filename examples ... + + + + for i, handler in enumerate(upload_handlers): + file_obj = handler.file_complete(counters[i]) + if file_obj: + upload = file_obj + break + else: + if len(request.FILES) == 1: + upload, filename, is_raw = handle_request_files_upload(request) + else: + raise UploadException("AJAX request not valid: Bad Upload") + return upload, filename, is_raw + + +def handle_request_files_upload(request): + is_raw = False + upload = list(request.FILES.values())[0] + filename = upload.name + return upload, filename, is_raw + + +def slugify(string): + return slugify_django(unidecode(force_text(string))) + + +~~def get_valid_filename(s): + s = get_valid_filename_django(s) + filename, ext = os.path.splitext(s) + filename = slugify(filename) + ext = slugify(ext) + if ext: + return "%s.%s" % (filename, ext) + else: + return "%s" % (filename,) + + + +## ... source file continues with no further get_valid_filename examples... + +``` + diff --git a/content/pages/examples/django/django-utils-text-slugify.markdown b/content/pages/examples/django/django-utils-text-slugify.markdown new file mode 100644 index 000000000..739c0520a --- /dev/null +++ b/content/pages/examples/django/django-utils-text-slugify.markdown @@ -0,0 +1,562 @@ +title: django.utils.text slugify Example Code +category: page +slug: django-utils-text-slugify-examples +sortorder: 500011493 +toc: False +sidebartitle: django.utils.text slugify +meta: Python example code for the slugify callable from the django.utils.text module of the Django project. + + +slugify is a callable within the django.utils.text module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / forms / wizards.py**](https://github.com/divio/django-cms/blob/develop/cms/forms/wizards.py) + +```python +# wizards.py + +from __future__ import unicode_literals + +from django import forms +from django.core.exceptions import ValidationError +from django.db import transaction +~~from django.utils.text import slugify +from django.utils.translation import ( + ugettext, + ugettext_lazy as _, +) + +from cms.admin.forms import AddPageForm +from cms.plugin_pool import plugin_pool +from cms.utils import get_current_site, permissions +from cms.utils.page import get_available_slug +from cms.utils.page_permissions import ( + user_can_add_page, + user_can_add_subpage, +) +from cms.utils.conf import get_cms_setting +from cms.utils.urlutils import static_with_version + +try: + from djangocms_text_ckeditor.widgets import TextEditorWidget + text_widget = TextEditorWidget +except ImportError: + text_widget = forms.Textarea + + +class SlugWidget(forms.widgets.TextInput): + + +## ... source file abbreviated to get to slugify examples ... + + + super(CreateCMSPageForm, self).__init__(*args, **kwargs) + self.fields['title'].help_text = _(u"Provide a title for the new page.") + self.fields['slug'].required = False + self.fields['slug'].widget = SlugWidget() + self.fields['slug'].help_text = _(u"Leave empty for automatic slug, or override as required.") + + @staticmethod + def get_placeholder(page, slot=None): + placeholders = page.get_placeholders() + + if slot: + placeholders = placeholders.filter(slot=slot) + + for ph in placeholders: + if not ph.is_static and ph.is_editable: + return ph + + return None + + def clean(self): + data = self.cleaned_data + + if self._errors: + return data + +~~ slug = data.get('slug') or slugify(data['title']) + + parent_node = data.get('parent_node') + + if parent_node: + base = parent_node.item.get_path(self._language) + path = u'%s/%s' % (base, slug) if base else slug + else: + base = '' + path = slug + + data['slug'] = get_available_slug(self._site, path, self._language, suffix=None) + data['path'] = '%s/%s' % (base, data['slug']) if base else data['slug'] + + if not data['slug']: + raise forms.ValidationError("Please provide a valid slug.") + return data + + def clean_parent_node(self): + if self.page and self.sub_page_form: + parent_page = self.page + elif self.page and self.page.parent_page: + parent_page = self.page.parent_page + else: + parent_page = None + + +## ... source file continues with no further slugify examples... + +``` + + +## Example 2 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / utils.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./utils.py) + +```python +# utils.py +from jet.models import PinnedApplication + +try: + from django.apps.registry import apps +except ImportError: + try: + from django.apps import apps # Fix Django 1.7 import issue + except ImportError: + pass +from django.core.serializers.json import DjangoJSONEncoder +from django.http import HttpResponse +try: + from django.core.urlresolvers import reverse, resolve, NoReverseMatch +except ImportError: # Django 1.11 + from django.urls import reverse, resolve, NoReverseMatch + +from django.contrib.admin import AdminSite +from django.utils.encoding import smart_text +from django.utils.text import capfirst +from django.contrib import messages +from django.utils.encoding import force_text +from django.utils.functional import Promise +from django.contrib.admin.options import IncorrectLookupParameters +from django.contrib import admin +from django.utils.translation import ugettext_lazy as _ +~~from django.utils.text import slugify + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # Python 2.6 + + +class JsonResponse(HttpResponse): + + def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs): + if safe and not isinstance(data, dict): + raise TypeError('In order to allow non-dict objects to be ' + 'serialized set the safe parameter to False') + kwargs.setdefault('content_type', 'application/json') + data = json.dumps(data, cls=encoder) + super(JsonResponse, self).__init__(content=data, **kwargs) + + +def get_app_list(context, order=True): + admin_site = get_admin_site(context) + request = context['request'] + + app_dict = {} + for model, model_admin in admin_site._registry.items(): + + +## ... source file abbreviated to get to slugify examples ... + + + )) + + if name in models: + item = models[name].copy() + + if 'label' in data: + item['label'] = data['label'] + + if 'url' in data: + item['url'] = get_menu_item_url(data['url'], original_app_list) + + if 'url_blank' in data: + item['url_blank'] = data['url_blank'] + + if 'permissions' in data: + item['has_perms'] = item.get('has_perms', True) and context['user'].has_perms(data['permissions']) + + return item + + def get_menu_item_app(data): + app_label = data.get('app_label') + + if not app_label: + if 'label' not in data: + raise Exception('Custom menu items should at least have \'label\' or \'app_label\' key') +~~ app_label = 'custom_%s' % slugify(data['label'], allow_unicode=True) + + if app_label in original_app_list: + item = original_app_list[app_label].copy() + else: + item = {'app_label': app_label, 'has_perms': True} + + if 'label' in data: + item['label'] = data['label'] + + if 'items' in data: + item['items'] = list(map(lambda x: get_menu_item_app_model(app_label, x), data['items'])) + + if 'url' in data: + item['url'] = get_menu_item_url(data['url'], original_app_list) + + if 'url_blank' in data: + item['url_blank'] = data['url_blank'] + + if 'permissions' in data: + item['has_perms'] = item.get('has_perms', True) and context['user'].has_perms(data['permissions']) + + item['pinned'] = item['app_label'] in pinned_apps + + return item + + +## ... source file continues with no further slugify examples... + +``` + + +## Example 3 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / exporters.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./exporters.py) + +```python +# exporters.py +from django.db import DatabaseError +from django.core.serializers.json import DjangoJSONEncoder +import json +import uuid +import string +import sys +from datetime import datetime +PY3 = sys.version_info[0] == 3 +if PY3: + import csv +else: + import unicodecsv as csv + +from django.utils.module_loading import import_string +~~from django.utils.text import slugify +from explorer import app_settings +from six import StringIO, BytesIO + + +def get_exporter_class(format): + class_str = dict(getattr(app_settings, 'EXPLORER_DATA_EXPORTERS'))[format] + return import_string(class_str) + + +class BaseExporter(object): + + name = '' + content_type = '' + file_extension = '' + + def __init__(self, query): + self.query = query + + def get_output(self, **kwargs): + value = self.get_file_output(**kwargs).getvalue() + if PY3: + return value + else: + return str(value) + + +## ... source file abbreviated to get to slugify examples ... + + + + row = 0 + col = 0 + header_style = wb.add_format({'bold': True}) + for header in res.header_strings: + ws.write(row, col, header, header_style) + col += 1 + + row = 1 + col = 0 + for data_row in res.data: + for data in data_row: + if isinstance(data, datetime) or isinstance(data, uuid.UUID): + data = str(data) + if isinstance(data, dict) or isinstance(data, list): + data = json.dumps(data) + ws.write(row, col, data) + col += 1 + row += 1 + col = 0 + + wb.close() + return output + + def _format_title(self): +~~ title = slugify(self.query.title) + return title[:31] + + + +## ... source file continues with no further slugify examples... + +``` + + +## Example 4 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / models.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./models.py) + +```python +# models.py +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +from django.db import IntegrityError, models, router, transaction +~~from django.utils.text import slugify +from django.utils.translation import gettext, gettext_lazy as _ + +try: + from unidecode import unidecode +except ImportError: + + def unidecode(tag): + return tag + + +class TagBase(models.Model): + name = models.CharField(verbose_name=_("name"), unique=True, max_length=100) + slug = models.SlugField(verbose_name=_("slug"), unique=True, max_length=100) + + def __str__(self): + return self.name + + def __gt__(self, other): + return self.name.lower() > other.name.lower() + + def __lt__(self, other): + return self.name.lower() < other.name.lower() + + class Meta: + + +## ... source file abbreviated to get to slugify examples ... + + + using = kwargs.get("using") or router.db_for_write( + type(self), instance=self + ) + kwargs["using"] = using + try: + with transaction.atomic(using=using): + res = super().save(*args, **kwargs) + return res + except IntegrityError: + pass + slugs = set( + type(self) + ._default_manager.filter(slug__startswith=self.slug) + .values_list("slug", flat=True) + ) + i = 1 + while True: + slug = self.slugify(self.name, i) + if slug not in slugs: + self.slug = slug + return super().save(*args, **kwargs) + i += 1 + else: + return super().save(*args, **kwargs) + +~~ def slugify(self, tag, i=None): +~~ slug = slugify(unidecode(tag)) + if i is not None: + slug += "_%d" % i + return slug + + +class Tag(TagBase): + class Meta: + verbose_name = _("tag") + verbose_name_plural = _("tags") + app_label = "taggit" + + +class ItemBase(models.Model): + def __str__(self): + return gettext("%(object)s tagged with %(tag)s") % { + "object": self.content_object, + "tag": self.tag, + } + + class Meta: + abstract = True + + @classmethod + def tag_model(cls): + + +## ... source file continues with no further slugify examples... + +``` + + +## Example 5 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / models.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/models.py) + +```python +# models.py +import json +import logging +from collections import defaultdict +from io import StringIO +from urllib.parse import urlparse + +from django.conf import settings +from django.contrib.auth.models import Group, Permission +from django.contrib.contenttypes.models import ContentType +from django.core import checks +from django.core.cache import cache +from django.core.exceptions import ValidationError +from django.core.handlers.base import BaseHandler +from django.core.handlers.wsgi import WSGIRequest +from django.db import models, transaction +from django.db.models import Case, Q, Value, When +from django.db.models.functions import Concat, Lower, Substr +from django.http import Http404 +from django.http.request import split_domain_port +from django.template.response import TemplateResponse +from django.urls import NoReverseMatch, reverse +from django.utils import timezone +from django.utils.cache import patch_cache_control +from django.utils.functional import cached_property +~~from django.utils.text import capfirst, slugify +from django.utils.translation import gettext_lazy as _ +from modelcluster.models import ( + ClusterableModel, get_all_child_m2m_relations, get_all_child_relations) +from treebeard.mp_tree import MP_Node + +from wagtail.core.query import PageQuerySet, TreeQuerySet +from wagtail.core.signals import page_published, page_unpublished, post_page_move, pre_page_move +from wagtail.core.sites import get_site_for_hostname +from wagtail.core.url_routing import RouteResult +from wagtail.core.utils import WAGTAIL_APPEND_SLASH, camelcase_to_underscore, resolve_model_string +from wagtail.search import index + + +logger = logging.getLogger('wagtail.core') + +PAGE_TEMPLATE_VAR = 'page' + + +class SiteManager(models.Manager): + def get_queryset(self): + return super(SiteManager, self).get_queryset().order_by(Lower("hostname")) + + def get_by_natural_key(self, hostname, port): + return self.get(hostname=hostname, port=port) + + +## ... source file abbreviated to get to slugify examples ... + + + def _slug_is_available(slug, parent_page, page=None): + if parent_page is None: + return True + + siblings = parent_page.get_children() + if page: + siblings = siblings.not_page(page) + + return not siblings.filter(slug=slug).exists() + + def _get_autogenerated_slug(self, base_slug): + candidate_slug = base_slug + suffix = 1 + parent_page = self.get_parent() + + while not Page._slug_is_available(candidate_slug, parent_page, self): + suffix += 1 + candidate_slug = "%s-%d" % (base_slug, suffix) + + return candidate_slug + + def full_clean(self, *args, **kwargs): + + if not self.slug: + allow_unicode = getattr(settings, 'WAGTAIL_ALLOW_UNICODE_SLUGS', True) +~~ base_slug = slugify(self.title, allow_unicode=allow_unicode) + + if base_slug: + self.slug = self._get_autogenerated_slug(base_slug) + + if not self.draft_title: + self.draft_title = self.title + + super().full_clean(*args, **kwargs) + + def clean(self): + super().clean() + if not Page._slug_is_available(self.slug, self.get_parent(), self): + raise ValidationError({'slug': _("This slug is already in use")}) + + @transaction.atomic + def save(self, clean=True, **kwargs): + if clean: + self.full_clean() + + update_descendant_url_paths = False + is_new = self.id is None + + if is_new: + self.set_url_path(self.get_parent()) + + +## ... source file continues with no further slugify examples... + +``` + diff --git a/content/pages/examples/django/django-utils-text-truncator.markdown b/content/pages/examples/django/django-utils-text-truncator.markdown new file mode 100644 index 000000000..a0fb92648 --- /dev/null +++ b/content/pages/examples/django/django-utils-text-truncator.markdown @@ -0,0 +1,152 @@ +title: django.utils.text Truncator Example Code +category: page +slug: django-utils-text-truncator-examples +sortorder: 500011488 +toc: False +sidebartitle: django.utils.text Truncator +meta: Python example code for the Truncator class from the django.utils.text module of the Django project. + + +Truncator is a class within the django.utils.text module of the Django project. + + +## Example 1 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / admin / widgets.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/admin/widgets.py) + +```python +# widgets.py +import six +from six.moves import urllib +from django import forms +from django.contrib.admin.sites import site +from django.contrib.admin.widgets import ForeignKeyRawIdWidget +from django.template.loader import render_to_string +from django.templatetags.static import static +from django.urls import reverse +from django.utils.safestring import mark_safe +~~from django.utils.text import Truncator + + +class ForeignKeySearchInput(ForeignKeyRawIdWidget): + + widget_template = None + search_path = None + + def _media(self): + js_files = [ + static('django_extensions/js/jquery.bgiframe.js'), + static('django_extensions/js/jquery.ajaxQueue.js'), + static('django_extensions/js/jquery.autocomplete.js'), + ] + + return forms.Media( + css={'all': (static('django_extensions/css/jquery.autocomplete.css'), )}, + js=js_files, + ) + media = property(_media) + + def label_for_value(self, value): + key = self.rel.get_related_field().name + obj = self.rel.model._default_manager.get(**{key: value}) + +~~ return Truncator(obj).words(14, truncate='...') + + def __init__(self, rel, search_fields, attrs=None): + self.search_fields = search_fields + super().__init__(rel, site, attrs) + + def render(self, name, value, attrs=None, renderer=None): + if attrs is None: + attrs = {} + opts = self.rel.model._meta + app_label = opts.app_label + model_name = opts.object_name.lower() + related_url = reverse('admin:%s_%s_changelist' % (app_label, model_name)) + if not self.search_path: + self.search_path = urllib.parse.urljoin(related_url, 'foreignkey_autocomplete/') + params = self.url_parameters() + if params: + url = '?' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()]) + else: + url = '' + + if 'class' not in attrs: + attrs['class'] = 'vForeignKeyRawIdAdminField' + output = [forms.TextInput.render(self, name, value, attrs)] + + + +## ... source file continues with no further Truncator examples... + +``` + + +## Example 2 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / utils / compatibility.py**](https://github.com/divio/django-filer/blob/develop/filer/utils/compatibility.py) + +```python +# compatibility.py +from __future__ import absolute_import, unicode_literals + +import sys + +from django.utils import six +from django.utils.functional import keep_lazy +~~from django.utils.text import Truncator, format_lazy + + +def string_concat(*strings): + return format_lazy('{}' * len(strings), *strings) + + +def truncate_words(s, num, end_text='...'): + truncate = end_text and ' %s' % end_text or '' +~~ return Truncator(s).words(num, truncate=truncate) + + +truncate_words = keep_lazy(truncate_words, six.text_type) + + +if not six.PY3: + fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() + + +def upath(path): + if six.PY2 and not isinstance(path, six.text_type): + return path.decode(fs_encoding) + return path + + +def get_delete_permission(opts): + from django.contrib.auth import get_permission_codename # noqa + return '%s.%s' % (opts.app_label, get_permission_codename('delete', opts)) + + +try: + from PIL import Image as PILImage # noqa + from PIL import ImageDraw as PILImageDraw # noqa + from PIL import ExifTags as PILExifTags # noqa + + +## ... source file continues with no further Truncator examples... + +``` + diff --git a/content/pages/examples/django/django-utils-timezone-get-current-timezone.markdown b/content/pages/examples/django/django-utils-timezone-get-current-timezone.markdown new file mode 100644 index 000000000..fd87a5d16 --- /dev/null +++ b/content/pages/examples/django/django-utils-timezone-get-current-timezone.markdown @@ -0,0 +1,79 @@ +title: django.utils.timezone get_current_timezone Example Code +category: page +slug: django-utils-timezone-get-current-timezone-examples +sortorder: 500011494 +toc: False +sidebartitle: django.utils.timezone get_current_timezone +meta: Python example code for the get_current_timezone callable from the django.utils.timezone module of the Django project. + + +get_current_timezone is a callable within the django.utils.timezone module of the Django project. + + +## Example 1 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / models / imagemodels.py**](https://github.com/divio/django-filer/blob/develop/filer/models/imagemodels.py) + +```python +# imagemodels.py +from __future__ import absolute_import + +import logging +from datetime import datetime + +from django.conf import settings +from django.db import models +~~from django.utils.timezone import get_current_timezone, make_aware, now +from django.utils.translation import ugettext_lazy as _ + +from .abstract import BaseImage + + +logger = logging.getLogger("filer") + + +class Image(BaseImage): + date_taken = models.DateTimeField(_('date taken'), null=True, blank=True, + editable=False) + author = models.CharField(_('author'), max_length=255, null=True, blank=True) + must_always_publish_author_credit = models.BooleanField(_('must always publish author credit'), default=False) + must_always_publish_copyright = models.BooleanField(_('must always publish copyright'), default=False) + + class Meta(BaseImage.Meta): + swappable = 'FILER_IMAGE_MODEL' + default_manager_name = 'objects' + + def save(self, *args, **kwargs): + if self.date_taken is None: + try: + exif_date = self.exif.get('DateTimeOriginal', None) + if exif_date is not None: + d, t = exif_date.split(" ") + year, month, day = d.split(':') + hour, minute, second = t.split(':') + if getattr(settings, "USE_TZ", False): +~~ tz = get_current_timezone() + self.date_taken = make_aware(datetime( + int(year), int(month), int(day), + int(hour), int(minute), int(second)), tz) + else: + self.date_taken = datetime( + int(year), int(month), int(day), + int(hour), int(minute), int(second)) + except Exception: + pass + if self.date_taken is None: + self.date_taken = now() + super(Image, self).save(*args, **kwargs) + + + +## ... source file continues with no further get_current_timezone examples... + +``` + diff --git a/content/pages/examples/django/django-utils-timezone-make-aware.markdown b/content/pages/examples/django/django-utils-timezone-make-aware.markdown new file mode 100644 index 000000000..7935b8df0 --- /dev/null +++ b/content/pages/examples/django/django-utils-timezone-make-aware.markdown @@ -0,0 +1,296 @@ +title: django.utils.timezone make_aware Example Code +category: page +slug: django-utils-timezone-make-aware-examples +sortorder: 500011495 +toc: False +sidebartitle: django.utils.timezone make_aware +meta: Python example code for the make_aware callable from the django.utils.timezone module of the Django project. + + +make_aware is a callable within the django.utils.timezone module of the Django project. + + +## Example 1 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / models / imagemodels.py**](https://github.com/divio/django-filer/blob/develop/filer/models/imagemodels.py) + +```python +# imagemodels.py +from __future__ import absolute_import + +import logging +from datetime import datetime + +from django.conf import settings +from django.db import models +~~from django.utils.timezone import get_current_timezone, make_aware, now +from django.utils.translation import ugettext_lazy as _ + +from .abstract import BaseImage + + +logger = logging.getLogger("filer") + + +class Image(BaseImage): + date_taken = models.DateTimeField(_('date taken'), null=True, blank=True, + editable=False) + author = models.CharField(_('author'), max_length=255, null=True, blank=True) + must_always_publish_author_credit = models.BooleanField(_('must always publish author credit'), default=False) + must_always_publish_copyright = models.BooleanField(_('must always publish copyright'), default=False) + + class Meta(BaseImage.Meta): + swappable = 'FILER_IMAGE_MODEL' + default_manager_name = 'objects' + + def save(self, *args, **kwargs): + if self.date_taken is None: + try: + exif_date = self.exif.get('DateTimeOriginal', None) + if exif_date is not None: + d, t = exif_date.split(" ") + year, month, day = d.split(':') + hour, minute, second = t.split(':') + if getattr(settings, "USE_TZ", False): + tz = get_current_timezone() +~~ self.date_taken = make_aware(datetime( + int(year), int(month), int(day), + int(hour), int(minute), int(second)), tz) + else: + self.date_taken = datetime( + int(year), int(month), int(day), + int(hour), int(minute), int(second)) + except Exception: + pass + if self.date_taken is None: + self.date_taken = now() + super(Image, self).save(*args, **kwargs) + + + +## ... source file continues with no further make_aware examples... + +``` + + +## Example 2 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / oauth2_validators.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/./oauth2_validators.py) + +```python +# oauth2_validators.py +import base64 +import binascii +import http.client +import logging +from collections import OrderedDict +from datetime import datetime, timedelta +from urllib.parse import unquote_plus + +import requests +from django.conf import settings +from django.contrib.auth import authenticate, get_user_model +from django.core.exceptions import ObjectDoesNotExist +from django.db import transaction +from django.db.models import Q +from django.utils import timezone +~~from django.utils.timezone import make_aware +from django.utils.translation import gettext_lazy as _ +from oauthlib.oauth2 import RequestValidator + +from .exceptions import FatalClientError +from .models import ( + AbstractApplication, get_access_token_model, + get_application_model, get_grant_model, get_refresh_token_model +) +from .scopes import get_scopes_backend +from .settings import oauth2_settings + + +log = logging.getLogger("oauth2_provider") + +GRANT_TYPE_MAPPING = { + "authorization_code": (AbstractApplication.GRANT_AUTHORIZATION_CODE, ), + "password": (AbstractApplication.GRANT_PASSWORD, ), + "client_credentials": (AbstractApplication.GRANT_CLIENT_CREDENTIALS, ), + "refresh_token": ( + AbstractApplication.GRANT_AUTHORIZATION_CODE, + AbstractApplication.GRANT_PASSWORD, + AbstractApplication.GRANT_CLIENT_CREDENTIALS, + ) +} + + +## ... source file abbreviated to get to make_aware examples ... + + + content = response.json() + except ValueError: + log.exception("Introspection: Failed to parse response as json") + return None + + if "active" in content and content["active"] is True: + if "username" in content: + user, _created = UserModel.objects.get_or_create( + **{UserModel.USERNAME_FIELD: content["username"]} + ) + else: + user = None + + max_caching_time = datetime.now() + timedelta( + seconds=oauth2_settings.RESOURCE_SERVER_TOKEN_CACHING_SECONDS + ) + + if "exp" in content: + expires = datetime.utcfromtimestamp(content["exp"]) + if expires > max_caching_time: + expires = max_caching_time + else: + expires = max_caching_time + + scope = content.get("scope", "") +~~ expires = make_aware(expires) + + access_token, _created = AccessToken.objects.update_or_create( + token=token, + defaults={ + "user": user, + "application": None, + "scope": scope, + "expires": expires, + }) + + return access_token + + def validate_bearer_token(self, token, scopes, request): + if not token: + return False + + introspection_url = oauth2_settings.RESOURCE_SERVER_INTROSPECTION_URL + introspection_token = oauth2_settings.RESOURCE_SERVER_AUTH_TOKEN + introspection_credentials = oauth2_settings.RESOURCE_SERVER_INTROSPECTION_CREDENTIALS + + try: + access_token = AccessToken.objects.select_related("application", "user").get(token=token) + except AccessToken.DoesNotExist: + access_token = None + + +## ... source file continues with no further make_aware examples... + +``` + + +## Example 3 from graphite-web +[Graphite](https://github.com/graphite-project/graphite-web) +([project website](http://graphiteapp.org/), +[documentation](https://graphite.readthedocs.io/en/latest/) and +[PyPI package information](https://pypi.org/project/graphite-web/)) +is a metrics collection and visualization tool, built with both +Python and JavaScript. Metrics are collected by a Node.js application +and displayed using a [Django](/django.html) web application, +called "Graphite-Web", which is one of three core projects under +the Graphite umbrella (the other two are +[Carbon](https://github.com/graphite-project/carbon) and +[Whisper](https://github.com/graphite-project/whisper)). + +Graphite is provided as open sourced under the +[Apache License 2.0](https://github.com/graphite-project/whisper/blob/master/LICENSE). + +[**graphite-web / webapp / graphite / util.py**](https://github.com/graphite-project/graphite-web/blob/master/webapp/graphite/util.py) + +```python +# util.py + +import imp +import io +import json as _json +import socket +import time +import sys +import calendar +import pytz +import six +import traceback + +from datetime import datetime +from functools import wraps +from os.path import splitext, basename + +from django.conf import settings +~~from django.utils.timezone import make_aware + +from graphite.compat import HttpResponse +from graphite.logger import log + +if sys.version_info >= (3, 0): + PY3 = True + import pickle + from io import BytesIO +else: + PY3 = False + import cPickle as pickle + from cStringIO import StringIO as BytesIO + +try: + import msgpack # NOQA +except ImportError: + import graphite.umsgpack as msgpack # NOQA + + +def epoch(dt): + if not dt.tzinfo: + tb = traceback.extract_stack(None, 2) + log.warning('epoch() called with non-timezone-aware datetime in %s at %s:%d' % (tb[0][2], tb[0][0], tb[0][1])) + return calendar.timegm(make_aware(dt, pytz.timezone(settings.TIME_ZONE)).astimezone(pytz.utc).timetuple()) + return calendar.timegm(dt.astimezone(pytz.utc).timetuple()) + + +def epoch_to_dt(timestamp): +~~ return make_aware(datetime.utcfromtimestamp(timestamp), pytz.utc) + + +def timebounds(requestContext): + startTime = int(epoch(requestContext['startTime'])) + endTime = int(epoch(requestContext['endTime'])) + now = int(epoch(requestContext['now'])) + + return (startTime, endTime, now) + + +def is_local_interface(host): + is_ipv6 = False + if ':' not in host: + pass + elif host.count(':') == 1: + host = host.split(':', 1)[0] + else: + is_ipv6 = True + + if host.find('[', 0, 2) != -1: + last_bracket_position = host.rfind(']') + last_colon_position = host.rfind(':') + if last_colon_position > last_bracket_position: + host = host.rsplit(':', 1)[0] + + +## ... source file continues with no further make_aware examples... + +``` + diff --git a/content/pages/examples/django/django-utils-timezone-now.markdown b/content/pages/examples/django/django-utils-timezone-now.markdown new file mode 100644 index 000000000..46a227ee3 --- /dev/null +++ b/content/pages/examples/django/django-utils-timezone-now.markdown @@ -0,0 +1,825 @@ +title: django.utils.timezone now Example Code +category: page +slug: django-utils-timezone-now-examples +sortorder: 500011496 +toc: False +sidebartitle: django.utils.timezone now +meta: Python example code for the now callable from the django.utils.timezone module of the Django project. + + +now is a callable within the django.utils.timezone module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / utils.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/utils.py) + +```python +# utils.py +import unicodedata +from collections import OrderedDict +from datetime import timedelta + +from django.conf import settings +from django.contrib import messages +from django.contrib.auth import update_session_auth_hash +from django.core.exceptions import FieldDoesNotExist, ValidationError +from django.db import models +from django.db.models import Q +from django.http import HttpResponseRedirect +from django.utils.encoding import force_str +from django.utils.http import base36_to_int, int_to_base36, urlencode +~~from django.utils.timezone import now + +from ..exceptions import ImmediateHttpResponse +from ..utils import ( + get_request_param, + get_user_model, + import_callable, + valid_email_or_none, +) +from . import app_settings, signals +from .adapter import get_adapter +from .app_settings import EmailVerificationMethod + + +def _unicode_ci_compare(s1, s2): + norm_s1 = unicodedata.normalize('NFKC', s1).casefold() + norm_s2 = unicodedata.normalize('NFKC', s2).casefold() + return norm_s1 == norm_s2 + + +def get_next_redirect_url(request, redirect_field_name="next"): + redirect_to = get_request_param(request, redirect_field_name) + if not get_adapter(request).is_safe_url(redirect_to): + redirect_to = None + return redirect_to + + +## ... source file abbreviated to get to now examples ... + + + a.user = user + a.save() + EmailAddress.objects.fill_cache_for_user(user, addresses) + if (primary and email and email.lower() != primary.email.lower()): + user_email(user, primary.email) + user.save() + return primary + + +def send_email_confirmation(request, user, signup=False): + from .models import EmailAddress, EmailConfirmation + + cooldown_period = timedelta( + seconds=app_settings.EMAIL_CONFIRMATION_COOLDOWN + ) + + email = user_email(user) + if email: + try: + email_address = EmailAddress.objects.get_for_user(user, email) + if not email_address.verified: + if app_settings.EMAIL_CONFIRMATION_HMAC: + send_email = True + else: + send_email = not EmailConfirmation.objects.filter( +~~ sent__gt=now() - cooldown_period, + email_address=email_address).exists() + if send_email: + email_address.send_confirmation(request, + signup=signup) + else: + send_email = False + except EmailAddress.DoesNotExist: + send_email = True + email_address = EmailAddress.objects.add_email(request, + user, + email, + signup=signup, + confirm=True) + assert email_address + if send_email: + get_adapter(request).add_message( + request, + messages.INFO, + 'account/messages/' + 'email_confirmation_sent.txt', + {'email': email}) + if signup: + get_adapter(request).stash_user(request, user_pk_to_url_str(user)) + + + +## ... source file continues with no further now examples... + +``` + + +## Example 2 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / attempts.py**](https://github.com/jazzband/django-axes/blob/master/axes/./attempts.py) + +```python +# attempts.py +from logging import getLogger + +from django.db.models import QuerySet +~~from django.utils.timezone import datetime, now + +from axes.conf import settings +from axes.models import AccessAttempt +from axes.helpers import get_client_username, get_client_parameters, get_cool_off + +log = getLogger(settings.AXES_LOGGER) + + +def get_cool_off_threshold(attempt_time: datetime = None) -> datetime: + + cool_off = get_cool_off() + if cool_off is None: + raise TypeError( + "Cool off threshold can not be calculated with settings.AXES_COOLOFF_TIME set to None" + ) + + if attempt_time is None: +~~ return now() - cool_off + return attempt_time - cool_off + + +def filter_user_attempts(request, credentials: dict = None) -> QuerySet: + + username = get_client_username(request, credentials) + + filter_kwargs = get_client_parameters( + username, request.axes_ip_address, request.axes_user_agent + ) + + return AccessAttempt.objects.filter(**filter_kwargs) + + +def get_user_attempts(request, credentials: dict = None) -> QuerySet: + + attempts = filter_user_attempts(request, credentials) + + if settings.AXES_COOLOFF_TIME is None: + log.debug( + "AXES: Getting all access attempts from database because no AXES_COOLOFF_TIME is configured" + ) + return attempts + + + +## ... source file continues with no further now examples... + +``` + + +## Example 3 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / views.py**](https://github.com/divio/django-cms/blob/develop/cms/./views.py) + +```python +# views.py + +from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login +from django.contrib.auth.views import redirect_to_login +from django.http import HttpResponse, HttpResponseRedirect +from django.urls import reverse +from django.utils.cache import patch_cache_control +from django.utils.http import is_safe_url, urlquote +~~from django.utils.timezone import now +from django.utils.translation import get_language_from_request +from django.views.decorators.http import require_POST + +from cms.cache.page import get_page_cache +from cms.exceptions import LanguageError +from cms.forms.login import CMSToolbarLoginForm +from cms.models.pagemodel import TreeNode +from cms.page_rendering import _handle_no_page, render_page, render_object_structure, _render_welcome_page +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils import get_current_site +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import (get_fallback_languages, get_public_languages, + get_redirect_on_fallback, get_language_list, + get_default_language_for_site, + is_language_prefix_patterns_used) +from cms.utils.page import get_page_from_request +from cms.utils.page_permissions import user_can_change_page + + +def _clean_redirect_url(redirect_url, language): + if (redirect_url and is_language_prefix_patterns_used() and redirect_url[0] == "/" + and not redirect_url.startswith('/%s/' % language)): + redirect_url = "/%s/%s" % (language, redirect_url.lstrip("/")) + return redirect_url + + +def details(request, slug): +~~ response_timestamp = now() + if get_cms_setting("PAGE_CACHE") and ( + not hasattr(request, 'toolbar') or ( + not request.toolbar.edit_mode_active and + not request.toolbar.show_toolbar and + not request.user.is_authenticated + ) + ): + cache_content = get_page_cache(request) + if cache_content is not None: + content, headers, expires_datetime = cache_content + response = HttpResponse(content) + response.xframe_options_exempt = True + response._headers = headers + max_age = int( + (expires_datetime - response_timestamp).total_seconds() + 0.5) + patch_cache_control(response, max_age=max_age) + return response + + site = get_current_site() + page = get_page_from_request(request, use_path=slug) + toolbar = get_toolbar_from_request(request) + tree_nodes = TreeNode.objects.get_for_site(site) + + if not page and not slug and not tree_nodes.exists(): + + +## ... source file continues with no further now examples... + +``` + + +## Example 4 from django-downloadview +[django-downloadview](https://github.com/benoitbryon/django-downloadview) +([project documentation](https://django-downloadview.readthedocs.io/en/1.9/) +and +[PyPI package information](https://pypi.org/project/django-downloadview/)) +is a [Django](/django.html) extension for serving downloads through your +web application. While typically you would use a web server to handle +[static content](/static-content.html), sometimes you need to control +file access, such as requiring a user to register before downloading a +PDF. In that situations, django-downloadview is a handy library to avoid +boilerplate code for common scenarios. + +[**django-downloadview / django_downloadview / nginx / response.py**](https://github.com/benoitbryon/django-downloadview/blob/master/django_downloadview/nginx/response.py) + +```python +# response.py +from datetime import timedelta + +~~from django.utils.timezone import now + +from django_downloadview.response import ProxiedDownloadResponse, content_disposition +from django_downloadview.utils import content_type_to_charset, url_basename + + +class XAccelRedirectResponse(ProxiedDownloadResponse): + "Http response that delegates serving file to Nginx via X-Accel headers." + + def __init__( + self, + redirect_url, + content_type, + basename=None, + expires=None, + with_buffering=None, + limit_rate=None, + attachment=True, + ): + super(XAccelRedirectResponse, self).__init__(content_type=content_type) + if attachment: + self.basename = basename or url_basename(redirect_url, content_type) + self["Content-Disposition"] = content_disposition(self.basename) + self["X-Accel-Redirect"] = redirect_url + self["X-Accel-Charset"] = content_type_to_charset(content_type) + if with_buffering is not None: + self["X-Accel-Buffering"] = with_buffering and "yes" or "no" + if expires: +~~ expire_seconds = timedelta(expires - now()).seconds + self["X-Accel-Expires"] = expire_seconds + elif expires is not None: # We explicitely want it off. + self["X-Accel-Expires"] = "off" + if limit_rate is not None: + self["X-Accel-Limit-Rate"] = limit_rate and "%d" % limit_rate or "off" + + + +## ... source file continues with no further now examples... + +``` + + +## Example 5 from django-extensions +[django-extensions](https://github.com/django-extensions/django-extensions) +([project documentation](https://django-extensions.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-extensions/)) +is a [Django](/django.html) project that adds a bunch of additional +useful commands to the `manage.py` interface. This +[GoDjango video](https://www.youtube.com/watch?v=1F6G3ONhr4k) provides a +quick overview of what you get when you install it into your Python +environment. + +The django-extensions project is open sourced under the +[MIT license](https://github.com/django-extensions/django-extensions/blob/master/LICENSE). + +[**django-extensions / django_extensions / db / models.py**](https://github.com/django-extensions/django-extensions/blob/master/django_extensions/db/models.py) + +```python +# models.py + +from django.db import models +~~from django.utils.timezone import now +from django.utils.translation import gettext_lazy as _ + +from django_extensions.db.fields import AutoSlugField, CreationDateTimeField, ModificationDateTimeField + + +class TimeStampedModel(models.Model): + + created = CreationDateTimeField(_('created')) + modified = ModificationDateTimeField(_('modified')) + + def save(self, **kwargs): + self.update_modified = kwargs.pop('update_modified', getattr(self, 'update_modified', True)) + super().save(**kwargs) + + class Meta: + get_latest_by = 'modified' + abstract = True + + +class TitleDescriptionModel(models.Model): + + title = models.CharField(_('title'), max_length=255) + description = models.TextField(_('description'), blank=True, null=True) + + + +## ... source file abbreviated to get to now examples ... + + + + def inactive(self): + return self.get_queryset().inactive() + + +class ActivatorModel(models.Model): + + INACTIVE_STATUS = 0 + ACTIVE_STATUS = 1 + + STATUS_CHOICES = ( + (INACTIVE_STATUS, _('Inactive')), + (ACTIVE_STATUS, _('Active')), + ) + status = models.IntegerField(_('status'), choices=STATUS_CHOICES, default=ACTIVE_STATUS) + activate_date = models.DateTimeField(blank=True, null=True, help_text=_('keep empty for an immediate activation')) + deactivate_date = models.DateTimeField(blank=True, null=True, help_text=_('keep empty for indefinite activation')) + objects = ActivatorModelManager() + + class Meta: + ordering = ('status', '-activate_date',) + abstract = True + + def save(self, *args, **kwargs): + if not self.activate_date: +~~ self.activate_date = now() + super().save(*args, **kwargs) + + + +## ... source file continues with no further now examples... + +``` + + +## Example 6 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / models / imagemodels.py**](https://github.com/divio/django-filer/blob/develop/filer/models/imagemodels.py) + +```python +# imagemodels.py +from __future__ import absolute_import + +import logging +from datetime import datetime + +from django.conf import settings +from django.db import models +~~from django.utils.timezone import get_current_timezone, make_aware, now +from django.utils.translation import ugettext_lazy as _ + +from .abstract import BaseImage + + +logger = logging.getLogger("filer") + + +class Image(BaseImage): + date_taken = models.DateTimeField(_('date taken'), null=True, blank=True, + editable=False) + author = models.CharField(_('author'), max_length=255, null=True, blank=True) + must_always_publish_author_credit = models.BooleanField(_('must always publish author credit'), default=False) + must_always_publish_copyright = models.BooleanField(_('must always publish copyright'), default=False) + + class Meta(BaseImage.Meta): + swappable = 'FILER_IMAGE_MODEL' + default_manager_name = 'objects' + + def save(self, *args, **kwargs): + if self.date_taken is None: + try: + exif_date = self.exif.get('DateTimeOriginal', None) + if exif_date is not None: + d, t = exif_date.split(" ") + year, month, day = d.split(':') + hour, minute, second = t.split(':') + if getattr(settings, "USE_TZ", False): + tz = get_current_timezone() + self.date_taken = make_aware(datetime( + int(year), int(month), int(day), + int(hour), int(minute), int(second)), tz) + else: + self.date_taken = datetime( + int(year), int(month), int(day), + int(hour), int(minute), int(second)) + except Exception: + pass + if self.date_taken is None: +~~ self.date_taken = now() + super(Image, self).save(*args, **kwargs) + + + +## ... source file continues with no further now examples... + +``` + + +## Example 7 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / filters.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./filters.py) + +```python +# filters.py +from collections import OrderedDict +from datetime import timedelta + +from django import forms +from django.db.models import Q +from django.db.models.constants import LOOKUP_SEP +from django.forms.utils import pretty_name +from django.utils.itercompat import is_iterable +~~from django.utils.timezone import now +from django.utils.translation import gettext_lazy as _ + +from .conf import settings +from .constants import EMPTY_VALUES +from .fields import ( + BaseCSVField, + BaseRangeField, + ChoiceField, + DateRangeField, + DateTimeRangeField, + IsoDateTimeField, + IsoDateTimeRangeField, + LookupChoiceField, + ModelChoiceField, + ModelMultipleChoiceField, + MultipleChoiceField, + RangeField, + TimeRangeField +) +from .utils import get_model_field, label_for_filter + +__all__ = [ + 'AllValuesFilter', + 'AllValuesMultipleFilter', + + +## ... source file abbreviated to get to now examples ... + + + elif value.start is not None: + self.lookup_expr = 'gte' + value = value.start + elif value.stop is not None: + self.lookup_expr = 'lte' + value = value.stop + + return super().filter(qs, value) + + +def _truncate(dt): + return dt.date() + + +class DateRangeFilter(ChoiceFilter): + choices = [ + ('today', _('Today')), + ('yesterday', _('Yesterday')), + ('week', _('Past 7 days')), + ('month', _('This month')), + ('year', _('This year')), + ] + + filters = { + 'today': lambda qs, name: qs.filter(**{ +~~ '%s__year' % name: now().year, +~~ '%s__month' % name: now().month, +~~ '%s__day' % name: now().day + }), + 'yesterday': lambda qs, name: qs.filter(**{ + '%s__year' % name: (now() - timedelta(days=1)).year, + '%s__month' % name: (now() - timedelta(days=1)).month, + '%s__day' % name: (now() - timedelta(days=1)).day, + }), + 'week': lambda qs, name: qs.filter(**{ + '%s__gte' % name: _truncate(now() - timedelta(days=7)), + '%s__lt' % name: _truncate(now() + timedelta(days=1)), + }), + 'month': lambda qs, name: qs.filter(**{ +~~ '%s__year' % name: now().year, +~~ '%s__month' % name: now().month + }), + 'year': lambda qs, name: qs.filter(**{ +~~ '%s__year' % name: now().year, + }), + } + + def __init__(self, choices=None, filters=None, *args, **kwargs): + if choices is not None: + self.choices = choices + if filters is not None: + self.filters = filters + + unique = set([x[0] for x in self.choices]) ^ set(self.filters) + assert not unique, \ + "Keys must be present in both 'choices' and 'filters'. Missing keys: " \ + "'%s'" % ', '.join(sorted(unique)) + + assert not hasattr(self, 'options'), \ + "The 'options' attribute has been replaced by 'choices' and 'filters'. " \ + "See: https://django-filter.readthedocs.io/en/master/guide/migration.html" + + kwargs.setdefault('null_label', None) + super().__init__(choices=self.choices, *args, **kwargs) + + def filter(self, qs, value): + if not value: + return qs + + +## ... source file continues with no further now examples... + +``` + + +## Example 8 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / mixins.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./mixins.py) + +```python +# mixins.py +from django.http import HttpResponse +~~from django.utils.timezone import now +from django.views.generic.edit import FormView + +from .formats import base_formats +from .forms import ExportForm +from .resources import modelresource_factory +from .signals import post_export + + +class ExportViewMixin: + formats = base_formats.DEFAULT_FORMATS + form_class = ExportForm + resource_class = None + + def get_export_formats(self): + return [f for f in self.formats if f().can_export()] + + def get_resource_class(self): + if not self.resource_class: + return modelresource_factory(self.model) + return self.resource_class + + def get_export_resource_class(self): + return self.get_resource_class() + + def get_resource_kwargs(self, request, *args, **kwargs): + return {} + + def get_export_resource_kwargs(self, request, *args, **kwargs): + return self.get_resource_kwargs(request, *args, **kwargs) + + def get_export_data(self, file_format, queryset, *args, **kwargs): + resource_class = self.get_export_resource_class() + data = resource_class(**self.get_export_resource_kwargs(self.request))\ + .export(queryset, *args, **kwargs) + export_data = file_format.export_data(data) + return export_data + + def get_export_filename(self, file_format): +~~ date_str = now().strftime('%Y-%m-%d') + filename = "%s-%s.%s" % (self.model.__name__, + date_str, + file_format.get_extension()) + return filename + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + return context + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs['formats'] = self.get_export_formats() + return kwargs + + +class ExportViewFormMixin(ExportViewMixin, FormView): + def form_valid(self, form): + formats = self.get_export_formats() + file_format = formats[ + int(form.cleaned_data['file_format']) + ]() + if hasattr(self, 'get_filterset'): + queryset = self.get_filterset(self.get_filterset_class()).qs + else: + + +## ... source file continues with no further now examples... + +``` + + +## Example 9 from django-model-utils +[django-model-utils](https://github.com/jazzband/django-model-utils) +([project documentation](https://django-model-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-model-utils/)) +provides useful mixins and utilities for working with +[Django ORM](/django-orm.html) models in your projects. + +The django-model-utils project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/jazzband/django-model-utils/blob/master/LICENSE.txt). + +[**django-model-utils / model_utils / fields.py**](https://github.com/jazzband/django-model-utils/blob/master/model_utils/./fields.py) + +```python +# fields.py +import uuid +from django.db import models +from django.conf import settings +from django.core.exceptions import ValidationError +~~from django.utils.timezone import now + +DEFAULT_CHOICES_NAME = 'STATUS' + + +class AutoCreatedField(models.DateTimeField): + + def __init__(self, *args, **kwargs): + kwargs.setdefault('editable', False) + kwargs.setdefault('default', now) + super().__init__(*args, **kwargs) + + +class AutoLastModifiedField(AutoCreatedField): + def get_default(self): + if not hasattr(self, "_default"): + self._default = self._get_default() + return self._default + + def pre_save(self, model_instance, add): +~~ value = now() + if add: + current_value = getattr(model_instance, self.attname, self.get_default()) + if current_value != self.get_default(): + value = getattr(model_instance, self.attname) + else: + for field in model_instance._meta.get_fields(): + if isinstance(field, AutoCreatedField): + value = getattr(model_instance, field.name) + break + setattr(model_instance, self.attname, value) + return value + + +class StatusField(models.CharField): + + def __init__(self, *args, **kwargs): + kwargs.setdefault('max_length', 100) + self.check_for_status = not kwargs.pop('no_check_for_status', False) + self.choices_name = kwargs.pop('choices_name', DEFAULT_CHOICES_NAME) + super().__init__(*args, **kwargs) + + def prepare_class(self, sender, **kwargs): + if not sender._meta.abstract and self.check_for_status: + assert hasattr(sender, self.choices_name), \ + + +## ... source file abbreviated to get to now examples ... + + + monitor = kwargs.pop('monitor', None) + if not monitor: + raise TypeError( + '%s requires a "monitor" argument' % self.__class__.__name__) + self.monitor = monitor + when = kwargs.pop('when', None) + if when is not None: + when = set(when) + self.when = when + super().__init__(*args, **kwargs) + + def contribute_to_class(self, cls, name): + self.monitor_attname = '_monitor_%s' % name + models.signals.post_init.connect(self._save_initial, sender=cls) + super().contribute_to_class(cls, name) + + def get_monitored_value(self, instance): + return getattr(instance, self.monitor) + + def _save_initial(self, sender, instance, **kwargs): + if self.monitor in instance.get_deferred_fields(): + return + setattr(instance, self.monitor_attname, self.get_monitored_value(instance)) + + def pre_save(self, model_instance, add): +~~ value = now() + previous = getattr(model_instance, self.monitor_attname, None) + current = self.get_monitored_value(model_instance) + if previous != current: + if self.when is None or current in self.when: + setattr(model_instance, self.attname, value) + self._save_initial(model_instance.__class__, model_instance) + return super().pre_save(model_instance, add) + + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + kwargs['monitor'] = self.monitor + if self.when is not None: + kwargs['when'] = self.when + return name, path, args, kwargs + + +SPLIT_MARKER = getattr(settings, 'SPLIT_MARKER', '') + +SPLIT_DEFAULT_PARAGRAPHS = getattr(settings, 'SPLIT_DEFAULT_PARAGRAPHS', 2) + + +def _excerpt_field_name(name): + return '_%s_excerpt' % name + + + +## ... source file continues with no further now examples... + +``` + diff --git a/content/pages/examples/django/django-utils-timezone-timedelta.markdown b/content/pages/examples/django/django-utils-timezone-timedelta.markdown new file mode 100644 index 000000000..4bd751e05 --- /dev/null +++ b/content/pages/examples/django/django-utils-timezone-timedelta.markdown @@ -0,0 +1,177 @@ +title: django.utils.timezone timedelta Example Code +category: page +slug: django-utils-timezone-timedelta-examples +sortorder: 500011497 +toc: False +sidebartitle: django.utils.timezone timedelta +meta: Python example code for the timedelta callable from the django.utils.timezone module of the Django project. + + +timedelta is a callable within the django.utils.timezone module of the Django project. + + +## Example 1 from django-axes +[django-axes](https://github.com/jazzband/django-axes/) +([project documentation](https://django-axes.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-axes/) +is a code library for [Django](/django.html) projects to track failed +login attempts against a web application. The goal of the project is +to make it easier for you to stop people and scripts from hacking your +Django-powered website. + +The code for django-axes is +[open source under the MIT license](https://github.com/jazzband/django-axes/blob/master/LICENSE) +and maintained by the group of developers known as +[Jazzband](https://jazzband.co/). + +[**django-axes / axes / tests / test_handlers.py**](https://github.com/jazzband/django-axes/blob/master/axes/tests/test_handlers.py) + +```python +# test_handlers.py +from unittest.mock import MagicMock, patch + +from django.test import override_settings +from django.urls import reverse +from django.utils import timezone +~~from django.utils.timezone import timedelta + +from axes.conf import settings +from axes.handlers.proxy import AxesProxyHandler +from axes.helpers import get_client_str +from axes.models import AccessAttempt, AccessLog +from axes.tests.base import AxesTestCase + + +@override_settings(AXES_HANDLER="axes.handlers.base.AxesHandler") +class AxesHandlerTestCase(AxesTestCase): + def test_base_handler_reset_attempts_raises(self): + with self.assertRaises(NotImplementedError): + AxesProxyHandler.reset_attempts() + + def test_base_handler_reset_logs_raises(self): + with self.assertRaises(NotImplementedError): + AxesProxyHandler.reset_logs() + + def test_base_handler_raises_on_undefined_is_allowed_to_authenticate(self): + with self.assertRaises(NotImplementedError): + AxesProxyHandler.is_allowed(self.request, {}) + + @override_settings(AXES_IP_BLACKLIST=["127.0.0.1"]) + def test_is_allowed_with_blacklisted_ip_address(self): + + +## ... source file abbreviated to get to timedelta examples ... + + + +class AxesHandlerBaseTestCase(AxesTestCase): + def check_whitelist(self, log): + with override_settings( + AXES_NEVER_LOCKOUT_WHITELIST=True, AXES_IP_WHITELIST=[self.ip_address] + ): + AxesProxyHandler.user_login_failed( + sender=None, request=self.request, credentials=self.credentials + ) + client_str = get_client_str( + self.username, self.ip_address, self.user_agent, self.path_info + ) + log.info.assert_called_with( + "AXES: Login failed from whitelisted client %s.", client_str + ) + + def check_empty_request(self, log, handler): + AxesProxyHandler.user_login_failed(sender=None, credentials={}, request=None) + log.error.assert_called_with( + f"AXES: {handler}.user_login_failed does not function without a request." + ) + + +@override_settings( + AXES_HANDLER="axes.handlers.database.AxesDatabaseHandler", +~~ AXES_COOLOFF_TIME=timedelta(seconds=1), + AXES_RESET_ON_SUCCESS=True, +) +class AxesDatabaseHandlerTestCase(AxesHandlerBaseTestCase): + def test_handler_reset_attempts(self): + self.create_attempt() + self.assertEqual(1, AxesProxyHandler.reset_attempts()) + self.assertFalse(AccessAttempt.objects.count()) + + def test_handler_reset_logs(self): + self.create_log() + self.assertEqual(1, AxesProxyHandler.reset_logs()) + self.assertFalse(AccessLog.objects.count()) + + def test_handler_reset_logs_older_than_42_days(self): + self.create_log() + + then = timezone.now() - timezone.timedelta(days=90) + with patch("django.utils.timezone.now", return_value=then): + self.create_log() + + self.assertEqual(AccessLog.objects.count(), 2) + self.assertEqual(1, AxesProxyHandler.reset_logs(age_days=42)) + self.assertEqual(AccessLog.objects.count(), 1) + + + +## ... source file abbreviated to get to timedelta examples ... + + + usernames, + ) in configurations: + with self.settings(**overrides): + with self.subTest( + total_attempts_count=total_attempts_count, + failures_since_start=failures_since_start, + settings=overrides, + ): + self.login(username=usernames[0]) + attempt = AccessAttempt.objects.get(username=usernames[0]) + self.assertEqual(1, attempt.failures_since_start) + + self.login(username=usernames[1]) + attempt = AccessAttempt.objects.get(username=usernames[1]) + self.assertEqual(failures_since_start, attempt.failures_since_start) + + self.assertEqual( + total_attempts_count, AccessAttempt.objects.count() + ) + + AccessAttempt.objects.all().delete() + + +@override_settings( + AXES_HANDLER="axes.handlers.cache.AxesCacheHandler", +~~ AXES_COOLOFF_TIME=timedelta(seconds=1), +) +class AxesCacheHandlerTestCase(AxesHandlerBaseTestCase): + @override_settings(AXES_RESET_ON_SUCCESS=True) + def test_handler(self): + self.check_handler() + + @override_settings(AXES_RESET_ON_SUCCESS=False) + def test_handler_without_reset(self): + self.check_handler() + + @override_settings(AXES_LOCK_OUT_AT_FAILURE=False) + def test_handler_without_lockout(self): + self.check_handler() + + @patch("axes.handlers.cache.log") + def test_empty_request(self, log): + self.check_empty_request(log, "AxesCacheHandler") + + @patch("axes.handlers.cache.log") + def test_whitelist(self, log): + self.check_whitelist(log) + + +@override_settings(AXES_HANDLER="axes.handlers.dummy.AxesDummyHandler") + + +## ... source file continues with no further timedelta examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-activate.markdown b/content/pages/examples/django/django-utils-translation-activate.markdown new file mode 100644 index 000000000..d5af83b0c --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-activate.markdown @@ -0,0 +1,241 @@ +title: django.utils.translation activate Example Code +category: page +slug: django-utils-translation-activate-examples +sortorder: 500011499 +toc: False +sidebartitle: django.utils.translation activate +meta: Python example code for the activate callable from the django.utils.translation module of the Django project. + + +activate is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_pool.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_pool.py) + +```python +# plugin_pool.py +from operator import attrgetter + +from django.core.exceptions import ImproperlyConfigured +from django.conf.urls import url, include +from django.template.defaultfilters import slugify +from django.utils.encoding import force_text +from django.utils.functional import cached_property +from django.utils.module_loading import autodiscover_modules +~~from django.utils.translation import get_language, deactivate_all, activate +from django.template import TemplateDoesNotExist, TemplateSyntaxError + +from six import string_types, text_type + +from cms.exceptions import PluginAlreadyRegistered, PluginNotRegistered +from cms.plugin_base import CMSPluginBase +from cms.utils.conf import get_cms_setting +from cms.utils.helpers import normalize_name + + +class PluginPool(object): + + def __init__(self): + self.plugins = {} + self.discovered = False + + def _clear_cached(self): + if 'registered_plugins' in self.__dict__: + del self.__dict__['registered_plugins'] + + if 'plugins_with_extra_menu' in self.__dict__: + del self.__dict__['plugins_with_extra_menu'] + + if 'plugins_with_extra_placeholder_menu' in self.__dict__: + + +## ... source file abbreviated to get to activate examples ... + + + def get_text_enabled_plugins(self, placeholder, page): + plugins = set(self.get_all_plugins(placeholder, page)) + plugins.update(self.get_all_plugins(placeholder, page, 'text_only_plugins')) + return sorted((p for p in plugins if p.text_enabled), + key=attrgetter('module', 'name')) + + def get_plugin(self, name): + self.discover_plugins() + return self.plugins[name] + + def get_patterns(self): + self.discover_plugins() + + lang = get_language() + deactivate_all() + + try: + url_patterns = [] + for plugin in self.registered_plugins: + p = plugin() + slug = slugify(force_text(normalize_name(p.__class__.__name__))) + url_patterns += [ + url(r'^plugin/%s/' % (slug,), include(p.plugin_urls)), + ] + finally: +~~ activate(lang) + + return url_patterns + + def get_system_plugins(self): + self.discover_plugins() + return [plugin.__name__ for plugin in self.plugins.values() if plugin.system] + + @cached_property + def registered_plugins(self): + return self.get_all_plugins() + + @cached_property + def plugins_with_extra_menu(self): + plugin_classes = [cls for cls in self.registered_plugins + if cls._has_extra_plugin_menu_items] + return plugin_classes + + @cached_property + def plugins_with_extra_placeholder_menu(self): + plugin_classes = [cls for cls in self.registered_plugins + if cls._has_extra_placeholder_menu_items] + return plugin_classes + + + + +## ... source file continues with no further activate examples... + +``` + + +## Example 2 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / tests / test_templatetags.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/tests/test_templatetags.py) + +```python +# test_templatetags.py +import pytest +from django.template.base import TemplateSyntaxError +~~from django.utils.translation import activate, deactivate_all + +from sitetree.exceptions import SiteTreeError +from sitetree.settings import ALIAS_THIS_ANCESTOR_CHILDREN, ALIAS_THIS_CHILDREN, ALIAS_THIS_PARENT_SIBLINGS, \ + ALIAS_THIS_SIBLINGS, ALIAS_TRUNK + + +def test_items_hook(template_render_tag, template_context, common_tree): + + from sitetree.toolbox import register_items_hook + + with pytest.raises(SiteTreeError): + register_items_hook(lambda: []) + + def my_processor(tree_items, tree_sender): + for item in tree_items: + item.hint = f'hooked_hint_{item.title}' + return tree_items + + register_items_hook(my_processor) + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', template_context()) + + assert 'hooked_hint_Darwin' in result + assert 'hooked_hint_Australia' in result + assert 'hooked_hint_China' in result + + +## ... source file abbreviated to get to activate examples ... + + + register_items_hook(None) # Reset. + + +def test_i18n(build_tree, template_render_tag, template_context): + + from sitetree.toolbox import register_i18n_trees + + build_tree( + {'alias': 'i18tree'}, + [{'title': 'My title', 'url': '/url_default/'}], + ) + build_tree( + {'alias': 'i18tree_ru'}, + [{'title': 'Заголовок', 'url': '/url_ru/'}], + ) + build_tree( + {'alias': 'i18tree_pt-br'}, + [{'title': 'Meu Título', 'url': '/url_pt-br/'}], + ) + build_tree( + {'alias': 'i18tree_zh-hans'}, + [{'title': '我蒂特', 'url': '/url_zh-hans/'}], + ) + register_i18n_trees(['i18tree']) + +~~ activate('en') + result = template_render_tag('sitetree', 'sitetree_tree from "i18tree"', template_context()) + + assert '/url_default/' in result + assert 'My title' in result + +~~ activate('ru') + result = template_render_tag('sitetree', 'sitetree_tree from "i18tree"', template_context()) + + assert '/url_ru/' in result + assert 'Заголовок' in result + +~~ activate('pt-br') + result = template_render_tag('sitetree', 'sitetree_tree from "i18tree"', template_context()) + + assert '/url_pt-br/' in result + assert 'Meu Título' in result + +~~ activate('zh-hans') + result = template_render_tag('sitetree', 'sitetree_tree from "i18tree"', template_context()) + + assert '/url_zh-hans/' in result + assert '我蒂特' in result + + deactivate_all() + + +def test_restricted(user_create, template_render_tag, template_context, common_tree): + context = template_context() + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', context) + + assert '"/contacts/australia/darwin/"' in result + assert '"/contacts/australia/alice/"' not in result + + context = template_context(user=user_create()) + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', context) + + assert '"/contacts/australia/darwin/"' not in result + assert '"/contacts/australia/alice/"' in result + + +def test_permissions(user_create, build_tree, template_render_tag, template_context): + + + +## ... source file continues with no further activate examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-deactivate-all.markdown b/content/pages/examples/django/django-utils-translation-deactivate-all.markdown new file mode 100644 index 000000000..6f61206bf --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-deactivate-all.markdown @@ -0,0 +1,223 @@ +title: django.utils.translation deactivate_all Example Code +category: page +slug: django-utils-translation-deactivate-all-examples +sortorder: 500011500 +toc: False +sidebartitle: django.utils.translation deactivate_all +meta: Python example code for the deactivate_all callable from the django.utils.translation module of the Django project. + + +deactivate_all is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_pool.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_pool.py) + +```python +# plugin_pool.py +from operator import attrgetter + +from django.core.exceptions import ImproperlyConfigured +from django.conf.urls import url, include +from django.template.defaultfilters import slugify +from django.utils.encoding import force_text +from django.utils.functional import cached_property +from django.utils.module_loading import autodiscover_modules +~~from django.utils.translation import get_language, deactivate_all, activate +from django.template import TemplateDoesNotExist, TemplateSyntaxError + +from six import string_types, text_type + +from cms.exceptions import PluginAlreadyRegistered, PluginNotRegistered +from cms.plugin_base import CMSPluginBase +from cms.utils.conf import get_cms_setting +from cms.utils.helpers import normalize_name + + +class PluginPool(object): + + def __init__(self): + self.plugins = {} + self.discovered = False + + def _clear_cached(self): + if 'registered_plugins' in self.__dict__: + del self.__dict__['registered_plugins'] + + if 'plugins_with_extra_menu' in self.__dict__: + del self.__dict__['plugins_with_extra_menu'] + + if 'plugins_with_extra_placeholder_menu' in self.__dict__: + + +## ... source file abbreviated to get to deactivate_all examples ... + + + if allowed_plugins: + plugins = (plugin for plugin in plugins if plugin.__name__ in allowed_plugins) + + if excluded_plugins: + plugins = (plugin for plugin in plugins if plugin.__name__ not in excluded_plugins) + + if placeholder: + plugins = (plugin for plugin in plugins + if not plugin.requires_parent_plugin(placeholder, page)) + return sorted(plugins, key=attrgetter('module')) + + def get_text_enabled_plugins(self, placeholder, page): + plugins = set(self.get_all_plugins(placeholder, page)) + plugins.update(self.get_all_plugins(placeholder, page, 'text_only_plugins')) + return sorted((p for p in plugins if p.text_enabled), + key=attrgetter('module', 'name')) + + def get_plugin(self, name): + self.discover_plugins() + return self.plugins[name] + + def get_patterns(self): + self.discover_plugins() + + lang = get_language() +~~ deactivate_all() + + try: + url_patterns = [] + for plugin in self.registered_plugins: + p = plugin() + slug = slugify(force_text(normalize_name(p.__class__.__name__))) + url_patterns += [ + url(r'^plugin/%s/' % (slug,), include(p.plugin_urls)), + ] + finally: + activate(lang) + + return url_patterns + + def get_system_plugins(self): + self.discover_plugins() + return [plugin.__name__ for plugin in self.plugins.values() if plugin.system] + + @cached_property + def registered_plugins(self): + return self.get_all_plugins() + + @cached_property + def plugins_with_extra_menu(self): + + +## ... source file continues with no further deactivate_all examples... + +``` + + +## Example 2 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / tests / test_templatetags.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/tests/test_templatetags.py) + +```python +# test_templatetags.py +import pytest +from django.template.base import TemplateSyntaxError +~~from django.utils.translation import activate, deactivate_all + +from sitetree.exceptions import SiteTreeError +from sitetree.settings import ALIAS_THIS_ANCESTOR_CHILDREN, ALIAS_THIS_CHILDREN, ALIAS_THIS_PARENT_SIBLINGS, \ + ALIAS_THIS_SIBLINGS, ALIAS_TRUNK + + +def test_items_hook(template_render_tag, template_context, common_tree): + + from sitetree.toolbox import register_items_hook + + with pytest.raises(SiteTreeError): + register_items_hook(lambda: []) + + def my_processor(tree_items, tree_sender): + for item in tree_items: + item.hint = f'hooked_hint_{item.title}' + return tree_items + + register_items_hook(my_processor) + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', template_context()) + + assert 'hooked_hint_Darwin' in result + assert 'hooked_hint_Australia' in result + assert 'hooked_hint_China' in result + + +## ... source file abbreviated to get to deactivate_all examples ... + + + + activate('en') + result = template_render_tag('sitetree', 'sitetree_tree from "i18tree"', template_context()) + + assert '/url_default/' in result + assert 'My title' in result + + activate('ru') + result = template_render_tag('sitetree', 'sitetree_tree from "i18tree"', template_context()) + + assert '/url_ru/' in result + assert 'Заголовок' in result + + activate('pt-br') + result = template_render_tag('sitetree', 'sitetree_tree from "i18tree"', template_context()) + + assert '/url_pt-br/' in result + assert 'Meu Título' in result + + activate('zh-hans') + result = template_render_tag('sitetree', 'sitetree_tree from "i18tree"', template_context()) + + assert '/url_zh-hans/' in result + assert '我蒂特' in result + +~~ deactivate_all() + + +def test_restricted(user_create, template_render_tag, template_context, common_tree): + context = template_context() + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', context) + + assert '"/contacts/australia/darwin/"' in result + assert '"/contacts/australia/alice/"' not in result + + context = template_context(user=user_create()) + result = template_render_tag('sitetree', 'sitetree_tree from "mytree"', context) + + assert '"/contacts/australia/darwin/"' not in result + assert '"/contacts/australia/alice/"' in result + + +def test_permissions(user_create, build_tree, template_render_tag, template_context): + + from sitetree.models import TreeItem + + build_tree( + {'alias': 'restricted_tree'}, + [ + {'title': 'Minjilang', 'access_restricted': True, 'url': '/contacts/australia/minjilang/'}, + + +## ... source file continues with no further deactivate_all examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-get-language-from-request.markdown b/content/pages/examples/django/django-utils-translation-get-language-from-request.markdown new file mode 100644 index 000000000..103efee74 --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-get-language-from-request.markdown @@ -0,0 +1,204 @@ +title: django.utils.translation get_language_from_request Example Code +category: page +slug: django-utils-translation-get-language-from-request-examples +sortorder: 500011502 +toc: False +sidebartitle: django.utils.translation get_language_from_request +meta: Python example code for the get_language_from_request callable from the django.utils.translation module of the Django project. + + +get_language_from_request is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / templatetags / djng_tags.py**](https://github.com/jrief/django-angular/blob/master/djng/templatetags/djng_tags.py) + +```python +# djng_tags.py +import json + +from django.template import Library +from django.template.base import Node, NodeList, TextNode, VariableNode +from django.utils.html import format_html +from django.utils.safestring import mark_safe +~~from django.utils.translation import get_language_from_request + +from djng.core.urlresolvers import get_all_remote_methods, get_current_remote_methods + + +register = Library() + + +@register.simple_tag(name='djng_all_rmi') +def djng_all_rmi(): + return mark_safe(json.dumps(get_all_remote_methods())) + + +@register.simple_tag(name='djng_current_rmi', takes_context=True) +def djng_current_rmi(context): + return mark_safe(json.dumps(get_current_remote_methods(context.get('view')))) + + +@register.simple_tag(name='load_djng_urls', takes_context=True) +def djng_urls(context, *namespaces): + raise DeprecationWarning( + "load_djng_urls templatetag is deprecated and has been removed from this version of django-angular." + "Please refer to documentation for updated way to manage django urls in angular.") + + + + +## ... source file abbreviated to get to get_language_from_request examples ... + + +@register.tag +def angularjs(parser, token): + bits = token.contents.split() + if len(bits) < 2: + bits.append('1') + values = [parser.compile_filter(bit) for bit in bits[1:]] + django_nodelist = parser.parse(('endangularjs',)) + angular_nodelist = NodeList() + for node in django_nodelist: + if isinstance(node, VariableNode): + tokens = node.filter_expression.token.split('.') + token = tokens[0] + for part in tokens[1:]: + if part.isdigit(): + token += '[%s]' % part + else: + token += '.%s' % part + node = TextNode('{{ %s }}' % token) + angular_nodelist.append(node) + parser.delete_first_token() + return AngularJsNode(django_nodelist, angular_nodelist, values[0]) + + +@register.simple_tag(name='djng_locale_script', takes_context=True) +def djng_locale_script(context, default_language='en'): +~~ language = get_language_from_request(context['request']) + if not language: + language = default_language + return format_html('angular-locale_{}.js', language.lower()) + + + +## ... source file continues with no further get_language_from_request examples... + +``` + + +## Example 2 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / views.py**](https://github.com/divio/django-cms/blob/develop/cms/./views.py) + +```python +# views.py + +from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login +from django.contrib.auth.views import redirect_to_login +from django.http import HttpResponse, HttpResponseRedirect +from django.urls import reverse +from django.utils.cache import patch_cache_control +from django.utils.http import is_safe_url, urlquote +from django.utils.timezone import now +~~from django.utils.translation import get_language_from_request +from django.views.decorators.http import require_POST + +from cms.cache.page import get_page_cache +from cms.exceptions import LanguageError +from cms.forms.login import CMSToolbarLoginForm +from cms.models.pagemodel import TreeNode +from cms.page_rendering import _handle_no_page, render_page, render_object_structure, _render_welcome_page +from cms.toolbar.utils import get_toolbar_from_request +from cms.utils import get_current_site +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import (get_fallback_languages, get_public_languages, + get_redirect_on_fallback, get_language_list, + get_default_language_for_site, + is_language_prefix_patterns_used) +from cms.utils.page import get_page_from_request +from cms.utils.page_permissions import user_can_change_page + + +def _clean_redirect_url(redirect_url, language): + if (redirect_url and is_language_prefix_patterns_used() and redirect_url[0] == "/" + and not redirect_url.startswith('/%s/' % language)): + redirect_url = "/%s/%s" % (language, redirect_url.lstrip("/")) + return redirect_url + + + +## ... source file abbreviated to get to get_language_from_request examples ... + + + response.xframe_options_exempt = True + response._headers = headers + max_age = int( + (expires_datetime - response_timestamp).total_seconds() + 0.5) + patch_cache_control(response, max_age=max_age) + return response + + site = get_current_site() + page = get_page_from_request(request, use_path=slug) + toolbar = get_toolbar_from_request(request) + tree_nodes = TreeNode.objects.get_for_site(site) + + if not page and not slug and not tree_nodes.exists(): + return _render_welcome_page(request) + + if not page: + _handle_no_page(request) + + request.current_page = page + + if hasattr(request, 'user') and request.user.is_staff: + user_languages = get_language_list(site_id=site.pk) + else: + user_languages = get_public_languages(site_id=site.pk) + +~~ request_language = get_language_from_request(request, check_path=True) + + if not page.is_home and request_language not in user_languages: + return _handle_no_page(request) + + available_languages = [ + language for language in user_languages + if language in list(page.get_published_languages()) + ] + + own_urls = [ + request.build_absolute_uri(request.path), + '/%s' % request.path, + request.path, + ] + + try: + redirect_on_fallback = get_redirect_on_fallback(request_language, site_id=site.pk) + except LanguageError: + redirect_on_fallback = False + + if request_language not in user_languages: + default_language = get_default_language_for_site(site.pk) + fallbacks = get_fallback_languages(default_language, site_id=site.pk) + fallbacks = [default_language] + fallbacks + + +## ... source file continues with no further get_language_from_request examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-get-language.markdown b/content/pages/examples/django/django-utils-translation-get-language.markdown new file mode 100644 index 000000000..1bf9ec1bc --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-get-language.markdown @@ -0,0 +1,329 @@ +title: django.utils.translation get_language Example Code +category: page +slug: django-utils-translation-get-language-examples +sortorder: 500011501 +toc: False +sidebartitle: django.utils.translation get_language +meta: Python example code for the get_language callable from the django.utils.translation module of the Django project. + + +get_language is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_pool.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_pool.py) + +```python +# plugin_pool.py +from operator import attrgetter + +from django.core.exceptions import ImproperlyConfigured +from django.conf.urls import url, include +from django.template.defaultfilters import slugify +from django.utils.encoding import force_text +from django.utils.functional import cached_property +from django.utils.module_loading import autodiscover_modules +~~from django.utils.translation import get_language, deactivate_all, activate +from django.template import TemplateDoesNotExist, TemplateSyntaxError + +from six import string_types, text_type + +from cms.exceptions import PluginAlreadyRegistered, PluginNotRegistered +from cms.plugin_base import CMSPluginBase +from cms.utils.conf import get_cms_setting +from cms.utils.helpers import normalize_name + + +class PluginPool(object): + + def __init__(self): + self.plugins = {} + self.discovered = False + + def _clear_cached(self): + if 'registered_plugins' in self.__dict__: + del self.__dict__['registered_plugins'] + + if 'plugins_with_extra_menu' in self.__dict__: + del self.__dict__['plugins_with_extra_menu'] + + if 'plugins_with_extra_placeholder_menu' in self.__dict__: + + +## ... source file abbreviated to get to get_language examples ... + + + + if allowed_plugins: + plugins = (plugin for plugin in plugins if plugin.__name__ in allowed_plugins) + + if excluded_plugins: + plugins = (plugin for plugin in plugins if plugin.__name__ not in excluded_plugins) + + if placeholder: + plugins = (plugin for plugin in plugins + if not plugin.requires_parent_plugin(placeholder, page)) + return sorted(plugins, key=attrgetter('module')) + + def get_text_enabled_plugins(self, placeholder, page): + plugins = set(self.get_all_plugins(placeholder, page)) + plugins.update(self.get_all_plugins(placeholder, page, 'text_only_plugins')) + return sorted((p for p in plugins if p.text_enabled), + key=attrgetter('module', 'name')) + + def get_plugin(self, name): + self.discover_plugins() + return self.plugins[name] + + def get_patterns(self): + self.discover_plugins() + +~~ lang = get_language() + deactivate_all() + + try: + url_patterns = [] + for plugin in self.registered_plugins: + p = plugin() + slug = slugify(force_text(normalize_name(p.__class__.__name__))) + url_patterns += [ + url(r'^plugin/%s/' % (slug,), include(p.plugin_urls)), + ] + finally: + activate(lang) + + return url_patterns + + def get_system_plugins(self): + self.discover_plugins() + return [plugin.__name__ for plugin in self.plugins.values() if plugin.system] + + @cached_property + def registered_plugins(self): + return self.get_all_plugins() + + @cached_property + + +## ... source file continues with no further get_language examples... + +``` + + +## Example 2 from django-sitetree +[django-sitetree](https://github.com/idlesign/django-sitetree) +([project documentation](https://django-sitetree.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-sitetree/)) +is a [Django](/django.html) extension that makes it easier for +developers to add site trees, menus and breadcrumb navigation elements +to their web applications. + +The django-sitetree project is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/idlesign/django-sitetree/blob/master/LICENSE). + +[**django-sitetree / sitetree / sitetreeapp.py**](https://github.com/idlesign/django-sitetree/blob/master/sitetree/./sitetreeapp.py) + +```python +# sitetreeapp.py +import warnings +from collections import defaultdict +from copy import deepcopy +from inspect import getfullargspec +from sys import exc_info +from threading import local +from typing import Callable, List, Optional, Dict, Union, Sequence, Any, Tuple + +from django.conf import settings +from django.core.cache import cache +from django.db.models import signals, QuerySet +from django.template.base import ( + FilterExpression, Lexer, Parser, Token, Variable, VariableDoesNotExist, VARIABLE_TAG_START, Context) +from django.template.defaulttags import url as url_tag +from django.template.loader import get_template +from django.utils import module_loading +from django.utils.http import urlquote +~~from django.utils.translation import get_language + +from .compat import TOKEN_BLOCK, TOKEN_TEXT, TOKEN_VAR +from .exceptions import SiteTreeError +from .settings import ( + ALIAS_TRUNK, ALIAS_THIS_CHILDREN, ALIAS_THIS_SIBLINGS, ALIAS_THIS_PARENT_SIBLINGS, ALIAS_THIS_ANCESTOR_CHILDREN, + UNRESOLVED_ITEM_MARKER, RAISE_ITEMS_ERRORS_ON_DEBUG, CACHE_TIMEOUT, DYNAMIC_ONLY, ADMIN_APP_NAME, SITETREE_CLS) +from .utils import get_tree_model, get_tree_item_model, import_app_sitetree_module, generate_id_for + +if False: # pragma: nocover + from django.contrib.auth.models import User # noqa + from .models import TreeItemBase, TreeBase + +TypeDynamicTrees = Dict[str, Union[Dict[str, List['TreeBase']], List['TreeBase']]] + +MODEL_TREE_CLASS = get_tree_model() +MODEL_TREE_ITEM_CLASS = get_tree_item_model() + + +_ITEMS_PROCESSOR: Optional[Callable] = None + +_ITEMS_PROCESSOR_ARGS_LEN: int = 0 + +_I18N_TREES: List[str] = [] + + + +## ... source file abbreviated to get to get_language examples ... + + + + def get_entry(self, entry_name: str, key) -> Any: + return self.cache[entry_name].get(key, False) + + def update_entry_value(self, entry_name: str, key: str, value: Any): + if key not in self.cache[entry_name]: + self.cache[entry_name][key] = {} + + self.cache[entry_name][key].update(value) + + def set_entry(self, entry_name: str, key: str, value: Any): + self.cache[entry_name][key] = value + + +class SiteTree: + + cache_cls = Cache # Allow customizations. + + def __init__(self): + self.init(context=None) + + def init(self, context: Optional[Context]): + self.cache = self.cache_cls() + self.current_page_context = context + self.current_request = context.get('request', None) if context else None +~~ self.current_lang = get_language() + + self._current_app_is_admin = None + self._current_user_permissions = _UNSET + self._items_urls = {} # Resolved urls are cache for a request. + self._current_items = {} + + def resolve_tree_i18n_alias(self, alias: str) -> str: + if alias not in _I18N_TREES: + return alias + + current_language_code = self.current_lang + i18n_tree_alias = f'{alias}_{current_language_code}' + trees_count = self.cache.get_entry('tree_aliases', i18n_tree_alias) + + if trees_count is False: + trees_count = MODEL_TREE_CLASS.objects.filter(alias=i18n_tree_alias).count() + self.cache.set_entry('tree_aliases', i18n_tree_alias, trees_count) + + if trees_count: + alias = i18n_tree_alias + + return alias + + @staticmethod + + +## ... source file continues with no further get_language examples... + +``` + + +## Example 3 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / users / models.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/users/models.py) + +```python +# models.py +import os +import uuid + +from django.conf import settings +from django.db import models +from django.utils.translation import gettext_lazy as _ +~~from django.utils.translation import get_language + + +def upload_avatar_to(instance, filename): + filename, ext = os.path.splitext(filename) + return os.path.join( + 'avatar_images', + 'avatar_{uuid}_{filename}{ext}'.format( + uuid=uuid.uuid4(), filename=filename, ext=ext) + ) + + +class UserProfile(models.Model): + user = models.OneToOneField( + settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='wagtail_userprofile' + ) + + submitted_notifications = models.BooleanField( + verbose_name=_('submitted notifications'), + default=True, + help_text=_("Receive notification when a page is submitted for moderation") + ) + + approved_notifications = models.BooleanField( + verbose_name=_('approved notifications'), + + +## ... source file abbreviated to get to get_language examples ... + + + preferred_language = models.CharField( + verbose_name=_('preferred language'), + max_length=10, + help_text=_("Select language for the admin"), + default='' + ) + + current_time_zone = models.CharField( + verbose_name=_('current time zone'), + max_length=40, + help_text=_("Select your current time zone"), + default='' + ) + + avatar = models.ImageField( + verbose_name=_('profile picture'), + upload_to=upload_avatar_to, + blank=True, + ) + + @classmethod + def get_for_user(cls, user): + return cls.objects.get_or_create(user=user)[0] + + def get_preferred_language(self): +~~ return self.preferred_language or get_language() + + def get_current_time_zone(self): + return self.current_time_zone or settings.TIME_ZONE + + def __str__(self): + return self.user.get_username() + + class Meta: + verbose_name = _('user profile') + verbose_name_plural = _('user profiles') + + + +## ... source file continues with no further get_language examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-gettext-lazy.markdown b/content/pages/examples/django/django-utils-translation-gettext-lazy.markdown new file mode 100644 index 000000000..c709f84b4 --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-gettext-lazy.markdown @@ -0,0 +1,50 @@ +title: django.utils.translation gettext_lazy Example Code +category: page +slug: django-utils-translation-gettext-lazy-examples +sortorder: 500011504 +toc: False +sidebartitle: django.utils.translation gettext_lazy +meta: Python example code for the gettext_lazy callable from the django.utils.translation module of the Django project. + + +gettext_lazy is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / core / forms.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/core/forms.py) + +```python +# forms.py +from django import forms +from django.utils.crypto import constant_time_compare +from django.utils.translation import gettext as _ +~~from django.utils.translation import gettext_lazy + + +class PasswordViewRestrictionForm(forms.Form): +~~ password = forms.CharField(label=gettext_lazy("Password"), widget=forms.PasswordInput) + return_url = forms.CharField(widget=forms.HiddenInput) + + def __init__(self, *args, **kwargs): + self.restriction = kwargs.pop('instance') + super().__init__(*args, **kwargs) + + def clean_password(self): + data = self.cleaned_data['password'] + if not constant_time_compare(data, self.restriction.password): + raise forms.ValidationError(_("The password you have entered is not correct. Please try again.")) + + return data + + + +## ... source file continues with no further gettext_lazy examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-gettext.markdown b/content/pages/examples/django/django-utils-translation-gettext.markdown new file mode 100644 index 000000000..66705feae --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-gettext.markdown @@ -0,0 +1,791 @@ +title: django.utils.translation gettext Example Code +category: page +slug: django-utils-translation-gettext-examples +sortorder: 500011503 +toc: False +sidebartitle: django.utils.translation gettext +meta: Python example code for the gettext callable from the django.utils.translation module of the Django project. + + +gettext is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / forms.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/forms.py) + +```python +# forms.py +from __future__ import absolute_import + +import warnings +from importlib import import_module + +from django import forms +from django.contrib.auth.tokens import PasswordResetTokenGenerator +from django.contrib.sites.shortcuts import get_current_site +from django.core import exceptions, validators +from django.urls import reverse +~~from django.utils.translation import gettext, gettext_lazy as _, pgettext + +from ..utils import ( + build_absolute_uri, + get_username_max_length, + set_form_field_order, +) +from . import app_settings +from .adapter import get_adapter +from .app_settings import AuthenticationMethod +from .models import EmailAddress +from .utils import ( + filter_users_by_email, + get_user_model, + perform_login, + setup_user_email, + sync_user_email_addresses, + url_str_to_user_pk, + user_email, + user_pk_to_url_str, + user_username, +) + + +class EmailAwarePasswordResetTokenGenerator(PasswordResetTokenGenerator): + + +## ... source file abbreviated to get to gettext examples ... + + + username_field = self.fields['username'] + username_field.max_length = get_username_max_length() + username_field.validators.append( + validators.MaxLengthValidator(username_field.max_length)) + username_field.widget.attrs['maxlength'] = str( + username_field.max_length) + + default_field_order = [ + 'email', + 'email2', # ignored when not present + 'username', + 'password1', + 'password2' # ignored when not present + ] + if app_settings.SIGNUP_EMAIL_ENTER_TWICE: + self.fields["email2"] = forms.EmailField( + label=_("E-mail (again)"), + widget=forms.TextInput( + attrs={ + 'type': 'email', + 'placeholder': _('E-mail address confirmation') + } + ) + ) + if email_required: +~~ self.fields['email'].label = gettext("E-mail") + self.fields['email'].required = True + else: +~~ self.fields['email'].label = gettext("E-mail (optional)") + self.fields['email'].required = False + self.fields['email'].widget.is_required = False + if self.username_required: + default_field_order = [ + 'username', + 'email', + 'email2', # ignored when not present + 'password1', + 'password2' # ignored when not present + ] + + if not self.username_required: + del self.fields["username"] + + set_form_field_order( + self, + getattr(self, 'field_order', None) or default_field_order) + + def clean_username(self): + value = self.cleaned_data["username"] + value = get_adapter().clean_username(value) + return value + + def clean_email(self): + + +## ... source file continues with no further gettext examples... + +``` + + +## Example 2 from django-guardian +[django-guardian](https://github.com/django-guardian/django-guardian) +([project documentation](https://django-guardian.readthedocs.io/en/stable/) +and +[PyPI page](https://pypi.org/project/django-guardian/)) +provides per-object permissions in [Django](/django.html) projects +by enhancing the existing authentication backend. The project's code +is open source under the +[MIT license](https://github.com/django-guardian/django-guardian/blob/devel/LICENSE). + +[**django-guardian / guardian / admin.py**](https://github.com/django-guardian/django-guardian/blob/devel/guardian/./admin.py) + +```python +# admin.py +from collections import OrderedDict + +from django import forms +from django.conf import settings +from django.contrib import admin, messages +from django.contrib.admin.widgets import FilteredSelectMultiple +from django.contrib.auth import get_user_model +from django.shortcuts import get_object_or_404, redirect, render +from django.urls import reverse, path +~~from django.utils.translation import gettext_lazy as _ +~~from django.utils.translation import gettext +from guardian.forms import GroupObjectPermissionsForm, UserObjectPermissionsForm +from django.contrib.auth.models import Group +from guardian.shortcuts import (get_group_perms, get_groups_with_perms, get_perms_for_model, get_user_perms, + get_users_with_perms) + + +class AdminUserObjectPermissionsForm(UserObjectPermissionsForm): + + def get_obj_perms_field_widget(self): + return FilteredSelectMultiple(_("Permissions"), False) + + +class AdminGroupObjectPermissionsForm(GroupObjectPermissionsForm): + + def get_obj_perms_field_widget(self): + return FilteredSelectMultiple(_("Permissions"), False) + + +class GuardedModelAdminMixin: + change_form_template = \ + 'admin/guardian/model/change_form.html' + obj_perms_manage_template = \ + 'admin/guardian/model/obj_perms_manage.html' + obj_perms_manage_user_template = \ + + +## ... source file abbreviated to get to gettext examples ... + + + context['groups_perms'] = groups_perms + context['user_form'] = user_form + context['group_form'] = group_form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_template(), context) + + def get_obj_perms_manage_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage.html' + return self.obj_perms_manage_template + + def obj_perms_manage_user_view(self, request, object_pk, user_id): + if not self.has_change_permission(request, None): + post_url = reverse('admin:index', current_app=self.admin_site.name) + return redirect(post_url) + + user = get_object_or_404(get_user_model(), pk=user_id) + obj = get_object_or_404(self.get_queryset(request), pk=object_pk) + form_class = self.get_obj_perms_manage_user_form(request) + form = form_class(user, obj, request.POST or None) + + if request.method == 'POST' and form.is_valid(): + form.save_obj_perms() +~~ msg = gettext("Permissions saved.") + messages.success(request, msg) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + url = reverse( + '%s:%s_%s_permissions_manage_user' % info, + args=[obj.pk, user.pk] + ) + return redirect(url) + + context = self.get_obj_perms_base_context(request, obj) + context['user_obj'] = user + context['user_perms'] = get_user_perms(user, obj) + context['form'] = form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_user_template(), context) + + def get_obj_perms_manage_user_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage_user.html' + return self.obj_perms_manage_user_template + + def get_obj_perms_user_select_form(self, request): + return UserManage + + def get_obj_perms_group_select_form(self, request): + return GroupManage + + def get_obj_perms_manage_user_form(self, request): + return AdminUserObjectPermissionsForm + + def obj_perms_manage_group_view(self, request, object_pk, group_id): + if not self.has_change_permission(request, None): + post_url = reverse('admin:index', current_app=self.admin_site.name) + return redirect(post_url) + + group = get_object_or_404(Group, id=group_id) + obj = get_object_or_404(self.get_queryset(request), pk=object_pk) + form_class = self.get_obj_perms_manage_group_form(request) + form = form_class(group, obj, request.POST or None) + + if request.method == 'POST' and form.is_valid(): + form.save_obj_perms() +~~ msg = gettext("Permissions saved.") + messages.success(request, msg) + info = ( + self.admin_site.name, + self.model._meta.app_label, + self.model._meta.model_name, + ) + url = reverse( + '%s:%s_%s_permissions_manage_group' % info, + args=[obj.pk, group.id] + ) + return redirect(url) + + context = self.get_obj_perms_base_context(request, obj) + context['group_obj'] = group + context['group_perms'] = get_group_perms(group, obj) + context['form'] = form + + request.current_app = self.admin_site.name + + return render(request, self.get_obj_perms_manage_group_template(), context) + + def get_obj_perms_manage_group_template(self): + if 'grappelli' in settings.INSTALLED_APPS: + return 'admin/guardian/contrib/grappelli/obj_perms_manage_group.html' + + +## ... source file continues with no further gettext examples... + +``` + + +## Example 3 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / models.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./models.py) + +```python +# models.py +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +from django.db import IntegrityError, models, router, transaction +from django.utils.text import slugify +~~from django.utils.translation import gettext, gettext_lazy as _ + +try: + from unidecode import unidecode +except ImportError: + + def unidecode(tag): + return tag + + +class TagBase(models.Model): + name = models.CharField(verbose_name=_("name"), unique=True, max_length=100) + slug = models.SlugField(verbose_name=_("slug"), unique=True, max_length=100) + + def __str__(self): + return self.name + + def __gt__(self, other): + return self.name.lower() > other.name.lower() + + def __lt__(self, other): + return self.name.lower() < other.name.lower() + + class Meta: + abstract = True + + +## ... source file abbreviated to get to gettext examples ... + + + while True: + slug = self.slugify(self.name, i) + if slug not in slugs: + self.slug = slug + return super().save(*args, **kwargs) + i += 1 + else: + return super().save(*args, **kwargs) + + def slugify(self, tag, i=None): + slug = slugify(unidecode(tag)) + if i is not None: + slug += "_%d" % i + return slug + + +class Tag(TagBase): + class Meta: + verbose_name = _("tag") + verbose_name_plural = _("tags") + app_label = "taggit" + + +class ItemBase(models.Model): + def __str__(self): +~~ return gettext("%(object)s tagged with %(tag)s") % { + "object": self.content_object, + "tag": self.tag, + } + + class Meta: + abstract = True + + @classmethod + def tag_model(cls): + field = cls._meta.get_field("tag") + return field.remote_field.model + + @classmethod + def tag_relname(cls): + field = cls._meta.get_field("tag") + return field.remote_field.related_name + + @classmethod + def lookup_kwargs(cls, instance): + return {"content_object": instance} + + @classmethod + def tags_for(cls, model, instance=None, **extra_filters): + kwargs = extra_filters or {} + + +## ... source file continues with no further gettext examples... + +``` + + +## Example 4 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / forms.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./forms.py) + +```python +# forms.py + "SpamProtectionMixin", + "CreateRootForm", + "MoveForm", + "EditForm", + "SelectWidgetBootstrap", + "TextInputPrepend", + "CreateForm", + "DeleteForm", + "PermissionsForm", + "DirFilterForm", + "SearchForm", +] + +from datetime import timedelta + +from django import forms +from django.apps import apps +from django.contrib.auth import get_user_model +from django.core import validators +from django.core.validators import RegexValidator +from django.forms.widgets import HiddenInput +from django.shortcuts import get_object_or_404 +from django.urls import Resolver404, resolve +from django.utils import timezone +from django.utils.safestring import mark_safe +~~from django.utils.translation import gettext, gettext_lazy as _, pgettext_lazy +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.plugins.base import PluginSettingsFormMixin +from wiki.editors import getEditor + +from .forms_account_handling import UserCreationForm, UserUpdateForm + +validate_slug_numbers = RegexValidator( + r"^[0-9]+$", + _("A 'slug' cannot consist solely of numbers."), + "invalid", + inverse_match=True, +) + + +class WikiSlugField(forms.CharField): + + default_validators = [validators.validate_slug, validate_slug_numbers] + + def __init__(self, *args, **kwargs): + self.allow_unicode = kwargs.pop("allow_unicode", False) + if self.allow_unicode: + self.default_validators = [ + validators.validate_unicode_slug, + validate_slug_numbers, + ] + super().__init__(*args, **kwargs) + + +def _clean_slug(slug, urlpath): + if slug.startswith("_"): + raise forms.ValidationError(gettext("A slug may not begin with an underscore.")) + if slug == "admin": + raise forms.ValidationError(gettext("'admin' is not a permitted slug name.")) + + if settings.URL_CASE_SENSITIVE: + already_existing_slug = models.URLPath.objects.filter(slug=slug, parent=urlpath) + else: + slug = slug.lower() + already_existing_slug = models.URLPath.objects.filter( + slug__iexact=slug, parent=urlpath + ) + if already_existing_slug: + already_urlpath = already_existing_slug[0] + if already_urlpath.article and already_urlpath.article.current_revision.deleted: + raise forms.ValidationError( +~~ gettext('A deleted article with slug "%s" already exists.') + % already_urlpath.slug + ) + else: + raise forms.ValidationError( +~~ gettext('A slug named "%s" already exists.') % already_urlpath.slug + ) + + if settings.CHECK_SLUG_URL_AVAILABLE: + try: + match = resolve(urlpath.path + "/" + slug + "/") + if match.app_name != "wiki": + raise forms.ValidationError( +~~ gettext("This slug conflicts with an existing URL.") + ) + except Resolver404: + pass + + return slug + + +User = get_user_model() +Group = apps.get_model(settings.GROUP_MODEL) + + +class SpamProtectionMixin: + + + revision_model = models.ArticleRevision + + def check_spam(self): # noqa + request = self.request + user = None + ip_address = None + if request.user.is_authenticated: + user = request.user + else: + ip_address = request.META.get("REMOTE_ADDR", None) + + if not (user or ip_address): + raise forms.ValidationError( +~~ gettext( + "Spam protection failed to find both a logged in user and an IP address." + ) + ) + + def check_interval(from_time, max_count, interval_name): + from_time = timezone.now() - timedelta( + minutes=settings.REVISIONS_MINUTES_LOOKBACK + ) + revisions = self.revision_model.objects.filter(created__gte=from_time,) + if user: + revisions = revisions.filter(user=user) + if ip_address: + revisions = revisions.filter(ip_address=ip_address) + revisions = revisions.count() + if revisions >= max_count: + raise forms.ValidationError( +~~ gettext( + "Spam protection: You are only allowed to create or edit %(revisions)d article(s) per %(interval_name)s." + ) + % {"revisions": max_count, "interval_name": interval_name} + ) + + if not settings.LOG_IPS_ANONYMOUS: + return + if request.user.has_perm("wiki.moderator"): + return + + from_time = timezone.now() - timedelta( + minutes=settings.REVISIONS_MINUTES_LOOKBACK + ) + if request.user.is_authenticated: + per_minute = settings.REVISIONS_PER_MINUTES + else: + per_minute = settings.REVISIONS_PER_MINUTES_ANONYMOUS + check_interval( + from_time, + per_minute, + _("minute") + if settings.REVISIONS_MINUTES_LOOKBACK == 1 + else (_("%d minutes") % settings.REVISIONS_MINUTES_LOOKBACK), + ) + + +## ... source file abbreviated to get to gettext examples ... + + + if not str(self.presumed_revision) == str(self.initial_revision.id): + newdata = {} + for k, v in data.items(): + newdata[k] = v + newdata["current_revision"] = self.initial_revision.id + if provided_content: + self.presumed_revision = self.initial_revision.id + else: + newdata["content"] = simple_merge( + content, data.get("content", "") + ) + newdata["title"] = current_revision.title + kwargs["data"] = newdata + else: + kwargs["data"] = data + + kwargs["initial"] = initial + + super().__init__(*args, **kwargs) + + def clean_title(self): + title = self.cleaned_data.get("title", None) + title = (title or "").strip() + if not title: + raise forms.ValidationError( +~~ gettext("Article is missing title or has an invalid title") + ) + return title + + def clean(self): + if self.no_clean or self.preview: + return self.cleaned_data + if not str(self.initial_revision.id) == str(self.presumed_revision): + raise forms.ValidationError( +~~ gettext( + "While you were editing, someone else changed the revision. Your contents have been automatically merged with the new contents. Please review the text below." + ) + ) + if ( + "title" in self.cleaned_data + and self.cleaned_data["title"] == self.initial_revision.title + and self.cleaned_data["content"] == self.initial_revision.content + ): + raise forms.ValidationError(gettext("No changes made. Nothing to save.")) + self.check_spam() + return self.cleaned_data + + +class SelectWidgetBootstrap(forms.Select): + + def __init__(self, attrs=None, choices=()): + if attrs is None: + attrs = {"class": ""} + elif "class" not in attrs: + attrs["class"] = "" + attrs["class"] += " form-control" + + super().__init__(attrs, choices) + + + +## ... source file abbreviated to get to gettext examples ... + + + +class DeleteForm(forms.Form): + def __init__(self, *args, **kwargs): + self.article = kwargs.pop("article") + self.has_children = kwargs.pop("has_children") + super().__init__(*args, **kwargs) + + confirm = forms.BooleanField(required=False, label=_("Yes, I am sure")) + purge = forms.BooleanField( + widget=HiddenInput(), + required=False, + label=_("Purge"), + help_text=_( + "Purge the article: Completely remove it (and all its contents) with no undo. Purging is a good idea if you want to free the slug such that users can create new articles in its place." + ), + ) + revision = forms.ModelChoiceField( + models.ArticleRevision.objects.all(), widget=HiddenInput(), required=False + ) + + def clean(self): + if not self.cleaned_data["confirm"]: + raise forms.ValidationError(gettext("You are not sure enough!")) + if self.cleaned_data["revision"] != self.article.current_revision: + raise forms.ValidationError( +~~ gettext( + "While you tried to delete this article, it was modified. TAKE CARE!" + ) + ) + return self.cleaned_data + + +class PermissionsForm(PluginSettingsFormMixin, forms.ModelForm): + + locked = forms.BooleanField( + label=_("Lock article"), + help_text=_("Deny all users access to edit this article."), + required=False, + ) + + settings_form_headline = _("Permissions") + settings_order = 5 + settings_write_access = False + + owner_username = forms.CharField( + required=False, + label=_("Owner"), + help_text=_("Enter the username of the owner."), + ) + group = forms.ModelChoiceField( + + +## ... source file continues with no further gettext examples... + +``` + + +## Example 5 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / images / wagtail_hooks.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/images/wagtail_hooks.py) + +```python +# wagtail_hooks.py +from django.conf.urls import include, url +from django.urls import reverse +from django.utils.html import format_html +~~from django.utils.translation import gettext_lazy as _ +~~from django.utils.translation import gettext, ngettext + +import wagtail.admin.rich_text.editors.draftail.features as draftail_features +from wagtail.admin.menu import MenuItem +from wagtail.admin.navigation import get_site_for_user +from wagtail.admin.rich_text import HalloPlugin +from wagtail.admin.search import SearchArea +from wagtail.admin.site_summary import SummaryItem +from wagtail.core import hooks +from wagtail.images import admin_urls, get_image_model, image_operations +from wagtail.images.api.admin.views import ImagesAdminAPIViewSet +from wagtail.images.forms import GroupImagePermissionFormSet +from wagtail.images.permissions import permission_policy +from wagtail.images.rich_text import ImageEmbedHandler +from wagtail.images.rich_text.contentstate import ContentstateImageConversionRule +from wagtail.images.rich_text.editor_html import EditorHTMLImageConversionRule + + +@hooks.register('register_admin_urls') +def register_admin_urls(): + return [ + url(r'^images/', include(admin_urls, namespace='wagtailimages')), + ] + + + + +## ... source file abbreviated to get to gettext examples ... + + + reverse('wagtailimages:chooser') + ) + + +@hooks.register('register_rich_text_features') +def register_image_feature(features): + features.register_embed_type(ImageEmbedHandler) + + features.register_editor_plugin( + 'hallo', 'image', + HalloPlugin( + name='hallowagtailimage', + js=[ + 'wagtailimages/js/image-chooser-modal.js', + 'wagtailimages/js/hallo-plugins/hallo-wagtailimage.js', + ], + ) + ) + + features.register_converter_rule('editorhtml', 'image', EditorHTMLImageConversionRule) + + features.register_editor_plugin( + 'draftail', 'image', draftail_features.EntityFeature({ + 'type': 'IMAGE', + 'icon': 'image', +~~ 'description': gettext('Image'), + 'attributes': ['id', 'src', 'alt', 'format'], + 'whitelist': { + 'id': True, + } + }, js=[ + 'wagtailimages/js/image-chooser-modal.js', + ]) + ) + + features.register_converter_rule('contentstate', 'image', ContentstateImageConversionRule) + + features.default_features.append('image') + + +@hooks.register('register_image_operations') +def register_image_operations(): + return [ + ('original', image_operations.DoNothingOperation), + ('fill', image_operations.FillOperation), + ('min', image_operations.MinMaxOperation), + ('max', image_operations.MinMaxOperation), + ('width', image_operations.WidthHeightOperation), + ('height', image_operations.WidthHeightOperation), + ('scale', image_operations.ScaleOperation), + + +## ... source file continues with no further gettext examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-language-session-key.markdown b/content/pages/examples/django/django-utils-translation-language-session-key.markdown new file mode 100644 index 000000000..12610c6a9 --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-language-session-key.markdown @@ -0,0 +1,55 @@ +title: django.utils.translation LANGUAGE_SESSION_KEY Example Code +category: page +slug: django-utils-translation-language-session-key-examples +sortorder: 500011498 +toc: False +sidebartitle: django.utils.translation LANGUAGE_SESSION_KEY +meta: Python example code for the LANGUAGE_SESSION_KEY constant from the django.utils.translation module of the Django project. + + +LANGUAGE_SESSION_KEY is a constant within the django.utils.translation module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / middleware / language.py**](https://github.com/divio/django-cms/blob/develop/cms/middleware/language.py) + +```python +# language.py +import datetime + +~~from django.utils.translation import LANGUAGE_SESSION_KEY, get_language +from django.conf import settings + +from cms.utils.compat import DJANGO_2_2 +from cms.utils.compat.dj import MiddlewareMixin + + +class LanguageCookieMiddleware(MiddlewareMixin): + def process_response(self, request, response): + language = get_language() + if hasattr(request, 'session') and DJANGO_2_2: +~~ session_language = request.session.get(LANGUAGE_SESSION_KEY, None) + if session_language and not session_language == language: + request.session[LANGUAGE_SESSION_KEY] = language + request.session.save() + if settings.LANGUAGE_COOKIE_NAME in request.COOKIES and \ + request.COOKIES[settings.LANGUAGE_COOKIE_NAME] == language: + return response + max_age = 365 * 24 * 60 * 60 # 10 years + expires = datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age) + response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language, expires=expires) + return response + + + +## ... source file continues with no further LANGUAGE_SESSION_KEY examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-ngettext.markdown b/content/pages/examples/django/django-utils-translation-ngettext.markdown new file mode 100644 index 000000000..7b58498db --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-ngettext.markdown @@ -0,0 +1,218 @@ +title: django.utils.translation ngettext Example Code +category: page +slug: django-utils-translation-ngettext-examples +sortorder: 500011505 +toc: False +sidebartitle: django.utils.translation ngettext +meta: Python example code for the ngettext callable from the django.utils.translation module of the Django project. + + +ngettext is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / article.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/article.py) + +```python +# article.py +import difflib +import logging +from urllib.parse import urljoin + +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.db import transaction +from django.db.models import Q +from django.http import Http404 +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.shortcuts import render +from django.urls import reverse +from django.utils.decorators import method_decorator +from django.utils.translation import gettext as _ +~~from django.utils.translation import ngettext +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.generic import DetailView +from django.views.generic import FormView +from django.views.generic import ListView +from django.views.generic import RedirectView +from django.views.generic import TemplateView +from django.views.generic import View +from wiki import editors +from wiki import forms +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.exceptions import NoRootURL +from wiki.core.paginator import WikiPaginator +from wiki.core.plugins import registry as plugin_registry +from wiki.core.utils import object_to_json_response +from wiki.decorators import get_article +from wiki.views.mixins import ArticleMixin + +log = logging.getLogger(__name__) + + +class ArticleView(ArticleMixin, TemplateView): + + +## ... source file abbreviated to get to ngettext examples ... + + + + for descendant in descendants: + descendant.refresh_from_db() + dst_path = descendant.path + src_path = urljoin(old_path, dst_path[root_len:]) + src_len = len(src_path) + pos = src_path.rfind("/", 0, src_len - 1) + slug = src_path[pos + 1 : src_len - 1] + parent_urlpath = models.URLPath.get_by_path(src_path[0 : max(pos, 0)]) + + link = "[wiki:/{path}](wiki:/{path})".format(path=dst_path) + urlpath_new = models.URLPath._create_urlpath_from_request( + self.request, + self.article, + parent_urlpath, + slug, + _("Moved: {title}").format(title=descendant.article), + _("Article moved to {link}").format(link=link), + _("Created redirect (auto)"), + ) + urlpath_new.moved_to = descendant + urlpath_new.save() + + messages.success( + self.request, +~~ ngettext( + "Article successfully moved! Created {n} redirect.", + "Article successfully moved! Created {n} redirects.", + len(descendants), + ).format(n=len(descendants)), + ) + + else: + messages.success(self.request, _("Article successfully moved!")) + return redirect("wiki:get", path=self.urlpath.path) + + +class Deleted(Delete): + + + template_name = "wiki/deleted.html" + form_class = forms.DeleteForm + + @method_decorator(get_article(can_read=True, deleted_contents=True)) + def dispatch(self, request, article, *args, **kwargs): + + self.urlpath = kwargs.get("urlpath", None) + self.article = article + + if self.urlpath: + + +## ... source file continues with no further ngettext examples... + +``` + + +## Example 2 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / images / wagtail_hooks.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/images/wagtail_hooks.py) + +```python +# wagtail_hooks.py +from django.conf.urls import include, url +from django.urls import reverse +from django.utils.html import format_html +from django.utils.translation import gettext_lazy as _ +~~from django.utils.translation import gettext, ngettext + +import wagtail.admin.rich_text.editors.draftail.features as draftail_features +from wagtail.admin.menu import MenuItem +from wagtail.admin.navigation import get_site_for_user +from wagtail.admin.rich_text import HalloPlugin +from wagtail.admin.search import SearchArea +from wagtail.admin.site_summary import SummaryItem +from wagtail.core import hooks +from wagtail.images import admin_urls, get_image_model, image_operations +from wagtail.images.api.admin.views import ImagesAdminAPIViewSet +from wagtail.images.forms import GroupImagePermissionFormSet +from wagtail.images.permissions import permission_policy +from wagtail.images.rich_text import ImageEmbedHandler +from wagtail.images.rich_text.contentstate import ContentstateImageConversionRule +from wagtail.images.rich_text.editor_html import EditorHTMLImageConversionRule + + +@hooks.register('register_admin_urls') +def register_admin_urls(): + return [ + url(r'^images/', include(admin_urls, namespace='wagtailimages')), + ] + + + + +## ... source file abbreviated to get to ngettext examples ... + + + request.user, ['add', 'change', 'delete'] + ) + + +@hooks.register('register_admin_search_area') +def register_images_search_area(): + return ImagesSearchArea( + _('Images'), reverse('wagtailimages:index'), + name='images', + classnames='icon icon-image', + order=200) + + +@hooks.register('register_group_permission_panel') +def register_image_permissions_panel(): + return GroupImagePermissionFormSet + + +@hooks.register('describe_collection_contents') +def describe_collection_docs(collection): + images_count = get_image_model().objects.filter(collection=collection).count() + if images_count: + url = reverse('wagtailimages:index') + ('?collection_id=%d' % collection.id) + return { + 'count': images_count, +~~ 'count_text': ngettext( + "%(count)s image", + "%(count)s images", + images_count + ) % {'count': images_count}, + 'url': url, + } + + + +## ... source file continues with no further ngettext examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-override.markdown b/content/pages/examples/django/django-utils-translation-override.markdown new file mode 100644 index 000000000..677e62844 --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-override.markdown @@ -0,0 +1,210 @@ +title: django.utils.translation override Example Code +category: page +slug: django-utils-translation-override-examples +sortorder: 500011506 +toc: False +sidebartitle: django.utils.translation override +meta: Python example code for the override callable from the django.utils.translation module of the Django project. + + +override is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / appresolver.py**](https://github.com/divio/django-cms/blob/develop/cms/./appresolver.py) + +```python +# appresolver.py +from collections import OrderedDict +from importlib import import_module + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db import OperationalError, ProgrammingError +~~from django.utils.translation import get_language, override +from django.urls import Resolver404, reverse + +from six import string_types + +from cms.apphook_pool import apphook_pool +from cms.models.pagemodel import Page +from cms.utils import get_current_site +from cms.utils.compat import DJANGO_1_11 +from cms.utils.compat.dj import RegexPattern, URLPattern, URLResolver +from cms.utils.i18n import get_language_list +from cms.utils.moderator import use_draft + + +APP_RESOLVERS = [] + + +def clear_app_resolvers(): + global APP_RESOLVERS + APP_RESOLVERS = [] + + +def applications_page_check(request, current_page=None, path=None): + if current_page: + return current_page + + +## ... source file abbreviated to get to override examples ... + + + from cms.models import Title + + included = [] + + title_qs = Title.objects.public().filter(page__node__site=site) + + hooked_applications = OrderedDict() + + titles = (title_qs.exclude(page__application_urls=None) + .exclude(page__application_urls='') + .order_by('-page__node__path').select_related()) + for title in titles: + path = title.path + mix_id = "%s:%s:%s" % ( + path + "/", title.page.application_urls, title.language) + if mix_id in included: + continue + if not settings.APPEND_SLASH: + path += '/' + app = apphook_pool.get_apphook(title.page.application_urls) + if not app: + continue + if title.page_id not in hooked_applications: + hooked_applications[title.page_id] = {} + app_ns = app.app_name, title.page.application_namespace +~~ with override(title.language): + hooked_applications[title.page_id][title.language] = ( + app_ns, get_patterns_for_title(path, title), app) + included.append(mix_id) + app_patterns = [] + for page_id in hooked_applications.keys(): + resolver = None + for lang in hooked_applications[page_id].keys(): + (app_ns, inst_ns), current_patterns, app = hooked_applications[page_id][lang] # nopyflakes + if not resolver: + regex_pattern = RegexPattern(r'') if not DJANGO_1_11 else r'' + resolver = AppRegexURLResolver( + regex_pattern, 'app_resolver', app_name=app_ns, namespace=inst_ns) + resolver.page_id = page_id + if app.permissions: + _set_permissions(current_patterns, app.exclude_permissions) + + resolver.url_patterns_dict[lang] = current_patterns + app_patterns.append(resolver) + APP_RESOLVERS.append(resolver) + return app_patterns + + + +## ... source file continues with no further override examples... + +``` + + +## Example 2 from wagtail +[wagtail](https://github.com/wagtail/wagtail) +([project website](https://wagtail.io/)) is a fantastic +[Django](/django.html)-based CMS with code that is open source +under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/wagtail/wagtail/blob/master/LICENSE). + +[**wagtail / wagtail / admin / mail.py**](https://github.com/wagtail/wagtail/blob/master/wagtail/admin/mail.py) + +```python +# mail.py +import logging + +from django.conf import settings +from django.core.mail import get_connection +from django.core.mail.message import EmailMultiAlternatives +from django.template.loader import render_to_string +~~from django.utils.translation import override + +from wagtail.admin.auth import users_with_page_permission +from wagtail.core.models import PageRevision +from wagtail.users.models import UserProfile + + +logger = logging.getLogger('wagtail.admin') + + +def send_mail(subject, message, recipient_list, from_email=None, **kwargs): + if not from_email: + if hasattr(settings, 'WAGTAILADMIN_NOTIFICATION_FROM_EMAIL'): + from_email = settings.WAGTAILADMIN_NOTIFICATION_FROM_EMAIL + elif hasattr(settings, 'DEFAULT_FROM_EMAIL'): + from_email = settings.DEFAULT_FROM_EMAIL + else: + from_email = 'webmaster@localhost' + + connection = kwargs.get('connection', False) or get_connection( + username=kwargs.get('auth_user', None), + password=kwargs.get('auth_password', None), + fail_silently=kwargs.get('fail_silently', None), + ) + multi_alt_kwargs = { + + +## ... source file abbreviated to get to override examples ... + + + email_recipients = [ + recipient for recipient in recipients + if recipient.email and recipient.pk != excluded_user_id and getattr( + UserProfile.get_for_user(recipient), + notification + '_notifications' + ) + ] + + if not email_recipients: + return True + + template_subject = 'wagtailadmin/notifications/' + notification + '_subject.txt' + template_text = 'wagtailadmin/notifications/' + notification + '.txt' + template_html = 'wagtailadmin/notifications/' + notification + '.html' + + context = { + "revision": revision, + "settings": settings, + } + + sent_count = 0 + for recipient in email_recipients: + try: + context["user"] = recipient + +~~ with override(recipient.wagtail_userprofile.get_preferred_language()): + email_subject = render_to_string(template_subject, context).strip() + email_content = render_to_string(template_text, context).strip() + + kwargs = {} + if getattr(settings, 'WAGTAILADMIN_NOTIFICATION_USE_HTML', False): + kwargs['html_message'] = render_to_string(template_html, context) + + send_mail(email_subject, email_content, [recipient.email], **kwargs) + sent_count += 1 + except Exception: + logger.exception( + "Failed to send notification email '%s' to %s", + email_subject, recipient.email + ) + + return sent_count == len(email_recipients) + + + +## ... source file continues with no further override examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-pgettext-lazy.markdown b/content/pages/examples/django/django-utils-translation-pgettext-lazy.markdown new file mode 100644 index 000000000..d5ef274c0 --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-pgettext-lazy.markdown @@ -0,0 +1,198 @@ +title: django.utils.translation pgettext_lazy Example Code +category: page +slug: django-utils-translation-pgettext-lazy-examples +sortorder: 500011508 +toc: False +sidebartitle: django.utils.translation pgettext_lazy +meta: Python example code for the pgettext_lazy callable from the django.utils.translation module of the Django project. + + +pgettext_lazy is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / forms.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/./forms.py) + +```python +# forms.py + "SpamProtectionMixin", + "CreateRootForm", + "MoveForm", + "EditForm", + "SelectWidgetBootstrap", + "TextInputPrepend", + "CreateForm", + "DeleteForm", + "PermissionsForm", + "DirFilterForm", + "SearchForm", +] + +from datetime import timedelta + +from django import forms +from django.apps import apps +from django.contrib.auth import get_user_model +from django.core import validators +from django.core.validators import RegexValidator +from django.forms.widgets import HiddenInput +from django.shortcuts import get_object_or_404 +from django.urls import Resolver404, resolve +from django.utils import timezone +from django.utils.safestring import mark_safe +~~from django.utils.translation import gettext, gettext_lazy as _, pgettext_lazy +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.plugins.base import PluginSettingsFormMixin +from wiki.editors import getEditor + +from .forms_account_handling import UserCreationForm, UserUpdateForm + +validate_slug_numbers = RegexValidator( + r"^[0-9]+$", + _("A 'slug' cannot consist solely of numbers."), + "invalid", + inverse_match=True, +) + + +class WikiSlugField(forms.CharField): + + default_validators = [validators.validate_slug, validate_slug_numbers] + + def __init__(self, *args, **kwargs): + self.allow_unicode = kwargs.pop("allow_unicode", False) + if self.allow_unicode: + + +## ... source file abbreviated to get to pgettext_lazy examples ... + + + slug = WikiSlugField(max_length=models.URLPath.SLUG_MAX_LENGTH) + redirect = forms.BooleanField( + label=_("Redirect pages"), + help_text=_("Create a redirect page for every moved article?"), + required=False, + ) + + def clean(self): + cd = super().clean() + if cd.get("slug"): + dest_path = get_object_or_404( + models.URLPath, pk=self.cleaned_data["destination"] + ) + cd["slug"] = _clean_slug(cd["slug"], dest_path) + return cd + + +class EditForm(forms.Form, SpamProtectionMixin): + + title = forms.CharField(label=_("Title"),) + content = forms.CharField( + label=_("Contents"), required=False, widget=getEditor().get_widget() + ) # @UndefinedVariable + + summary = forms.CharField( +~~ label=pgettext_lazy("Revision comment", "Summary"), + help_text=_( + "Give a short reason for your edit, which will be stated in the revision log." + ), + required=False, + ) + + current_revision = forms.IntegerField(required=False, widget=forms.HiddenInput()) + + def __init__(self, request, current_revision, *args, **kwargs): + + self.request = request + self.no_clean = kwargs.pop("no_clean", False) + self.preview = kwargs.pop("preview", False) + self.initial_revision = current_revision + self.presumed_revision = None + if current_revision: + provided_content = True + content = kwargs.pop("content", None) + if content is None: + provided_content = False + content = current_revision.content + initial = { + "content": content, + "title": current_revision.title, + + +## ... source file abbreviated to get to pgettext_lazy examples ... + + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + context["prepend"] = mark_safe(self.prepend) + return context + + +class CreateForm(forms.Form, SpamProtectionMixin): + def __init__(self, request, urlpath_parent, *args, **kwargs): + super().__init__(*args, **kwargs) + self.request = request + self.urlpath_parent = urlpath_parent + + title = forms.CharField(label=_("Title"),) + slug = WikiSlugField( + label=_("Slug"), + help_text=_( + "This will be the address where your article can be found. Use only alphanumeric characters and - or _.
    Note: If you change the slug later on, links pointing to this article are not updated." + ), + max_length=models.URLPath.SLUG_MAX_LENGTH, + ) + content = forms.CharField( + label=_("Contents"), required=False, widget=getEditor().get_widget() + ) # @UndefinedVariable + + summary = forms.CharField( +~~ label=pgettext_lazy("Revision comment", "Summary"), + help_text=_("Write a brief message for the article's history log."), + required=False, + ) + + def clean_slug(self): + return _clean_slug(self.cleaned_data["slug"], self.urlpath_parent) + + def clean(self): + self.check_spam() + return self.cleaned_data + + +class DeleteForm(forms.Form): + def __init__(self, *args, **kwargs): + self.article = kwargs.pop("article") + self.has_children = kwargs.pop("has_children") + super().__init__(*args, **kwargs) + + confirm = forms.BooleanField(required=False, label=_("Yes, I am sure")) + purge = forms.BooleanField( + widget=HiddenInput(), + required=False, + label=_("Purge"), + help_text=_( + + +## ... source file continues with no further pgettext_lazy examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-pgettext.markdown b/content/pages/examples/django/django-utils-translation-pgettext.markdown new file mode 100644 index 000000000..a548708ad --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-pgettext.markdown @@ -0,0 +1,120 @@ +title: django.utils.translation pgettext Example Code +category: page +slug: django-utils-translation-pgettext-examples +sortorder: 500011507 +toc: False +sidebartitle: django.utils.translation pgettext +meta: Python example code for the pgettext callable from the django.utils.translation module of the Django project. + + +pgettext is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / forms.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/forms.py) + +```python +# forms.py +from __future__ import absolute_import + +import warnings +from importlib import import_module + +from django import forms +from django.contrib.auth.tokens import PasswordResetTokenGenerator +from django.contrib.sites.shortcuts import get_current_site +from django.core import exceptions, validators +from django.urls import reverse +~~from django.utils.translation import gettext, gettext_lazy as _, pgettext + +from ..utils import ( + build_absolute_uri, + get_username_max_length, + set_form_field_order, +) +from . import app_settings +from .adapter import get_adapter +from .app_settings import AuthenticationMethod +from .models import EmailAddress +from .utils import ( + filter_users_by_email, + get_user_model, + perform_login, + setup_user_email, + sync_user_email_addresses, + url_str_to_user_pk, + user_email, + user_pk_to_url_str, + user_username, +) + + +class EmailAwarePasswordResetTokenGenerator(PasswordResetTokenGenerator): + + +## ... source file abbreviated to get to pgettext examples ... + + + def __init__(self, *args, **kwargs): + self.request = kwargs.pop('request', None) + super(LoginForm, self).__init__(*args, **kwargs) + if app_settings.AUTHENTICATION_METHOD == AuthenticationMethod.EMAIL: + login_widget = forms.TextInput(attrs={'type': 'email', + 'placeholder': + _('E-mail address'), + 'autofocus': 'autofocus'}) + login_field = forms.EmailField(label=_("E-mail"), + widget=login_widget) + elif app_settings.AUTHENTICATION_METHOD \ + == AuthenticationMethod.USERNAME: + login_widget = forms.TextInput(attrs={'placeholder': + _('Username'), + 'autofocus': 'autofocus'}) + login_field = forms.CharField( + label=_("Username"), + widget=login_widget, + max_length=get_username_max_length()) + else: + assert app_settings.AUTHENTICATION_METHOD \ + == AuthenticationMethod.USERNAME_EMAIL + login_widget = forms.TextInput(attrs={'placeholder': + _('Username or e-mail'), + 'autofocus': 'autofocus'}) +~~ login_field = forms.CharField(label=pgettext("field label", + "Login"), + widget=login_widget) + self.fields["login"] = login_field + set_form_field_order(self, ["login", "password", "remember"]) + if app_settings.SESSION_REMEMBER is not None: + del self.fields['remember'] + + def user_credentials(self): + credentials = {} + login = self.cleaned_data["login"] + if app_settings.AUTHENTICATION_METHOD == AuthenticationMethod.EMAIL: + credentials["email"] = login + elif ( + app_settings.AUTHENTICATION_METHOD == + AuthenticationMethod.USERNAME): + credentials["username"] = login + else: + if self._is_login_email(login): + credentials["email"] = login + credentials["username"] = login + credentials["password"] = self.cleaned_data["password"] + return credentials + + def clean_login(self): + + +## ... source file continues with no further pgettext examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-ugettext-lazy.markdown b/content/pages/examples/django/django-utils-translation-ugettext-lazy.markdown new file mode 100644 index 000000000..042ab4467 --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-ugettext-lazy.markdown @@ -0,0 +1,115 @@ +title: django.utils.translation ugettext_lazy Example Code +category: page +slug: django-utils-translation-ugettext-lazy-examples +sortorder: 500011510 +toc: False +sidebartitle: django.utils.translation ugettext_lazy +meta: Python example code for the ugettext_lazy callable from the django.utils.translation module of the Django project. + + +ugettext_lazy is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / imageadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/imageadmin.py) + +```python +# imageadmin.py +from __future__ import absolute_import + +from django import forms +from django.utils.translation import ugettext as _ +~~from django.utils.translation import ugettext_lazy + +from ..settings import FILER_IMAGE_MODEL +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import string_concat +from ..utils.loader import load_model +from .fileadmin import FileAdmin + + +Image = load_model(FILER_IMAGE_MODEL) + + +class ImageAdminForm(forms.ModelForm): + subject_location = forms.CharField( + max_length=64, required=False, + label=_('Subject location'), + help_text=_('Location of the main subject of the scene. ' + 'Format: "x,y".')) + + def sidebar_image_ratio(self): + if self.instance: + return '%.6F' % self.instance.sidebar_image_ratio() + else: + return '' + + def _set_previous_subject_location(self, cleaned_data): + subject_location = self.instance.subject_location + cleaned_data['subject_location'] = subject_location + self.data = self.data.copy() + self.data['subject_location'] = subject_location + + def clean_subject_location(self): + cleaned_data = super(ImageAdminForm, self).clean() + subject_location = cleaned_data['subject_location'] + if not subject_location: + return subject_location + + coordinates = normalize_subject_location(subject_location) + + if not coordinates: +~~ err_msg = ugettext_lazy('Invalid subject location format. ') + err_code = 'invalid_subject_format' + + elif ( + coordinates[0] > self.instance.width + or coordinates[1] > self.instance.height + ): +~~ err_msg = ugettext_lazy( + 'Subject location is outside of the image. ') + err_code = 'subject_out_of_bounds' + else: + return subject_location + + self._set_previous_subject_location(cleaned_data) + raise forms.ValidationError( + string_concat( + err_msg, +~~ ugettext_lazy('Your input: "{subject_location}". '.format( + subject_location=subject_location)), + 'Previous value is restored.'), + code=err_code) + + class Meta(object): + model = Image + exclude = () + + class Media(object): + css = { + } + js = ( + + ) + + +class ImageAdmin(FileAdmin): + change_form_template = 'admin/filer/image/change_form.html' + form = ImageAdminForm + + +if FILER_IMAGE_MODEL == 'filer.Image': + extra_main_fields = ('author', 'default_alt_text', 'default_caption',) +else: + + +## ... source file continues with no further ugettext_lazy examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-ugettext.markdown b/content/pages/examples/django/django-utils-translation-ugettext.markdown new file mode 100644 index 000000000..4d003aaf6 --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-ugettext.markdown @@ -0,0 +1,125 @@ +title: django.utils.translation ugettext Example Code +category: page +slug: django-utils-translation-ugettext-examples +sortorder: 500011509 +toc: False +sidebartitle: django.utils.translation ugettext +meta: Python example code for the ugettext callable from the django.utils.translation module of the Django project. + + +ugettext is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / plugin_base.py**](https://github.com/divio/django-cms/blob/develop/cms/./plugin_base.py) + +```python +# plugin_base.py +import json +import re + +from django.shortcuts import render as render_to_response + +from django import forms +from django.contrib import admin +from django.contrib import messages +from django.core.exceptions import ( + ImproperlyConfigured, + ObjectDoesNotExist, + ValidationError, +) +from django.utils.encoding import force_text, smart_str +from django.utils.html import escapejs +~~from django.utils.translation import ugettext, ugettext_lazy as _ + +from six import with_metaclass, python_2_unicode_compatible + +from cms import operations +from cms.exceptions import SubClassNeededError +from cms.models import CMSPlugin +from cms.toolbar.utils import get_plugin_tree_as_json, get_plugin_toolbar_info +from cms.utils.conf import get_cms_setting + + +class CMSPluginBaseMetaclass(forms.MediaDefiningClass): + def __new__(cls, name, bases, attrs): + super_new = super(CMSPluginBaseMetaclass, cls).__new__ + parents = [base for base in bases if isinstance(base, CMSPluginBaseMetaclass)] + if not parents: + return super_new(cls, name, bases, attrs) + new_plugin = super_new(cls, name, bases, attrs) + if not issubclass(new_plugin.model, CMSPlugin): + raise SubClassNeededError( + "The 'model' attribute on CMSPluginBase subclasses must be " + "either CMSPlugin or a subclass of CMSPlugin. %r on %r is not." + % (new_plugin.model, new_plugin) + ) + if (not hasattr(new_plugin, 'render_template') and + + +## ... source file abbreviated to get to ugettext examples ... + + + + def icon_src(self, instance): + return "" + + def icon_alt(self, instance): + return "%s - %s" % (force_text(self.name), force_text(instance)) + + def get_fieldsets(self, request, obj=None): + fieldsets = super(CMSPluginBase, self).get_fieldsets(request, obj) + + for name, data in fieldsets: + if data.get('fields'): # if fieldset with non-empty fields is found, return fieldsets + return fieldsets + + if self.inlines: + return [] # if plugin has inlines but no own fields return empty fieldsets to remove empty white fieldset + + try: # if all fieldsets are empty (assuming there is only one fieldset then) add description + fieldsets[0][1]['description'] = self.get_empty_change_form_text(obj=obj) + except KeyError: + pass + return fieldsets + + @classmethod + def get_empty_change_form_text(cls, obj=None): +~~ return ugettext('There are no further settings for this plugin. Please press save.') + + @classmethod + def get_child_class_overrides(cls, slot, page): + from cms.utils.placeholder import get_placeholder_conf + + template = page.get_template() if page else None + + ph_conf = get_placeholder_conf('child_classes', slot, template, default={}) + return ph_conf.get(cls.__name__, cls.child_classes) + + @classmethod + def get_child_plugin_candidates(cls, slot, page): + from cms.plugin_pool import plugin_pool + return plugin_pool.registered_plugins + + @classmethod + def get_child_classes(cls, slot, page, instance=None): + child_classes = cls.get_child_class_overrides(slot, page) + + if child_classes: + return child_classes + + installed_plugins = cls.get_child_plugin_candidates(slot, page) + + + +## ... source file continues with no further ugettext examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-ungettext-lazy.markdown b/content/pages/examples/django/django-utils-translation-ungettext-lazy.markdown new file mode 100644 index 000000000..0872e9896 --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-ungettext-lazy.markdown @@ -0,0 +1,107 @@ +title: django.utils.translation ungettext_lazy Example Code +category: page +slug: django-utils-translation-ungettext-lazy-examples +sortorder: 500011512 +toc: False +sidebartitle: django.utils.translation ungettext_lazy +meta: Python example code for the ungettext_lazy callable from the django.utils.translation module of the Django project. + + +ungettext_lazy is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / forms / fields.py**](https://github.com/jrief/django-angular/blob/master/djng/forms/fields.py) + +```python +# fields.py +import re +import mimetypes + +from django.conf import settings +from django.contrib.staticfiles.storage import staticfiles_storage +from django.core import signing +from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.core.files.storage import default_storage +from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile +from django.urls import reverse_lazy +from django.forms import fields, models as model_fields, widgets +from django.utils.html import format_html +from django.utils.module_loading import import_string +from django.utils.safestring import mark_safe +~~from django.utils.translation import ugettext_lazy as _, ungettext_lazy + +from djng import app_settings +from .widgets import DropFileWidget, DropImageWidget + + +class DefaultFieldMixin(object): + render_label = True + + def has_subwidgets(self): + return False + + def get_potential_errors(self): + return self.get_input_required_errors() + + def get_input_required_errors(self): + errors = [] + if self.required: + self.widget.attrs['ng-required'] = 'true' + for key, msg in self.error_messages.items(): + if key == 'required': + errors.append(('$error.required', msg)) + return errors + + def get_min_max_length_errors(self): + errors = [] + if getattr(self, 'min_length', None): + self.widget.attrs['ng-minlength'] = self.min_length + if getattr(self, 'max_length', None): + self.widget.attrs['ng-maxlength'] = self.max_length + for item in self.validators: + if getattr(item, 'code', None) == 'min_length': +~~ message = ungettext_lazy( + 'Ensure this value has at least %(limit_value)d character', + 'Ensure this value has at least %(limit_value)d characters', + 'limit_value') + errors.append(('$error.minlength', message % {'limit_value': self.min_length})) + if getattr(item, 'code', None) == 'max_length': +~~ message = ungettext_lazy( + 'Ensure this value has at most %(limit_value)d character', + 'Ensure this value has at most %(limit_value)d characters', + 'limit_value') + errors.append(('$error.maxlength', message % {'limit_value': self.max_length})) + return errors + + def get_min_max_value_errors(self): + errors = [] + if isinstance(getattr(self, 'min_value', None), int): + self.widget.attrs['min'] = self.min_value + if isinstance(getattr(self, 'max_value', None), int): + self.widget.attrs['max'] = self.max_value + errkeys = [] + for key, msg in self.error_messages.items(): + if key == 'min_value': + errors.append(('$error.min', msg)) + errkeys.append(key) + if key == 'max_value': + errors.append(('$error.max', msg)) + errkeys.append(key) + for item in self.validators: + if getattr(item, 'code', None) == 'min_value' and 'min_value' not in errkeys: + errors.append(('$error.min', item.message % {'limit_value': self.min_value})) + errkeys.append('min_value') + + +## ... source file continues with no further ungettext_lazy examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation-ungettext.markdown b/content/pages/examples/django/django-utils-translation-ungettext.markdown new file mode 100644 index 000000000..ed932d381 --- /dev/null +++ b/content/pages/examples/django/django-utils-translation-ungettext.markdown @@ -0,0 +1,249 @@ +title: django.utils.translation ungettext Example Code +category: page +slug: django-utils-translation-ungettext-examples +sortorder: 500011511 +toc: False +sidebartitle: django.utils.translation ungettext +meta: Python example code for the ungettext callable from the django.utils.translation module of the Django project. + + +ungettext is a callable within the django.utils.translation module of the Django project. + + +## Example 1 from django-filer +[django-filer](https://github.com/divio/django-filer) +([project documentation](https://django-filer.readthedocs.io/en/latest/)) +is a file management library for uploading and organizing files and images +in Django's admin interface. The project's code is available under the +[BSD 3-Clause "New" or "Revised" open source license](https://github.com/divio/django-filer/blob/develop/LICENSE.txt). + +[**django-filer / filer / admin / folderadmin.py**](https://github.com/divio/django-filer/blob/develop/filer/admin/folderadmin.py) + +```python +# folderadmin.py +from __future__ import absolute_import, division, unicode_literals + +import itertools +import os +import re +from collections import OrderedDict + +from django import forms +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import messages +from django.contrib.admin import helpers +from django.contrib.admin.utils import capfirst, quote, unquote +from django.core.exceptions import PermissionDenied, ValidationError +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db import models, router +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils.encoding import force_text +from django.utils.html import escape +from django.utils.http import urlquote, urlunquote +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _ +~~from django.utils.translation import ugettext_lazy, ungettext + +from .. import settings +from ..models import ( + File, Folder, FolderPermission, FolderRoot, ImagesWithMissingData, + UnsortedImages, tools, +) +from ..settings import FILER_IMAGE_MODEL, FILER_PAGINATE_BY +from ..thumbnail_processors import normalize_subject_location +from ..utils.compatibility import get_delete_permission +from ..utils.filer_easy_thumbnails import FilerActionThumbnailer +from ..utils.loader import load_model +from . import views +from .forms import CopyFilesAndFoldersForm, RenameFilesForm, ResizeImagesForm +from .patched.admin_utils import get_deleted_objects +from .permissions import PrimitivePermissionAwareModelAdmin +from .tools import ( + AdminContext, admin_url_params_encoded, check_files_edit_permissions, + check_files_read_permissions, check_folder_edit_permissions, + check_folder_read_permissions, popup_status, userperms_for_request, +) + + +Image = load_model(FILER_IMAGE_MODEL) + + + +## ... source file abbreviated to get to ungettext examples ... + + + response = self.response_action(request, files_queryset=file_qs, folders_queryset=folder_qs) + if response: + return response + else: + msg = _("Items must be selected in order to perform " + "actions on them. No items have been changed.") + self.message_user(request, msg) + + if ( + actions and request.method == 'POST' + and helpers.ACTION_CHECKBOX_NAME in request.POST + and 'index' not in request.POST + and '_save' not in request.POST + ): + if selected: + response = self.response_action(request, files_queryset=file_qs, folders_queryset=folder_qs) + if response: + return response + + if actions: + action_form = self.action_form(auto_id=None) + action_form.fields['action'].choices = self.get_action_choices(request) + else: + action_form = None + +~~ selection_note_all = ungettext('%(total_count)s selected', + 'All %(total_count)s selected', paginator.count) + + try: + paginated_items = paginator.page(request.GET.get('page', 1)) + except PageNotAnInteger: + paginated_items = paginator.page(1) + except EmptyPage: + paginated_items = paginator.page(paginator.num_pages) + + context = self.admin_site.each_context(request) + context.update({ + 'folder': folder, + 'clipboard_files': File.objects.filter( + in_clipboards__clipboarditem__clipboard__user=request.user + ).distinct(), + 'paginator': paginator, + 'paginated_items': paginated_items, + 'virtual_items': virtual_items, + 'uploader_connections': settings.FILER_UPLOADER_CONNECTIONS, + 'permissions': permissions, + 'permstest': userperms_for_request(folder, request), + 'current_url': request.path, + 'title': _('Directory listing for %(folder_name)s') % {'folder_name': folder.name}, + 'search_string': ' '.join(search_terms), + + +## ... source file continues with no further ungettext examples... + +``` + + +## Example 2 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / admin.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./admin.py) + +```python +# admin.py +from django.contrib.admin.options import ModelAdmin, csrf_protect_m +from django.contrib.admin.views.main import SEARCH_VAR, ChangeList +from django.core.exceptions import PermissionDenied +from django.core.paginator import InvalidPage, Paginator +from django.shortcuts import render +from django.utils.encoding import force_str +~~from django.utils.translation import ungettext + +from haystack import connections +from haystack.constants import DEFAULT_ALIAS +from haystack.query import SearchQuerySet +from haystack.utils import get_model_ct_tuple + + +class SearchChangeList(ChangeList): + def __init__(self, **kwargs): + self.haystack_connection = kwargs.pop("haystack_connection", DEFAULT_ALIAS) + super(SearchChangeList, self).__init__(**kwargs) + + def get_results(self, request): + if SEARCH_VAR not in request.GET: + return super(SearchChangeList, self).get_results(request) + + sqs = ( + SearchQuerySet(self.haystack_connection) + .models(self.model) + .auto_query(request.GET[SEARCH_VAR]) + .load_all() + ) + + paginator = Paginator(sqs, self.list_per_page) + + +## ... source file abbreviated to get to ungettext examples ... + + + "model": self.model, + "list_display": list_display, + "list_display_links": self.list_display_links, + "list_filter": self.list_filter, + "date_hierarchy": self.date_hierarchy, + "search_fields": self.search_fields, + "list_select_related": self.list_select_related, + "list_per_page": self.list_per_page, + "list_editable": self.list_editable, + "list_max_show_all": self.list_max_show_all, + "model_admin": self, + } + if hasattr(self, 'get_sortable_by'): # Django 2.1+ + kwargs["sortable_by"] = self.get_sortable_by(request) + changelist = SearchChangeList(**kwargs) + changelist.formset = None + media = self.media + + actions = self.get_actions(request) + if actions: + action_form = self.action_form(auto_id=None) + action_form.fields["action"].choices = self.get_action_choices(request) + else: + action_form = None + +~~ selection_note = ungettext( + "0 of %(count)d selected", + "of %(count)d selected", + len(changelist.result_list), + ) +~~ selection_note_all = ungettext( + "%(total_count)s selected", + "All %(total_count)s selected", + changelist.result_count, + ) + + context = { + "module_name": force_str(self.model._meta.verbose_name_plural), + "selection_note": selection_note % {"count": len(changelist.result_list)}, + "selection_note_all": selection_note_all + % {"total_count": changelist.result_count}, + "title": changelist.title, + "is_popup": changelist.is_popup, + "cl": changelist, + "media": media, + "has_add_permission": self.has_add_permission(request), + "opts": changelist.opts, + "app_label": self.model._meta.app_label, + "action_form": action_form, + "actions_on_top": self.actions_on_top, + "actions_on_bottom": self.actions_on_bottom, + "actions_selection_counter": getattr(self, "actions_selection_counter", 0), + } + context.update(extra_context or {}) + request.current_app = self.admin_site.name + + +## ... source file continues with no further ungettext examples... + +``` + diff --git a/content/pages/examples/django/django-utils-translation.markdown b/content/pages/examples/django/django-utils-translation.markdown new file mode 100644 index 000000000..e74637893 --- /dev/null +++ b/content/pages/examples/django/django-utils-translation.markdown @@ -0,0 +1,494 @@ +title: django.utils translation Example Code +category: page +slug: django-utils-translation-examples +sortorder: 500011422 +toc: False +sidebartitle: django.utils translation +meta: Python example code for the translation callable from the django.utils module of the Django project. + + +translation is a callable within the django.utils module of the Django project. + + +## Example 1 from django-cms +[django-cms](https://github.com/divio/django-cms) +([project website](https://www.django-cms.org/en/)) is a Python-based +content management system (CMS) [library](https://pypi.org/project/django-cms/) +for use with Django web apps that is open sourced under the +[BSD 3-Clause "New"](https://github.com/divio/django-cms/blob/develop/LICENSE) +license. + +[**django-cms / cms / admin / placeholderadmin.py**](https://github.com/divio/django-cms/blob/develop/cms/admin/placeholderadmin.py) + +```python +# placeholderadmin.py +import uuid +import warnings + +from django.conf.urls import url +from django.contrib.admin.helpers import AdminForm +from django.contrib.admin.utils import get_deleted_objects +from django.core.exceptions import PermissionDenied +from django.db import router, transaction +from django.http import ( + HttpResponse, + HttpResponseBadRequest, + HttpResponseForbidden, + HttpResponseNotFound, + HttpResponseRedirect, +) +from django.shortcuts import get_list_or_404, get_object_or_404, render +from django.template.response import TemplateResponse +from django.utils.decorators import method_decorator +from django.utils.encoding import force_text +~~from django.utils import translation +from django.utils.translation import ugettext as _ +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.decorators.http import require_POST + +from six.moves.urllib.parse import parse_qsl, urlparse + +from six import get_unbound_function, get_method_function + +from cms import operations +from cms.admin.forms import PluginAddValidationForm +from cms.constants import SLUG_REGEXP +from cms.exceptions import PluginLimitReached +from cms.models.placeholdermodel import Placeholder +from cms.models.placeholderpluginmodel import PlaceholderReference +from cms.models.pluginmodel import CMSPlugin +from cms.plugin_pool import plugin_pool +from cms.signals import pre_placeholder_operation, post_placeholder_operation +from cms.toolbar.utils import get_plugin_tree_as_json +from cms.utils import copy_plugins, get_current_site +from cms.utils.compat import DJANGO_2_0 +from cms.utils.conf import get_cms_setting +from cms.utils.i18n import get_language_code, get_language_list +from cms.utils.plugins import has_reached_plugin_limit, reorder_plugins +from cms.utils.urlutils import admin_reverse + + +## ... source file abbreviated to get to translation examples ... + + + 'has_add_permission': False, + 'window_close_timeout': 10, + } + if cancel_clicked: + context.update({ + 'cancel': True, + }) + return render(request, 'admin/cms/page/plugin/confirm_form.html', context) + if not cancel_clicked and request.method == 'POST' and saved_successfully: + return render(request, 'admin/cms/page/plugin/confirm_form.html', context) + return render(request, 'admin/cms/page/plugin/change_form.html', context) + + +class PlaceholderAdminMixin(object): + + def _get_attached_admin(self, placeholder): + return placeholder._get_attached_admin(admin_site=self.admin_site) + + def _get_operation_language(self, request): + site = get_current_site() + parsed_url = urlparse(request.GET['cms_path']) + queries = dict(parse_qsl(parsed_url.query)) + language = queries.get('language') + + if not language: +~~ language = translation.get_language_from_path(parsed_url.path) + return get_language_code(language, site_id=site.pk) + + def _get_operation_origin(self, request): + return urlparse(request.GET['cms_path']).path + + def _send_pre_placeholder_operation(self, request, operation, **kwargs): + token = str(uuid.uuid4()) + + if not request.GET.get('cms_path'): + warnings.warn('All custom placeholder admin endpoints require ' + 'a "cms_path" GET query which points to the path ' + 'where the request originates from.' + 'This backwards compatible shim will be removed on 3.5 ' + 'and an HttpBadRequest response will be returned instead.', + UserWarning) + return token + + pre_placeholder_operation.send( + sender=self.__class__, + operation=operation, + request=request, + language=self._get_operation_language(request), + token=token, + origin=self._get_operation_origin(request), + + +## ... source file continues with no further translation examples... + +``` + + +## Example 2 from django-floppyforms +[django-floppyforms](https://github.com/jazzband/django-floppyforms) +([project documentation](https://django-floppyforms.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-floppyforms/)) +is a [Django](/django.html) code library for better control +over rendering HTML forms in your [templates](/template-engines.html). + +The django-floppyforms code is provided as +[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-floppyforms / floppyforms / gis / widgets.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/gis/widgets.py) + +```python +# widgets.py +from django.conf import settings +from django.template.defaultfilters import safe +~~from django.utils import translation + +import floppyforms as forms + +from urllib.parse import urlencode + +try: + from django.contrib.gis import gdal, geos +except ImportError: + + +__all__ = ('GeometryWidget', 'GeometryCollectionWidget', + 'PointWidget', 'MultiPointWidget', + 'LineStringWidget', 'MultiLineStringWidget', + 'PolygonWidget', 'MultiPolygonWidget', + 'BaseGeometryWidget', 'BaseMetacartaWidget', + 'BaseOsmWidget', 'BaseGMapWidget') + + +class BaseGeometryWidget(forms.Textarea): + display_wkt = False + map_width = 600 + map_height = 400 + map_srid = 4326 + template_name = 'floppyforms/gis/openlayers.html' + + +## ... source file abbreviated to get to translation examples ... + + + + if value and value.geom_type.upper() != self.geom_type and self.geom_type != 'GEOMETRY': + value = None + + wkt = '' + if value: + srid = self.map_srid + if value.srid != srid: + try: + ogr = value.ogr + ogr.transform(srid) + wkt = ogr.wkt + except gdal.GDALException: + pass # wkt left as an empty string + else: + wkt = value.wkt + context = super(BaseGeometryWidget, self).get_context(name, wkt, attrs) + context['module'] = 'map_%s' % name.replace('-', '_') + context['name'] = name + + + if hasattr(settings, 'ADMIN_MEDIA_PREFIX'): + context['ADMIN_MEDIA_PREFIX'] = settings.ADMIN_MEDIA_PREFIX + else: + context['ADMIN_MEDIA_PREFIX'] = settings.STATIC_URL + 'admin/' +~~ context['LANGUAGE_BIDI'] = translation.get_language_bidi() + return context + + +class GeometryWidget(BaseGeometryWidget): + pass + + +class GeometryCollectionWidget(GeometryWidget): + is_collection = True + geom_type = 'GEOMETRYCOLLECTION' + + +class PointWidget(BaseGeometryWidget): + is_point = True + geom_type = 'POINT' + + +class MultiPointWidget(PointWidget): + is_collection = True + geom_type = 'MULTIPOINT' + + +class LineStringWidget(BaseGeometryWidget): + is_linestring = True + + +## ... source file continues with no further translation examples... + +``` + + +## Example 3 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / utils.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./utils.py) + +```python +# utils.py +import datetime +import json +from django.template import Context +~~from django.utils import translation +from jet import settings +from jet.models import PinnedApplication + +try: + from django.apps.registry import apps +except ImportError: + try: + from django.apps import apps # Fix Django 1.7 import issue + except ImportError: + pass +from django.core.serializers.json import DjangoJSONEncoder +from django.http import HttpResponse +try: + from django.core.urlresolvers import reverse, resolve, NoReverseMatch +except ImportError: # Django 1.11 + from django.urls import reverse, resolve, NoReverseMatch + +from django.contrib.admin import AdminSite +from django.utils.encoding import smart_text +from django.utils.text import capfirst +from django.contrib import messages +from django.utils.encoding import force_text +from django.utils.functional import Promise +from django.contrib.admin.options import IncorrectLookupParameters + + +## ... source file abbreviated to get to translation examples ... + + + + ChangeList = model_admin.get_changelist(request) + + change_list_args = [ + request, model, list_display, list_display_links, list_filter, + model_admin.date_hierarchy, search_fields, list_select_related, + model_admin.list_per_page, model_admin.list_max_show_all, + model_admin.list_editable, model_admin] + + try: + sortable_by = model_admin.get_sortable_by(request) + change_list_args.append(sortable_by) + except AttributeError: + pass + + try: + cl = ChangeList(*change_list_args) + queryset = cl.get_queryset(request) + except IncorrectLookupParameters: + pass + + return queryset + + +def get_possible_language_codes(): +~~ language_code = translation.get_language() + + language_code = language_code.replace('_', '-').lower() + language_codes = [] + + split = language_code.split('-', 2) + if len(split) == 2: + language_code = '%s-%s' % (split[0].lower(), split[1].upper()) if split[0] != split[1] else split[0] + + language_codes.append(language_code) + + if len(split) == 2: + language_codes.append(split[0].lower()) + + return language_codes + + +def get_original_menu_items(context): + if context.get('user') and user_is_authenticated(context['user']): + pinned_apps = PinnedApplication.objects.filter(user=context['user'].pk).values_list('app_label', flat=True) + else: + pinned_apps = [] + + original_app_list = get_app_list(context) + + + +## ... source file continues with no further translation examples... + +``` + + +## Example 4 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / models / article.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/models/article.py) + +```python +# article.py +from django.conf import settings as django_settings +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +from django.core.cache import cache +from django.db import models +from django.db.models.fields import GenericIPAddressField as IPAddressField +from django.db.models.signals import post_save +from django.db.models.signals import pre_delete +from django.db.models.signals import pre_save +from django.urls import reverse +~~from django.utils import translation +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ +from mptt.models import MPTTModel +from wiki import managers +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.markdown import article_markdown +from wiki.decorators import disable_signal_for_loaddata + +__all__ = [ + "Article", + "ArticleForObject", + "ArticleRevision", + "BaseRevisionMixin", +] + + +class Article(models.Model): + + objects = managers.ArticleManager() + + current_revision = models.OneToOneField( + "ArticleRevision", + verbose_name=_("current revision"), + + +## ... source file abbreviated to get to translation examples ... + + + return self.current_revision.title + obj_name = _("Article without content (%(id)d)") % {"id": self.id} + return str(obj_name) + + class Meta: + permissions = ( + ("moderate", _("Can edit all articles and lock/unlock/restore")), + ("assign", _("Can change ownership of any article")), + ("grant", _("Can assign permissions to other users")), + ) + + def render(self, preview_content=None, user=None): + if not self.current_revision: + return "" + if preview_content: + content = preview_content + else: + content = self.current_revision.content + return mark_safe( + article_markdown( + content, self, preview=preview_content is not None, user=user + ) + ) + + def get_cache_key(self): +~~ lang = translation.get_language() + + return "wiki:article:{id}:{lang}".format( + id=self.current_revision.id if self.current_revision else self.id, lang=lang + ) + + def get_cache_content_key(self, user=None): + return "{key}:{user}".format( + key=self.get_cache_key(), user=user.get_username() if user else "" + ) + + def get_cached_content(self, user=None): + + cache_key = self.get_cache_key() + cache_content_key = self.get_cache_content_key(user) + + cached_items = cache.get(cache_key, list()) + + if cache_content_key in cached_items: + cached_content = cache.get(cache_content_key) + if cached_content is not None: + return mark_safe(cached_content) + + cached_content = self.render(user=user) + cached_items.append(cache_content_key) + + +## ... source file continues with no further translation examples... + +``` + + +## Example 5 from register +[register](https://github.com/ORGAN-IZE/register) is a [Django](/django.html), +[Bootstrap](/bootstrap-css.html), [PostgreSQL](/postgresql.html) project that is +open source under the +[GNU General Public License v3.0](https://github.com/ORGAN-IZE/register/blob/master/LICENSE). +This web application makes it easier for people to register as organ donors. +You can see the application live at +[https://register.organize.org/](https://register.organize.org/). + +[**register / registration / middleware.py**](https://github.com/ORGAN-IZE/register/blob/master/registration/./middleware.py) + +```python +# middleware.py +import django.middleware.locale +import django.shortcuts +~~from django.utils import translation +from django.utils.deprecation import MiddlewareMixin + + +class RequestLocaleMiddleware(MiddlewareMixin): + def process_view(self, request, view_func, view_args, view_kwargs): + if request.method == 'GET': + language = request.GET.get('lang') + if language: +~~ translation.activate(language) +~~ request.session[translation.LANGUAGE_SESSION_KEY] = translation.get_language() + query = request.GET.copy() + del query['lang'] + path = '?'.join([request.path, query.urlencode()]) + return django.shortcuts.redirect(path) + + + +## ... source file continues with no further translation examples... + +``` + diff --git a/content/pages/examples/django/django-utils-tree.markdown b/content/pages/examples/django/django-utils-tree.markdown new file mode 100644 index 000000000..c3496e58f --- /dev/null +++ b/content/pages/examples/django/django-utils-tree.markdown @@ -0,0 +1,123 @@ +title: django.utils tree Example Code +category: page +slug: django-utils-tree-examples +sortorder: 500011423 +toc: False +sidebartitle: django.utils tree +meta: Python example code for the tree callable from the django.utils module of the Django project. + + +tree is a callable within the django.utils module of the Django project. + + +## Example 1 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / backends / __init__.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/backends/__init__.py) + +```python +# __init__.py +import copy +from copy import deepcopy +from time import time + +from django.conf import settings +from django.db.models import Q +from django.db.models.base import ModelBase +~~from django.utils import tree +from django.utils.encoding import force_str + +from haystack.constants import VALID_FILTERS, FILTER_SEPARATOR, DEFAULT_ALIAS +from haystack.exceptions import MoreLikeThisError, FacetingError +from haystack.models import SearchResult +from haystack.utils.loading import UnifiedIndex +from haystack.utils import get_model_ct + +VALID_GAPS = ["year", "month", "day", "hour", "minute", "second"] + +SPELLING_SUGGESTION_HAS_NOT_RUN = object() + + +def log_query(func): + + def wrapper(obj, query_string, *args, **kwargs): + start = time() + + try: + return func(obj, query_string, *args, **kwargs) + finally: + stop = time() + + if settings.DEBUG: + + +## ... source file abbreviated to get to tree examples ... + + + if " " in query_string: + query_string = "(%s)" % query_string + + return "NOT %s" % query_string + + def build_exact_query(self, query_string): + return '"%s"' % query_string + + def add_filter(self, query_filter, use_or=False): + if use_or: + connector = SQ.OR + else: + connector = SQ.AND + + if ( + self.query_filter + and query_filter.connector != connector + and len(query_filter) > 1 + ): + self.query_filter.start_subtree(connector) + subtree = True + else: + subtree = False + + for child in query_filter.children: +~~ if isinstance(child, tree.Node): + self.query_filter.start_subtree(connector) + self.add_filter(child) + self.query_filter.end_subtree() + else: + expression, value = child + self.query_filter.add((expression, value), connector) + + connector = query_filter.connector + + if query_filter.negated: + self.query_filter.negate() + + if subtree: + self.query_filter.end_subtree() + + def add_order_by(self, field): + self.order_by.append(field) + + def clear_order_by(self): + self.order_by = [] + + def add_model(self, model): + if not isinstance(model, ModelBase): + raise AttributeError( + + +## ... source file continues with no further tree examples... + +``` + diff --git a/content/pages/examples/django/django-utils-version-get-complete-version.markdown b/content/pages/examples/django/django-utils-version-get-complete-version.markdown new file mode 100644 index 000000000..b11ff5577 --- /dev/null +++ b/content/pages/examples/django/django-utils-version-get-complete-version.markdown @@ -0,0 +1,51 @@ +title: django.utils.version get_complete_version Example Code +category: page +slug: django-utils-version-get-complete-version-examples +sortorder: 500011513 +toc: False +sidebartitle: django.utils.version get_complete_version +meta: Python example code for the get_complete_version callable from the django.utils.version module of the Django project. + + +get_complete_version is a callable within the django.utils.version module of the Django project. + + +## Example 1 from django-webtest +[django-webtest](https://github.com/django-webtest/django-webtest) +([PyPI package information](https://pypi.org/project/django-webtest/)) +is a [Django](/django.html) extension that makes it easier to use +[WebTest](http://docs.pylonsproject.org/projects/webtest/) with +your projects. + +The project is open sourced under the +[MIT license](https://github.com/django-webtest/django-webtest/blob/master/LICENSE.txt). + +[**django-webtest / django_webtest / backends.py**](https://github.com/django-webtest/django-webtest/blob/master/django_webtest/./backends.py) + +```python +# backends.py +from __future__ import absolute_import +~~from django.utils.version import get_complete_version +from django.contrib.auth.backends import RemoteUserBackend +from django_webtest.compat import from_wsgi_safe_string + +class WebtestUserBackend(RemoteUserBackend): + +~~ if get_complete_version() >= (1, 11): + def authenticate(self, request, django_webtest_user): + return super(WebtestUserBackend, self).authenticate( + request, django_webtest_user) + else: + def authenticate(self, django_webtest_user): + return super(WebtestUserBackend, self).authenticate( + django_webtest_user) + + def clean_username(self, username): + return from_wsgi_safe_string(username) + + + +## ... source file continues with no further get_complete_version examples... + +``` + diff --git a/content/pages/examples/django/django-views-csrf.markdown b/content/pages/examples/django/django-views-csrf.markdown new file mode 100644 index 000000000..3db00a9cf --- /dev/null +++ b/content/pages/examples/django/django-views-csrf.markdown @@ -0,0 +1,102 @@ +title: django.views csrf Example Code +category: page +slug: django-views-csrf-examples +sortorder: 500011514 +toc: False +sidebartitle: django.views csrf +meta: Python example code for the csrf callable from the django.views module of the Django project. + + +csrf is a callable within the django.views module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / tests.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/./tests.py) + +```python +# tests.py +from __future__ import unicode_literals + +import json +import requests +from datetime import date, datetime + +import django +from django.core.files.base import ContentFile +from django.db import models +from django.test import RequestFactory, TestCase +from django.utils.http import base36_to_int, int_to_base36 +~~from django.views import csrf + +from . import utils + + +try: + from unittest.mock import Mock, patch +except ImportError: + from mock import Mock, patch # noqa + + +class MockedResponse(object): + def __init__(self, status_code, content, headers=None): + if headers is None: + headers = {} + + self.status_code = status_code + self.content = content.encode('utf8') + self.headers = headers + + def json(self): + return json.loads(self.text) + + def raise_for_status(self): + pass + + +## ... source file abbreviated to get to csrf examples ... + + + + self.assertEqual(serialized['bb'], 'c29tZSBiaW5hcnkgZGF0YQ==') + self.assertEqual(serialized['bb_empty'], '') + self.assertEqual(deserialized.bb, b'some binary data') + self.assertEqual(deserialized.bb_empty, b'') + + def test_build_absolute_uri(self): + self.assertEqual( + utils.build_absolute_uri(None, '/foo'), + 'http://example.com/foo') + self.assertEqual( + utils.build_absolute_uri(None, '/foo', protocol='ftp'), + 'ftp://example.com/foo') + self.assertEqual( + utils.build_absolute_uri(None, 'http://foo.com/bar'), + 'http://foo.com/bar') + + def test_int_to_base36(self): + n = 55798679658823689999 + b36 = 'brxk553wvxbf3' + assert int_to_base36(n) == b36 + assert base36_to_int(b36) == n + + def test_templatetag_with_csrf_failure(self): + request = self.factory.get('/tests/test_403_csrf.html') +~~ response = csrf.csrf_failure( + request, + template_name='tests/test_403_csrf.html' + ) + self.assertEqual(response.status_code, 403) + + + +## ... source file continues with no further csrf examples... + +``` + diff --git a/content/pages/examples/django/django-views-debug-get-default-exception-reporter-filter.markdown b/content/pages/examples/django/django-views-debug-get-default-exception-reporter-filter.markdown new file mode 100644 index 000000000..9fe6bd2e6 --- /dev/null +++ b/content/pages/examples/django/django-views-debug-get-default-exception-reporter-filter.markdown @@ -0,0 +1,67 @@ +title: django.views.debug get_default_exception_reporter_filter Example Code +category: page +slug: django-views-debug-get-default-exception-reporter-filter-examples +sortorder: 500011515 +toc: False +sidebartitle: django.views.debug get_default_exception_reporter_filter +meta: Python example code for the get_default_exception_reporter_filter callable from the django.views.debug module of the Django project. + + +get_default_exception_reporter_filter is a callable within the django.views.debug module of the Django project. + + +## Example 1 from django-debug-toolbar +[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar) +([project documentation](https://github.com/jazzband/django-debug-toolbar) +and [PyPI page](https://pypi.org/project/django-debug-toolbar/)) +grants a developer detailed request-response cycle information while +developing a [Django](/django.html) web application. +The code for django-debug-toolbar is +[open source](https://github.com/jazzband/django-debug-toolbar/blob/master/LICENSE) +and maintained by the developer community group known as +[Jazzband](https://jazzband.co/). + +[**django-debug-toolbar / debug_toolbar / panels / settings.py**](https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/panels/settings.py) + +```python +# settings.py +from collections import OrderedDict + +import django +from django.conf import settings +from django.utils.translation import gettext_lazy as _ + +from debug_toolbar.panels import Panel + +if django.VERSION >= (3, 1): +~~ from django.views.debug import get_default_exception_reporter_filter + +~~ get_safe_settings = get_default_exception_reporter_filter().get_safe_settings +else: + from django.views.debug import get_safe_settings + + +class SettingsPanel(Panel): + + template = "debug_toolbar/panels/settings.html" + + nav_title = _("Settings") + + def title(self): + return _("Settings from %s") % settings.SETTINGS_MODULE + + def generate_stats(self, request, response): + self.record_stats( + { + "settings": OrderedDict( + sorted(get_safe_settings().items(), key=lambda s: s[0]) + ) + } + ) + + + +## ... source file continues with no further get_default_exception_reporter_filter examples... + +``` + diff --git a/content/pages/examples/django/django-views-decorators-csrf-csrf-exempt.markdown b/content/pages/examples/django/django-views-decorators-csrf-csrf-exempt.markdown new file mode 100644 index 000000000..3a0d4c446 --- /dev/null +++ b/content/pages/examples/django/django-views-decorators-csrf-csrf-exempt.markdown @@ -0,0 +1,123 @@ +title: django.views.decorators.csrf csrf_exempt Example Code +category: page +slug: django-views-decorators-csrf-csrf-exempt-examples +sortorder: 500011516 +toc: False +sidebartitle: django.views.decorators.csrf csrf_exempt +meta: Python example code for the csrf_exempt callable from the django.views.decorators.csrf module of the Django project. + + +csrf_exempt is a callable within the django.views.decorators.csrf module of the Django project. + + +## Example 1 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / viewsets.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./viewsets.py) + +```python +# viewsets.py +from collections import OrderedDict +from functools import update_wrapper +from inspect import getmembers + +from django.urls import NoReverseMatch +from django.utils.decorators import classonlymethod +~~from django.views.decorators.csrf import csrf_exempt + +from rest_framework import generics, mixins, views +from rest_framework.decorators import MethodMapper +from rest_framework.reverse import reverse + + +def _is_extra_action(attr): + return hasattr(attr, 'mapping') and isinstance(attr.mapping, MethodMapper) + + +class ViewSetMixin: + + @classonlymethod + def as_view(cls, actions=None, **initkwargs): + cls.name = None + cls.description = None + + cls.suffix = None + + cls.detail = None + + cls.basename = None + + if not actions: + + +## ... source file abbreviated to get to csrf_exempt examples ... + + + def view(request, *args, **kwargs): + self = cls(**initkwargs) + + if 'get' in actions and 'head' not in actions: + actions['head'] = actions['get'] + + self.action_map = actions + + for method, action in actions.items(): + handler = getattr(self, action) + setattr(self, method, handler) + + self.request = request + self.args = args + self.kwargs = kwargs + + return self.dispatch(request, *args, **kwargs) + + update_wrapper(view, cls, updated=()) + + update_wrapper(view, cls.dispatch, assigned=()) + + view.cls = cls + view.initkwargs = initkwargs + view.actions = actions +~~ return csrf_exempt(view) + + def initialize_request(self, request, *args, **kwargs): + request = super().initialize_request(request, *args, **kwargs) + method = request.method.lower() + if method == 'options': + self.action = 'metadata' + else: + self.action = self.action_map.get(method) + return request + + def reverse_action(self, url_name, *args, **kwargs): + url_name = '%s-%s' % (self.basename, url_name) + namespace = None + if self.request and self.request.resolver_match: + namespace = self.request.resolver_match.namespace + if namespace: + url_name = namespace + ':' + url_name + kwargs.setdefault('request', self.request) + + return reverse(url_name, *args, **kwargs) + + @classmethod + def get_extra_actions(cls): + return [method for _, method in getmembers(cls, _is_extra_action)] + + +## ... source file continues with no further csrf_exempt examples... + +``` + diff --git a/content/pages/examples/django/django-views-decorators-debug-sensitive-post-parameters.markdown b/content/pages/examples/django/django-views-decorators-debug-sensitive-post-parameters.markdown new file mode 100644 index 000000000..14a313c5d --- /dev/null +++ b/content/pages/examples/django/django-views-decorators-debug-sensitive-post-parameters.markdown @@ -0,0 +1,102 @@ +title: django.views.decorators.debug sensitive_post_parameters Example Code +category: page +slug: django-views-decorators-debug-sensitive-post-parameters-examples +sortorder: 500011517 +toc: False +sidebartitle: django.views.decorators.debug sensitive_post_parameters +meta: Python example code for the sensitive_post_parameters callable from the django.views.decorators.debug module of the Django project. + + +sensitive_post_parameters is a callable within the django.views.decorators.debug module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / views.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py) + +```python +# views.py +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.sites.shortcuts import get_current_site +from django.http import ( + Http404, + HttpResponsePermanentRedirect, + HttpResponseRedirect, +) +from django.shortcuts import redirect +from django.urls import reverse, reverse_lazy +from django.utils.decorators import method_decorator +~~from django.views.decorators.debug import sensitive_post_parameters +from django.views.generic.base import TemplateResponseMixin, TemplateView, View +from django.views.generic.edit import FormView + +from ..exceptions import ImmediateHttpResponse +from ..utils import get_form_class, get_request_param +from . import app_settings, signals +from .adapter import get_adapter +from .forms import ( + AddEmailForm, + ChangePasswordForm, + LoginForm, + ResetPasswordForm, + ResetPasswordKeyForm, + SetPasswordForm, + SignupForm, + UserTokenForm, +) +from .models import EmailAddress, EmailConfirmation, EmailConfirmationHMAC +from .utils import ( + complete_signup, + get_login_redirect_url, + get_next_redirect_url, + logout_on_password_change, + passthrough_next_redirect_url, + perform_login, + sync_user_email_addresses, + url_str_to_user_pk, +) + + +INTERNAL_RESET_URL_KEY = "set-password" +INTERNAL_RESET_SESSION_KEY = "_password_reset_key" + + +sensitive_post_parameters_m = method_decorator( +~~ sensitive_post_parameters( + 'oldpassword', 'password', 'password1', 'password2')) + + +def _ajax_response(request, response, form=None, data=None): + adapter = get_adapter(request) + if adapter.is_ajax(request): + if (isinstance(response, HttpResponseRedirect) or isinstance( + response, HttpResponsePermanentRedirect)): + redirect_to = response['Location'] + else: + redirect_to = None + response = adapter.ajax_response( + request, + response, + form=form, + data=data, + redirect_to=redirect_to) + return response + + +class RedirectAuthenticatedUserMixin(object): + + def dispatch(self, request, *args, **kwargs): + if request.user.is_authenticated and \ + + +## ... source file continues with no further sensitive_post_parameters examples... + +``` + diff --git a/content/pages/examples/django/django-views-decorators-http-require-get.markdown b/content/pages/examples/django/django-views-decorators-http-require-get.markdown new file mode 100644 index 000000000..5c2406f20 --- /dev/null +++ b/content/pages/examples/django/django-views-decorators-http-require-get.markdown @@ -0,0 +1,274 @@ +title: django.views.decorators.http require_GET Example Code +category: page +slug: django-views-decorators-http-require-get-examples +sortorder: 500011518 +toc: False +sidebartitle: django.views.decorators.http require_GET +meta: Python example code for the require_GET callable from the django.views.decorators.http module of the Django project. + + +require_GET is a callable within the django.views.decorators.http module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / submissions / views.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/submissions/views.py) + +```python +# views.py +import mimetypes + +from django.contrib import messages +from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth.decorators import login_required +from django.http import Http404, HttpResponse, HttpResponseForbidden, \ + HttpResponseRedirect, JsonResponse +from django.shortcuts import render, redirect, get_object_or_404 +~~from django.views.decorators.http import require_POST, require_GET + +from conferences.models import Conference +from conferences.utilities import validate_chair_access +from submissions.forms import CreateSubmissionForm, SubmissionDetailsForm, \ + AuthorCreateForm, AuthorsReorderForm, AuthorDeleteForm, \ + UploadReviewManuscriptForm, InviteAuthorForm, UploadAttachmentForm, \ + UpdateSubmissionStatusForm +from submissions.models import Submission, Author, Attachment +from submissions.utilities import is_authorized_edit, \ + is_authorized_view_attachment + + +def _create_submission(request, form): + if request.method == 'POST': + if form.is_valid(): + submission = form.save() + + submission.created_by = request.user + submission.save() + Author.objects.create( + submission=submission, + order=1, + user=request.user + ) + + +## ... source file abbreviated to get to require_GET examples ... + + + 'submission': submission, + 'form': form, + }) + return HttpResponseForbidden() + + +@login_required +@require_POST +def delete_manuscript(request, pk): + submission = get_object_or_404(Submission, pk=pk) + if submission.review_manuscript_editable_by(request.user): + file_name = submission.get_review_manuscript_name() + if submission.review_manuscript: + submission.review_manuscript.delete() + return render( + request, + 'submissions/components/file_deleted_message.html', { + 'alert_class': 'warning', + 'file_name': file_name, + }) + else: + return HttpResponseForbidden() + + +@login_required +~~@require_GET +def download_manuscript(request, pk): + submission = get_object_or_404(Submission, pk=pk) + if submission.is_manuscript_viewable_by(request.user): + if submission.review_manuscript: + filename = submission.get_review_manuscript_name() + mtype = mimetypes.guess_type(filename)[0] + response = HttpResponse( + submission.review_manuscript.file, + content_type=mtype + ) + response['Content-Disposition'] = f'filename={filename}' + return response + raise Http404 + return HttpResponseForbidden() + + +@login_required +def submission_overview(request, pk): + submission = get_object_or_404(Submission, pk=pk) + deadline = '' + + show_finish = not submission.reached_overview + if show_finish: + submission.reached_overview = True + + +## ... source file abbreviated to get to require_GET examples ... + + + submission = get_object_or_404(Submission, pk=pk) + if submission.authors_editable_by(request.user): + form = AuthorsReorderForm(submission, request.POST) + if form.is_valid(): + form.save() + return redirect('submissions:authors', pk=pk) + return HttpResponseForbidden() + + +@login_required +@require_POST +def send_invitation(request, pk): + submission = get_object_or_404(Submission, pk=pk) + if submission.authors_editable_by(request.user): + form = InviteAuthorForm(request.POST) + if form.is_valid(): + form.save(request, submission) + messages.success(request, _('Invitation sent')) + else: + messages.warning(request, _('Errors while sending invitation')) + return redirect('submissions:authors', pk=pk) + return HttpResponseForbidden() + + +@login_required +~~@require_GET +def camera_ready(request, pk): + submission = get_object_or_404(Submission, pk=pk) + if submission.status not in [Submission.ACCEPTED, Submission.IN_PRINT, + Submission.PUBLISHED]: + raise Http404 + return render(request, 'submissions/camera_ready.html', context={ + 'submission': submission, + 'editable': True, + }) + + +@login_required +~~@require_GET +def download_attachment(request, pk, att_pk): + submission = get_object_or_404(Submission, pk=pk) + attachment = Attachment.objects.get(pk=att_pk) + if not is_authorized_view_attachment(request.user, submission): + return HttpResponseForbidden() + if attachment.file: + filename = attachment.get_file_name() + mtype = mimetypes.guess_type(filename)[0] + response = HttpResponse(attachment.file.file, content_type=mtype) + response['Content-Disposition'] = f'filename={filename}' + return response + raise Http404 + + +@login_required +@require_POST +def upload_attachment(request, pk, att_pk): + submission = get_object_or_404(Submission, pk=pk) + attachment = get_object_or_404(Attachment, pk=att_pk) + if not is_authorized_edit(request.user, submission): + return HttpResponseForbidden() + form = UploadAttachmentForm( + request.POST, request.FILES, instance=attachment) + old_file = attachment.file.file if attachment.file else None + + +## ... source file continues with no further require_GET examples... + +``` + + +## Example 2 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / views.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./views.py) + +```python +# views.py +~~from django.views.decorators.http import require_POST, require_GET +from jet.forms import AddBookmarkForm, RemoveBookmarkForm, ToggleApplicationPinForm, ModelLookupForm +from jet.models import Bookmark +from jet.utils import JsonResponse + + +@require_POST +def add_bookmark_view(request): + result = {'error': False} + form = AddBookmarkForm(request, request.POST) + + if form.is_valid(): + bookmark = form.save() + result.update({ + 'id': bookmark.pk, + 'title': bookmark.title, + 'url': bookmark.url + }) + else: + result['error'] = True + + return JsonResponse(result) + + +@require_POST + + +## ... source file abbreviated to get to require_GET examples ... + + + + if form.is_valid(): + form.save() + else: + result['error'] = True + except Bookmark.DoesNotExist: + result['error'] = True + + return JsonResponse(result) + + +@require_POST +def toggle_application_pin_view(request): + result = {'error': False} + form = ToggleApplicationPinForm(request, request.POST) + + if form.is_valid(): + pinned = form.save() + result['pinned'] = pinned + else: + result['error'] = True + + return JsonResponse(result) + + +~~@require_GET +def model_lookup_view(request): + result = {'error': False} + + form = ModelLookupForm(request, request.GET) + + if form.is_valid(): + items, total = form.lookup() + result['items'] = items + result['total'] = total + else: + result['error'] = True + + return JsonResponse(result) + + + +## ... source file continues with no further require_GET examples... + +``` + diff --git a/content/pages/examples/django/django-views-decorators-http-require-post.markdown b/content/pages/examples/django/django-views-decorators-http-require-post.markdown new file mode 100644 index 000000000..1348baa8b --- /dev/null +++ b/content/pages/examples/django/django-views-decorators-http-require-post.markdown @@ -0,0 +1,303 @@ +title: django.views.decorators.http require_POST Example Code +category: page +slug: django-views-decorators-http-require-post-examples +sortorder: 500011519 +toc: False +sidebartitle: django.views.decorators.http require_POST +meta: Python example code for the require_POST callable from the django.views.decorators.http module of the Django project. + + +require_POST is a callable within the django.views.decorators.http module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / chair_mail / views.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/chair_mail/views.py) + +```python +# views.py +from django.contrib import messages +from django.http import JsonResponse, HttpResponse +from django.shortcuts import render, get_object_or_404, redirect +from django.template.loader import get_template +from django.urls import reverse +from django.utils import timezone +~~from django.views.decorators.http import require_GET, require_POST + +from conferences.utilities import validate_chair_access +from chair_mail.context import USER_VARS, CONFERENCE_VARS, SUBMISSION_VARS, \ + FRAME_VARS +from chair_mail.forms import EmailFrameUpdateForm, EmailFrameTestForm, \ + MessageForm, get_preview_form_class, EditNotificationForm, \ + UpdateNotificationStateForm +from chair_mail.mailing_lists import ALL_LISTS +from chair_mail.models import EmailSettings, EmailFrame, EmailMessage, \ + GroupMessage, MSG_TYPE_USER, MSG_TYPE_SUBMISSION, get_group_message_model, \ + get_message_leaf_model, SystemNotification, DEFAULT_NOTIFICATIONS_DATA +from chair_mail.utility import get_email_frame, get_email_frame_or_404, \ + reverse_preview_url, reverse_list_objects_url, get_object_name, \ + get_object_url +from conferences.models import Conference + + +def _get_grouped_vars(msg_type): + if msg_type == MSG_TYPE_USER: + return ( + ('Conference variables', CONFERENCE_VARS), + ('User variables', USER_VARS) + ) + elif msg_type == MSG_TYPE_SUBMISSION: + return ( + ('Conference variables', CONFERENCE_VARS), + ('User variables', USER_VARS), + ('Submission variables', SUBMISSION_VARS), + ) + raise ValueError(f'unrecognized message type "{msg_type}"') + + +@require_GET +def overview(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + frame = get_email_frame(conference) + return render(request, 'chair_mail/tab_pages/overview.html', context={ + 'conference': conference, + 'frame': frame, + 'active_tab': 'overview', + }) + + +~~@require_POST +def create_frame(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + if not hasattr(conference, 'email_settings'): + EmailSettings.objects.create(conference=conference) + email_settings = conference.email_settings + frame = email_settings.frame + template_html = get_template( + 'chair_mail/email/default_frame_html.html').template + template_plain = get_template( + 'chair_mail/email/default_frame_plain.txt').template + if frame: + frame.text_html = template_html.source + frame.text_plain = template_plain.source + frame.created_at = timezone.now() + frame.updated_at = timezone.now() + frame.created_by = request.user + frame.save() + messages.success(request, 'Reset existing frame') + else: + frame = EmailFrame.objects.create( + conference=conference, + created_by=request.user, + text_plain=template_plain.source, + + +## ... source file abbreviated to get to require_POST examples ... + + + form = EmailFrameUpdateForm(instance=frame) + + return render(request, 'chair_mail/tab_pages/frame_details.html', context={ + 'conference': conference, + 'frame': frame, + 'active_tab': 'frame', + 'form': form, + 'variables': FRAME_VARS, + }) + + +@require_GET +def sent_messages(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + frame = get_email_frame(conference) + msg_list = conference.sent_group_emails.all().order_by('-sent_at') + return render(request, 'chair_mail/tab_pages/messages.html', context={ + 'conference': conference, + 'active_tab': 'messages', + 'frame': frame, + 'msg_list': msg_list, + }) + + +~~@require_POST +def send_frame_test_message(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + form = EmailFrameTestForm(request.POST) + if form.is_valid(): + form.send_message(request.user, conference) + return JsonResponse({'email': request.user.email}) + resp = JsonResponse({'email': request.user.email}) + resp.status_code = 400 + return resp + + +@require_GET +def group_message_details(request, conf_pk, msg_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + msg = get_object_or_404(GroupMessage, pk=msg_pk) + leaf_msg = get_message_leaf_model(msg) + recipients = [{ + 'name': get_object_name(leaf_msg.message_type, obj), + 'url': get_object_url(leaf_msg.message_type, conference, obj), + } for obj in leaf_msg.recipients.all()] + + if request.is_ajax(): + + +## ... source file abbreviated to get to require_POST examples ... + + + 'sent_at': msg.sent_at, + 'sent_by': msg.sent_by.pk if msg.sent_by else '', + 'user_to': msg.user_to.pk, + }) + next_url = request.GET.get('next', default='') + return render( + request, 'chair_mail/preview_pages/email_message_preview.html', + context={ + 'conference': conference, + 'msg': msg, + 'next': next_url, + }) + + +def help_compose(request): + return render(request, 'chair_mail/compose/help.html', context={ + 'variables': ( + ('User variables', USER_VARS), + ('Submission variables', SUBMISSION_VARS), + ('Conference variables', CONFERENCE_VARS), + ), + 'mailing_lists': ALL_LISTS, + }) + + +~~@require_POST +def delete_all_messages(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + num_group_messages = GroupMessage.objects.count() + num_email_messages = EmailMessage.objects.count() + GroupMessage.objects.all().delete() + EmailMessage.objects.all().delete() + messages.success( + request, f'Deleted {num_group_messages} group messages and ' + f'{num_email_messages} messages instances' + ) + return redirect('chair_mail:sent-messages', conf_pk=conf_pk) + + +@require_GET +def render_frame_preview(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + frame = get_email_frame(conference) + if frame: + body = f"

    Dear {request.user.profile.get_full_name()},

    " \ + f"

    this is a frame preview.

    " + subject = 'Frame preview' + html = frame.render_html(subject, body) + return HttpResponse(html) + return HttpResponse() + + +@require_GET +def notifications_list(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + return render(request, 'chair_mail/tab_pages/notifications.html', context={ + 'conference': conference, + 'frame': get_email_frame(conference), + 'active_tab': 'notifications', + }) + + +~~@require_POST +def reset_all_notifications(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + conference.notifications.all().delete() + for name, kwargs in DEFAULT_NOTIFICATIONS_DATA.items(): + SystemNotification.objects.create(name=name, conference=conference, + **kwargs) + return redirect('chair_mail:notifications', conf_pk) + + +~~@require_POST +def refresh_notifications(request, conf_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + for name, kwargs in DEFAULT_NOTIFICATIONS_DATA.items(): + notif = SystemNotification.objects.filter( + name=name, conference=conference).first() + if not notif: + SystemNotification.objects.create( + name=name, conference=conference, **kwargs) + return redirect('chair_mail:notifications', conf_pk) + + +~~@require_POST +def reset_notification(request, conf_pk, notif_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + notification = get_object_or_404(SystemNotification, pk=notif_pk) + data = DEFAULT_NOTIFICATIONS_DATA[notification.name] + notification.subject = data['subject'] + notification.type = data['type'] + notification.body = data['body'] + notification.save() + return redirect('chair_mail:notifications', conf_pk) + + +def notification_details(request, conf_pk, notif_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + notification = get_object_or_404(SystemNotification, pk=notif_pk) + if request.method == 'POST': + notif_form = EditNotificationForm(request.POST, instance=notification) + if notif_form.is_valid(): + notif_form.save() + messages.success(request, 'Your changes were saved') + return redirect( + 'chair_mail:notification-details', conf_pk, notif_pk) + else: + notif_form = EditNotificationForm(instance=notification) + + return render( + request, 'chair_mail/tab_pages/notification_details.html', context={ + 'conference': conference, + 'notification': notification, + 'hide_tabs': True, + 'notif_form': notif_form, + 'variables': _get_grouped_vars(notification.type), + 'preview_url': reverse_preview_url(notification.type, conference), + 'preview_form': get_preview_form_class(notification.type)(), + 'list_objects_url': + reverse_list_objects_url(notification.type, conference), + }) + + +~~@require_POST +def update_notification_state(request, conf_pk, notif_pk): + conference = get_object_or_404(Conference, pk=conf_pk) + validate_chair_access(request.user, conference) + notification = get_object_or_404(SystemNotification, pk=notif_pk) + form = UpdateNotificationStateForm(request.POST, instance=notification) + if form.is_valid(): + form.save() + return redirect('chair_mail:notifications', conf_pk) + + + +## ... source file continues with no further require_POST examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-base-redirectview.markdown b/content/pages/examples/django/django-views-generic-base-redirectview.markdown new file mode 100644 index 000000000..ff13471ea --- /dev/null +++ b/content/pages/examples/django/django-views-generic-base-redirectview.markdown @@ -0,0 +1,89 @@ +title: django.views.generic.base RedirectView Example Code +category: page +slug: django-views-generic-base-redirectview-examples +sortorder: 500011529 +toc: False +sidebartitle: django.views.generic.base RedirectView +meta: Python example code for the RedirectView class from the django.views.generic.base module of the Django project. + + +RedirectView is a class within the django.views.generic.base module of the Django project. + + +## Example 1 from django-oscar +[django-oscar](https://github.com/django-oscar/django-oscar/) +([project website](http://oscarcommerce.com/)) +is a framework for building e-commerce sites on top of +[Django](/django.html). The code for the project is available open +source under a +[custom license written by Tangent Communications PLC](https://github.com/django-oscar/django-oscar/blob/master/LICENSE). + +[**django-oscar / src / oscar / config.py**](https://github.com/django-oscar/django-oscar/blob/master/src/oscar/config.py) + +```python +# config.py + +from django.apps import apps +from django.conf import settings +from django.conf.urls import url +from django.urls import reverse_lazy +~~from django.views.generic.base import RedirectView + +from oscar.core.application import OscarConfig +from oscar.core.loading import get_class + + +class Shop(OscarConfig): + name = 'oscar' + + def ready(self): + from django.contrib.auth.forms import SetPasswordForm + + self.catalogue_app = apps.get_app_config('catalogue') + self.customer_app = apps.get_app_config('customer') + self.basket_app = apps.get_app_config('basket') + self.checkout_app = apps.get_app_config('checkout') + self.search_app = apps.get_app_config('search') + self.dashboard_app = apps.get_app_config('dashboard') + self.offer_app = apps.get_app_config('offer') + + self.password_reset_form = get_class('customer.forms', 'PasswordResetForm') + self.set_password_form = SetPasswordForm + + def get_urls(self): + from django.contrib.auth import views as auth_views + + from oscar.views.decorators import login_forbidden + + urls = [ +~~ url(r'^$', RedirectView.as_view(url=settings.OSCAR_HOMEPAGE), name='home'), + url(r'^catalogue/', self.catalogue_app.urls), + url(r'^basket/', self.basket_app.urls), + url(r'^checkout/', self.checkout_app.urls), + url(r'^accounts/', self.customer_app.urls), + url(r'^search/', self.search_app.urls), + url(r'^dashboard/', self.dashboard_app.urls), + url(r'^offers/', self.offer_app.urls), + + url(r'^password-reset/$', + login_forbidden( + auth_views.PasswordResetView.as_view( + form_class=self.password_reset_form, + success_url=reverse_lazy('password-reset-done'), + template_name='oscar/registration/password_reset_form.html' + ) + ), + name='password-reset'), + url(r'^password-reset/done/$', + login_forbidden(auth_views.PasswordResetDoneView.as_view( + template_name='oscar/registration/password_reset_done.html' + )), + name='password-reset-done'), + url(r'^password-reset/confirm/(?P[0-9A-Za-z_\-]+)/(?P.+)/$', + login_forbidden( + + +## ... source file continues with no further RedirectView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-base-templateresponsemixin.markdown b/content/pages/examples/django/django-views-generic-base-templateresponsemixin.markdown new file mode 100644 index 000000000..f7805b63f --- /dev/null +++ b/content/pages/examples/django/django-views-generic-base-templateresponsemixin.markdown @@ -0,0 +1,238 @@ +title: django.views.generic.base TemplateResponseMixin Example Code +category: page +slug: django-views-generic-base-templateresponsemixin-examples +sortorder: 500011530 +toc: False +sidebartitle: django.views.generic.base TemplateResponseMixin +meta: Python example code for the TemplateResponseMixin class from the django.views.generic.base module of the Django project. + + +TemplateResponseMixin is a class within the django.views.generic.base module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / views.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py) + +```python +# views.py +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.sites.shortcuts import get_current_site +from django.http import ( + Http404, + HttpResponsePermanentRedirect, + HttpResponseRedirect, +) +from django.shortcuts import redirect +from django.urls import reverse, reverse_lazy +from django.utils.decorators import method_decorator +from django.views.decorators.debug import sensitive_post_parameters +~~from django.views.generic.base import TemplateResponseMixin, TemplateView, View +from django.views.generic.edit import FormView + +from ..exceptions import ImmediateHttpResponse +from ..utils import get_form_class, get_request_param +from . import app_settings, signals +from .adapter import get_adapter +from .forms import ( + AddEmailForm, + ChangePasswordForm, + LoginForm, + ResetPasswordForm, + ResetPasswordKeyForm, + SetPasswordForm, + SignupForm, + UserTokenForm, +) +from .models import EmailAddress, EmailConfirmation, EmailConfirmationHMAC +from .utils import ( + complete_signup, + get_login_redirect_url, + get_next_redirect_url, + logout_on_password_change, + passthrough_next_redirect_url, + perform_login, + + +## ... source file abbreviated to get to TemplateResponseMixin examples ... + + + def get_context_data(self, **kwargs): + ret = super(SignupView, self).get_context_data(**kwargs) + form = ret['form'] + email = self.request.session.get('account_verified_email') + if email: + email_keys = ['email'] + if app_settings.SIGNUP_EMAIL_ENTER_TWICE: + email_keys.append('email2') + for email_key in email_keys: + form.fields[email_key].initial = email + login_url = passthrough_next_redirect_url(self.request, + reverse("account_login"), + self.redirect_field_name) + redirect_field_name = self.redirect_field_name + redirect_field_value = get_request_param(self.request, + redirect_field_name) + ret.update({"login_url": login_url, + "redirect_field_name": redirect_field_name, + "redirect_field_value": redirect_field_value}) + return ret + + +signup = SignupView.as_view() + + +~~class ConfirmEmailView(TemplateResponseMixin, View): + + template_name = "account/email_confirm." + app_settings.TEMPLATE_EXTENSION + + def get(self, *args, **kwargs): + try: + self.object = self.get_object() + if app_settings.CONFIRM_EMAIL_ON_GET: + return self.post(*args, **kwargs) + except Http404: + self.object = None + ctx = self.get_context_data() + return self.render_to_response(ctx) + + def post(self, *args, **kwargs): + self.object = confirmation = self.get_object() + confirmation.confirm(self.request) + get_adapter(self.request).add_message( + self.request, + messages.SUCCESS, + 'account/messages/email_confirmed.txt', + {'email': confirmation.email_address.email}) + if app_settings.LOGIN_ON_EMAIL_CONFIRMATION: + resp = self.login_on_confirm(confirmation) + if resp is not None: + + +## ... source file abbreviated to get to TemplateResponseMixin examples ... + + + 'account/messages/password_changed.txt') + signals.password_reset.send(sender=self.reset_user.__class__, + request=self.request, + user=self.reset_user) + + if app_settings.LOGIN_ON_PASSWORD_RESET: + return perform_login( + self.request, self.reset_user, + email_verification=app_settings.EMAIL_VERIFICATION) + + return super(PasswordResetFromKeyView, self).form_valid(form) + + +password_reset_from_key = PasswordResetFromKeyView.as_view() + + +class PasswordResetFromKeyDoneView(TemplateView): + template_name = ( + "account/password_reset_from_key_done." + + app_settings.TEMPLATE_EXTENSION) + + +password_reset_from_key_done = PasswordResetFromKeyDoneView.as_view() + + +~~class LogoutView(TemplateResponseMixin, View): + + template_name = "account/logout." + app_settings.TEMPLATE_EXTENSION + redirect_field_name = "next" + + def get(self, *args, **kwargs): + if app_settings.LOGOUT_ON_GET: + return self.post(*args, **kwargs) + if not self.request.user.is_authenticated: + response = redirect(self.get_redirect_url()) + return _ajax_response(self.request, response) + ctx = self.get_context_data() + response = self.render_to_response(ctx) + return _ajax_response(self.request, response) + + def post(self, *args, **kwargs): + url = self.get_redirect_url() + if self.request.user.is_authenticated: + self.logout() + response = redirect(url) + return _ajax_response(self.request, response) + + def logout(self): + adapter = get_adapter(self.request) + adapter.add_message( + + +## ... source file continues with no further TemplateResponseMixin examples... + +``` + + +## Example 2 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / mixins.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/mixins.py) + +```python +# mixins.py +import logging + +~~from django.views.generic.base import TemplateResponseMixin +from wiki.conf import settings +from wiki.core.plugins import registry + +log = logging.getLogger(__name__) + + +~~class ArticleMixin(TemplateResponseMixin): + + + def dispatch(self, request, article, *args, **kwargs): + self.urlpath = kwargs.pop("urlpath", None) + self.article = article + self.children_slice = [] + if settings.SHOW_MAX_CHILDREN > 0: + try: + for child in self.article.get_children( + max_num=settings.SHOW_MAX_CHILDREN + 1, + articles__article__current_revision__deleted=False, + user_can_read=request.user, + ): + self.children_slice.append(child) + except AttributeError as e: + log.error( + "Attribute error most likely caused by wrong MPTT version. Use 0.5.3+.\n\n" + + str(e) + ) + raise + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + kwargs["urlpath"] = self.urlpath + + +## ... source file continues with no further TemplateResponseMixin examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-base-templateview.markdown b/content/pages/examples/django/django-views-generic-base-templateview.markdown new file mode 100644 index 000000000..7028e0f30 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-base-templateview.markdown @@ -0,0 +1,174 @@ +title: django.views.generic.base TemplateView Example Code +category: page +slug: django-views-generic-base-templateview-examples +sortorder: 500011531 +toc: False +sidebartitle: django.views.generic.base TemplateView +meta: Python example code for the TemplateView class from the django.views.generic.base module of the Django project. + + +TemplateView is a class within the django.views.generic.base module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / socialaccount / views.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/views.py) + +```python +# views.py +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.sites.shortcuts import get_current_site +from django.http import HttpResponseRedirect +from django.urls import reverse, reverse_lazy +~~from django.views.generic.base import TemplateView +from django.views.generic.edit import FormView + +from ..account import app_settings as account_settings +from ..account.adapter import get_adapter as get_account_adapter +from ..account.views import ( + AjaxCapableProcessFormViewMixin, + CloseableSignupMixin, + RedirectAuthenticatedUserMixin, +) +from ..utils import get_form_class +from . import app_settings, helpers +from .adapter import get_adapter +from .forms import DisconnectForm, SignupForm +from .models import SocialAccount, SocialLogin + + +class SignupView(RedirectAuthenticatedUserMixin, CloseableSignupMixin, + AjaxCapableProcessFormViewMixin, FormView): + form_class = SignupForm + template_name = ( + 'socialaccount/signup.' + account_settings.TEMPLATE_EXTENSION) + + def get_form_class(self): + return get_form_class(app_settings.FORMS, + + +## ... source file abbreviated to get to TemplateView examples ... + + + + def get_form_kwargs(self): + ret = super(SignupView, self).get_form_kwargs() + ret['sociallogin'] = self.sociallogin + return ret + + def form_valid(self, form): + self.request.session.pop('socialaccount_sociallogin', None) + form.save(self.request) + return helpers.complete_social_signup(self.request, + self.sociallogin) + + def get_context_data(self, **kwargs): + ret = super(SignupView, self).get_context_data(**kwargs) + ret.update(dict(site=get_current_site(self.request), + account=self.sociallogin.account)) + return ret + + def get_authenticated_redirect_url(self): + return reverse(connections) + + +signup = SignupView.as_view() + + +~~class LoginCancelledView(TemplateView): + template_name = ( + "socialaccount/login_cancelled." + account_settings.TEMPLATE_EXTENSION) + + +login_cancelled = LoginCancelledView.as_view() + + +~~class LoginErrorView(TemplateView): + template_name = ( + "socialaccount/authentication_error." + + account_settings.TEMPLATE_EXTENSION) + + +login_error = LoginErrorView.as_view() + + +class ConnectionsView(AjaxCapableProcessFormViewMixin, FormView): + template_name = ( + "socialaccount/connections." + + account_settings.TEMPLATE_EXTENSION) + form_class = DisconnectForm + success_url = reverse_lazy("socialaccount_connections") + + def get_form_class(self): + return get_form_class(app_settings.FORMS, + 'disconnect', + self.form_class) + + def get_form_kwargs(self): + kwargs = super(ConnectionsView, self).get_form_kwargs() + kwargs["request"] = self.request + return kwargs + + +## ... source file continues with no further TemplateView examples... + +``` + + +## Example 2 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / deleted_list.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/deleted_list.py) + +```python +# deleted_list.py +from django.shortcuts import redirect +~~from django.views.generic.base import TemplateView +from wiki import models + + +~~class DeletedListView(TemplateView): + + template_name = "wiki/deleted_list.html" + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_superuser: + return redirect("wiki:root") + + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + article_list = models.Article.objects.all() + deleted_articles = [] + for article in article_list: + if article.current_revision.deleted: + deleted_articles.append(article) + kwargs["deleted_articles"] = deleted_articles + return super().get_context_data(**kwargs) + + + +## ... source file continues with no further TemplateView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-base-view.markdown b/content/pages/examples/django/django-views-generic-base-view.markdown new file mode 100644 index 000000000..f21476c33 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-base-view.markdown @@ -0,0 +1,524 @@ +title: django.views.generic.base View Example Code +category: page +slug: django-views-generic-base-view-examples +sortorder: 500011532 +toc: False +sidebartitle: django.views.generic.base View +meta: Python example code for the View class from the django.views.generic.base module of the Django project. + + +View is a class within the django.views.generic.base module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / account / views.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py) + +```python +# views.py +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.sites.shortcuts import get_current_site +from django.http import ( + Http404, + HttpResponsePermanentRedirect, + HttpResponseRedirect, +) +from django.shortcuts import redirect +from django.urls import reverse, reverse_lazy +from django.utils.decorators import method_decorator +from django.views.decorators.debug import sensitive_post_parameters +~~from django.views.generic.base import TemplateResponseMixin, TemplateView, View +from django.views.generic.edit import FormView + +from ..exceptions import ImmediateHttpResponse +from ..utils import get_form_class, get_request_param +from . import app_settings, signals +from .adapter import get_adapter +from .forms import ( + AddEmailForm, + ChangePasswordForm, + LoginForm, + ResetPasswordForm, + ResetPasswordKeyForm, + SetPasswordForm, + SignupForm, + UserTokenForm, +) +from .models import EmailAddress, EmailConfirmation, EmailConfirmationHMAC +from .utils import ( + complete_signup, + get_login_redirect_url, + get_next_redirect_url, + logout_on_password_change, + passthrough_next_redirect_url, + perform_login, + + +## ... source file abbreviated to get to View examples ... + + + def get_context_data(self, **kwargs): + ret = super(SignupView, self).get_context_data(**kwargs) + form = ret['form'] + email = self.request.session.get('account_verified_email') + if email: + email_keys = ['email'] + if app_settings.SIGNUP_EMAIL_ENTER_TWICE: + email_keys.append('email2') + for email_key in email_keys: + form.fields[email_key].initial = email + login_url = passthrough_next_redirect_url(self.request, + reverse("account_login"), + self.redirect_field_name) + redirect_field_name = self.redirect_field_name + redirect_field_value = get_request_param(self.request, + redirect_field_name) + ret.update({"login_url": login_url, + "redirect_field_name": redirect_field_name, + "redirect_field_value": redirect_field_value}) + return ret + + +signup = SignupView.as_view() + + +~~class ConfirmEmailView(TemplateResponseMixin, View): + + template_name = "account/email_confirm." + app_settings.TEMPLATE_EXTENSION + + def get(self, *args, **kwargs): + try: + self.object = self.get_object() + if app_settings.CONFIRM_EMAIL_ON_GET: + return self.post(*args, **kwargs) + except Http404: + self.object = None + ctx = self.get_context_data() + return self.render_to_response(ctx) + + def post(self, *args, **kwargs): + self.object = confirmation = self.get_object() + confirmation.confirm(self.request) + get_adapter(self.request).add_message( + self.request, + messages.SUCCESS, + 'account/messages/email_confirmed.txt', + {'email': confirmation.email_address.email}) + if app_settings.LOGIN_ON_EMAIL_CONFIRMATION: + resp = self.login_on_confirm(confirmation) + if resp is not None: + + +## ... source file abbreviated to get to View examples ... + + + 'account/messages/password_changed.txt') + signals.password_reset.send(sender=self.reset_user.__class__, + request=self.request, + user=self.reset_user) + + if app_settings.LOGIN_ON_PASSWORD_RESET: + return perform_login( + self.request, self.reset_user, + email_verification=app_settings.EMAIL_VERIFICATION) + + return super(PasswordResetFromKeyView, self).form_valid(form) + + +password_reset_from_key = PasswordResetFromKeyView.as_view() + + +class PasswordResetFromKeyDoneView(TemplateView): + template_name = ( + "account/password_reset_from_key_done." + + app_settings.TEMPLATE_EXTENSION) + + +password_reset_from_key_done = PasswordResetFromKeyDoneView.as_view() + + +~~class LogoutView(TemplateResponseMixin, View): + + template_name = "account/logout." + app_settings.TEMPLATE_EXTENSION + redirect_field_name = "next" + + def get(self, *args, **kwargs): + if app_settings.LOGOUT_ON_GET: + return self.post(*args, **kwargs) + if not self.request.user.is_authenticated: + response = redirect(self.get_redirect_url()) + return _ajax_response(self.request, response) + ctx = self.get_context_data() + response = self.render_to_response(ctx) + return _ajax_response(self.request, response) + + def post(self, *args, **kwargs): + url = self.get_redirect_url() + if self.request.user.is_authenticated: + self.logout() + response = redirect(url) + return _ajax_response(self.request, response) + + def logout(self): + adapter = get_adapter(self.request) + adapter.add_message( + + +## ... source file continues with no further View examples... + +``` + + +## Example 2 from django-downloadview +[django-downloadview](https://github.com/benoitbryon/django-downloadview) +([project documentation](https://django-downloadview.readthedocs.io/en/1.9/) +and +[PyPI package information](https://pypi.org/project/django-downloadview/)) +is a [Django](/django.html) extension for serving downloads through your +web application. While typically you would use a web server to handle +[static content](/static-content.html), sometimes you need to control +file access, such as requiring a user to register before downloading a +PDF. In that situations, django-downloadview is a handy library to avoid +boilerplate code for common scenarios. + +[**django-downloadview / django_downloadview / views / base.py**](https://github.com/benoitbryon/django-downloadview/blob/master/django_downloadview/views/base.py) + +```python +# base.py +import calendar + +from django.http import Http404, HttpResponseNotModified +~~from django.views.generic.base import View +from django.views.static import was_modified_since + +from django_downloadview import exceptions +from django_downloadview.response import DownloadResponse + + +class DownloadMixin(object): + + response_class = DownloadResponse + + attachment = True + + basename = None + + mimetype = None + + encoding = None + + def get_file(self): + raise NotImplementedError() + + def get_basename(self): + return self.basename + + + +## ... source file abbreviated to get to View examples ... + + + + def download_response(self, *response_args, **response_kwargs): + response_kwargs.setdefault("file_instance", self.file_instance) + response_kwargs.setdefault("attachment", self.attachment) + response_kwargs.setdefault("basename", self.get_basename()) + response_kwargs.setdefault("file_mimetype", self.get_mimetype()) + response_kwargs.setdefault("file_encoding", self.get_encoding()) + response = self.response_class(*response_args, **response_kwargs) + return response + + def file_not_found_response(self): + raise Http404() + + def render_to_response(self, *response_args, **response_kwargs): + try: + self.file_instance = self.get_file() + except exceptions.FileNotFound: + return self.file_not_found_response() + since = self.request.META.get("HTTP_IF_MODIFIED_SINCE", None) + if since is not None: + if not self.was_modified_since(self.file_instance, since): + return self.not_modified_response(**response_kwargs) + return self.download_response(*response_args, **response_kwargs) + + +~~class BaseDownloadView(DownloadMixin, View): + + def get(self, request, *args, **kwargs): + return self.render_to_response() + + + +## ... source file continues with no further View examples... + +``` + + +## Example 3 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / views.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./views.py) + +```python +# views.py +import re +import six +from collections import Counter + +try: + from django.urls import reverse_lazy +except ImportError: + from django.core.urlresolvers import reverse_lazy + +import django +from django.db import DatabaseError +from django.db.models import Count +from django.forms.models import model_to_dict +from django.http import HttpResponse, JsonResponse, HttpResponseRedirect, Http404 +from django.shortcuts import get_object_or_404, render +from django.views.decorators.http import require_POST +from django.utils.decorators import method_decorator +from django.views.generic import ListView +~~from django.views.generic.base import View +from django.views.generic.edit import CreateView, DeleteView +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.core.exceptions import ImproperlyConfigured +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.auth.views import LoginView + +from explorer import app_settings +from explorer.connections import connections +from explorer.exporters import get_exporter_class +from explorer.forms import QueryForm +from explorer.models import Query, QueryLog, MSG_FAILED_BLACKLIST +from explorer.tasks import execute_query +from explorer.utils import ( + url_get_rows, + url_get_query_id, + url_get_log_id, + url_get_params, + safe_login_prompt, + fmt_sql, + allowed_query_pks, + url_get_show, + url_get_fullscreen +) + + + +## ... source file abbreviated to get to View examples ... + + + + +class SafeLoginView(LoginView): + template_name = 'admin/login.html' + + +def _export(request, query, download=True): + format = request.GET.get('format', 'csv') + exporter_class = get_exporter_class(format) + query.params = url_get_params(request) + delim = request.GET.get('delim') + exporter = exporter_class(query) + try: + output = exporter.get_output(delim=delim) + except DatabaseError as e: + msg = "Error executing query %s: %s" % (query.title, e) + return HttpResponse(msg, status=500) + response = HttpResponse(output, content_type=exporter.content_type) + if download: + response['Content-Disposition'] = 'attachment; filename="%s"' % ( + exporter.get_filename() + ) + return response + + +~~class DownloadQueryView(PermissionRequiredMixin, View): + + permission_required = 'view_permission' + + def get(self, request, query_id, *args, **kwargs): + query = get_object_or_404(Query, pk=query_id) + return _export(request, query) + + +~~class DownloadFromSqlView(PermissionRequiredMixin, View): + + permission_required = 'view_permission' + + def post(self, request, *args, **kwargs): + sql = request.POST.get('sql') + connection = request.POST.get('connection') + query = Query(sql=sql, connection=connection, title='') + ql = query.log(request.user) + query.title = 'Playground - %s' % ql.id + return _export(request, query) + + +~~class StreamQueryView(PermissionRequiredMixin, View): + + permission_required = 'view_permission' + + def get(self, request, query_id, *args, **kwargs): + query = get_object_or_404(Query, pk=query_id) + return _export(request, query, download=False) + + +~~class EmailCsvQueryView(PermissionRequiredMixin, View): + + permission_required = 'view_permission' + + def post(self, request, query_id, *args, **kwargs): + if request.is_ajax(): + email = request.POST.get('email', None) + if email: + execute_query.delay(query_id, email) + return JsonResponse({'message': 'message was sent successfully'}) + return JsonResponse({}, status=403) + + +~~class SchemaView(PermissionRequiredMixin, View): + permission_required = 'change_permission' + + @method_decorator(xframe_options_sameorigin) + def dispatch(self, *args, **kwargs): + return super(SchemaView, self).dispatch(*args, **kwargs) + + def get(self, request, *args, **kwargs): + connection = kwargs.get('connection') + if connection not in connections: + raise Http404 + schema = schema_info(connection) + if schema: + return render(None, 'explorer/schema.html', + {'schema': schema_info(connection)}) + else: + return render(None, 'explorer/schema_building.html') + + +@require_POST +def format_sql(request): + sql = request.POST.get('sql', '') + formatted = fmt_sql(sql) + return JsonResponse({"formatted": formatted}) + + + +## ... source file abbreviated to get to View examples ... + + + + context_object_name = "recent_logs" + model = QueryLog + paginate_by = 20 + + +class CreateQueryView(PermissionRequiredMixin, ExplorerContextMixin, CreateView): + + permission_required = 'change_permission' + + def form_valid(self, form): + form.instance.created_by_user = self.request.user + return super(CreateQueryView, self).form_valid(form) + + form_class = QueryForm + template_name = 'explorer/query.html' + + +class DeleteQueryView(PermissionRequiredMixin, ExplorerContextMixin, DeleteView): + + permission_required = 'change_permission' + model = Query + success_url = reverse_lazy("explorer_index") + + +~~class PlayQueryView(PermissionRequiredMixin, ExplorerContextMixin, View): + + permission_required = 'change_permission' + + def get(self, request): + if url_get_query_id(request): + query = get_object_or_404(Query, pk=url_get_query_id(request)) + return self.render_with_sql(request, query, run_query=False) + + if url_get_log_id(request): + log = get_object_or_404(QueryLog, pk=url_get_log_id(request)) + query = Query(sql=log.sql, title="Playground", connection=log.connection) + return self.render_with_sql(request, query) + + return self.render() + + def post(self, request): + sql = request.POST.get('sql') + show = url_get_show(request) + query = Query(sql=sql, title="Playground", connection=request.POST.get('connection')) + passes_blacklist, failing_words = query.passes_blacklist() + error = MSG_FAILED_BLACKLIST % ', '.join(failing_words) if not passes_blacklist else None + run_query = not bool(error) if show else False + return self.render_with_sql(request, query, run_query=run_query, error=error) + + def render(self): + return self.render_template('explorer/play.html', {'title': 'Playground', 'form': QueryForm()}) + + def render_with_sql(self, request, query, run_query=True, error=None): + rows = url_get_rows(request) + fullscreen = url_get_fullscreen(request) + template = 'fullscreen' if fullscreen else 'play' + form = QueryForm(request.POST if len(request.POST) else None, instance=query) + return self.render_template('explorer/%s.html' % template, query_viewmodel(request.user, + query, + title="Playground", + run_query=run_query, + error=error, + rows=rows, + form=form)) + + +~~class QueryView(PermissionRequiredMixin, ExplorerContextMixin, View): + + permission_required = 'view_permission' + + def get(self, request, query_id): + query, form = QueryView.get_instance_and_form(request, query_id) + query.save() # updates the modified date + show = url_get_show(request) + rows = url_get_rows(request) + vm = query_viewmodel(request.user, query, form=form, run_query=show, rows=rows) + fullscreen = url_get_fullscreen(request) + template = 'fullscreen' if fullscreen else 'query' + return self.render_template('explorer/%s.html' % template, vm) + + def post(self, request, query_id): + if not app_settings.EXPLORER_PERMISSION_CHANGE(request.user): + return HttpResponseRedirect( + reverse_lazy('query_detail', kwargs={'query_id': query_id}) + ) + show = url_get_show(request) + query, form = QueryView.get_instance_and_form(request, query_id) + success = form.is_valid() and form.save() + vm = query_viewmodel(request.user, + query, + form=form, + + +## ... source file continues with no further View examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-createview.markdown b/content/pages/examples/django/django-views-generic-createview.markdown new file mode 100644 index 000000000..5f01cf427 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-createview.markdown @@ -0,0 +1,84 @@ +title: django.views.generic CreateView Example Code +category: page +slug: django-views-generic-createview-examples +sortorder: 500011520 +toc: False +sidebartitle: django.views.generic CreateView +meta: Python example code for the CreateView class from the django.views.generic module of the Django project. + + +CreateView is a class within the django.views.generic module of the Django project. + + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / accounts.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/accounts.py) + +```python +# accounts.py +from django.conf import settings as django_settings +from django.contrib import messages +from django.contrib.auth import get_user_model +from django.contrib.auth import login as auth_login +from django.contrib.auth import logout as auth_logout +from django.contrib.auth.forms import AuthenticationForm +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.shortcuts import render +from django.urls import reverse +from django.utils.translation import gettext as _ +~~from django.views.generic import CreateView +from django.views.generic import FormView +from django.views.generic import UpdateView +from django.views.generic import View +from wiki import forms +from wiki.conf import settings + +User = get_user_model() + + +~~class Signup(CreateView): + model = User + form_class = forms.UserCreationForm + template_name = "wiki/accounts/signup.html" + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_anonymous and not request.user.is_superuser: + return redirect("wiki:root") + if not settings.ACCOUNT_HANDLING: + return redirect(settings.SIGNUP_URL) + if not request.user.is_superuser and not settings.ACCOUNT_SIGNUP_ALLOWED: + c = {"error_msg": _("Account signup is only allowed for administrators.")} + return render(request, "wiki/error.html", context=c) + + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["honeypot_class"] = context["form"].honeypot_class + context["honeypot_jsfunction"] = context["form"].honeypot_jsfunction + return context + + def get_success_url(self, *args): + messages.success( + self.request, _("You are now signed up... and now you can sign in!") + + +## ... source file continues with no further CreateView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-deleteview.markdown b/content/pages/examples/django/django-views-generic-deleteview.markdown new file mode 100644 index 000000000..5a7b82314 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-deleteview.markdown @@ -0,0 +1,61 @@ +title: django.views.generic DeleteView Example Code +category: page +slug: django-views-generic-deleteview-examples +sortorder: 500011521 +toc: False +sidebartitle: django.views.generic DeleteView +meta: Python example code for the DeleteView class from the django.views.generic module of the Django project. + + +DeleteView is a class within the django.views.generic module of the Django project. + + +## Example 1 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / views / token.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/views/token.py) + +```python +# token.py +from django.contrib.auth.mixins import LoginRequiredMixin +from django.urls import reverse_lazy +~~from django.views.generic import DeleteView, ListView + +from ..models import get_access_token_model + + +class AuthorizedTokensListView(LoginRequiredMixin, ListView): + context_object_name = "authorized_tokens" + template_name = "oauth2_provider/authorized-tokens.html" + model = get_access_token_model() + + def get_queryset(self): + return super().get_queryset().select_related("application").filter( + user=self.request.user + ) + + +~~class AuthorizedTokenDeleteView(LoginRequiredMixin, DeleteView): + template_name = "oauth2_provider/authorized-token-delete.html" + success_url = reverse_lazy("oauth2_provider:authorized-token-list") + model = get_access_token_model() + + def get_queryset(self): + return super().get_queryset().filter(user=self.request.user) + + + +## ... source file continues with no further DeleteView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-detail-singleobjectmixin.markdown b/content/pages/examples/django/django-views-generic-detail-singleobjectmixin.markdown new file mode 100644 index 000000000..eb253dfb1 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-detail-singleobjectmixin.markdown @@ -0,0 +1,65 @@ +title: django.views.generic.detail SingleObjectMixin Example Code +category: page +slug: django-views-generic-detail-singleobjectmixin-examples +sortorder: 500011533 +toc: False +sidebartitle: django.views.generic.detail SingleObjectMixin +meta: Python example code for the SingleObjectMixin class from the django.views.generic.detail module of the Django project. + + +SingleObjectMixin is a class within the django.views.generic.detail module of the Django project. + + +## Example 1 from django-downloadview +[django-downloadview](https://github.com/benoitbryon/django-downloadview) +([project documentation](https://django-downloadview.readthedocs.io/en/1.9/) +and +[PyPI package information](https://pypi.org/project/django-downloadview/)) +is a [Django](/django.html) extension for serving downloads through your +web application. While typically you would use a web server to handle +[static content](/static-content.html), sometimes you need to control +file access, such as requiring a user to register before downloading a +PDF. In that situations, django-downloadview is a handy library to avoid +boilerplate code for common scenarios. + +[**django-downloadview / django_downloadview / views / object.py**](https://github.com/benoitbryon/django-downloadview/blob/master/django_downloadview/views/object.py) + +```python +# object.py +~~from django.views.generic.detail import SingleObjectMixin + +from django_downloadview.exceptions import FileNotFound +from django_downloadview.views.base import BaseDownloadView + + +~~class ObjectDownloadView(SingleObjectMixin, BaseDownloadView): + + file_field = "file" + + basename_field = None + + encoding_field = None + + mime_type_field = None + + charset_field = None + + modification_time_field = None + + size_field = None + + def get_file(self): + file_instance = getattr(self.object, self.file_field) + if not file_instance: + raise FileNotFound( + f'Field="{self.file_field}" on object="{self.object}" is empty' + ) + for field in ("encoding", "mime_type", "charset", "modification_time", "size"): + model_field = getattr(self, "%s_field" % field, False) + if model_field: + + +## ... source file continues with no further SingleObjectMixin examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-detailview.markdown b/content/pages/examples/django/django-views-generic-detailview.markdown new file mode 100644 index 000000000..74f44aca4 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-detailview.markdown @@ -0,0 +1,135 @@ +title: django.views.generic DetailView Example Code +category: page +slug: django-views-generic-detailview-examples +sortorder: 500011522 +toc: False +sidebartitle: django.views.generic DetailView +meta: Python example code for the DetailView class from the django.views.generic module of the Django project. + + +DetailView is a class within the django.views.generic module of the Django project. + + +## Example 1 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / article.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/article.py) + +```python +# article.py +import difflib +import logging +from urllib.parse import urljoin + +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.db import transaction +from django.db.models import Q +from django.http import Http404 +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.shortcuts import render +from django.urls import reverse +from django.utils.decorators import method_decorator +from django.utils.translation import gettext as _ +from django.utils.translation import ngettext +from django.views.decorators.clickjacking import xframe_options_sameorigin +~~from django.views.generic import DetailView +from django.views.generic import FormView +from django.views.generic import ListView +from django.views.generic import RedirectView +from django.views.generic import TemplateView +from django.views.generic import View +from wiki import editors +from wiki import forms +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.exceptions import NoRootURL +from wiki.core.paginator import WikiPaginator +from wiki.core.plugins import registry as plugin_registry +from wiki.core.utils import object_to_json_response +from wiki.decorators import get_article +from wiki.views.mixins import ArticleMixin + +log = logging.getLogger(__name__) + + +class ArticleView(ArticleMixin, TemplateView): + + template_name = "wiki/view.html" + + +## ... source file abbreviated to get to DetailView examples ... + + + def post(self, request, *args, **kwargs): + edit_form = forms.EditForm( + request, self.article.current_revision, request.POST, preview=True + ) + if edit_form.is_valid(): + self.title = edit_form.cleaned_data["title"] + self.content = edit_form.cleaned_data["content"] + self.preview = True + return super().get(request, *args, **kwargs) + + def get(self, request, *args, **kwargs): + if self.revision and not self.title: + self.title = self.revision.title + if self.revision and not self.content: + self.content = self.revision.content + return super().get(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + kwargs["title"] = self.title + kwargs["revision"] = self.revision + kwargs["content"] = self.content + kwargs["preview"] = self.preview + return ArticleMixin.get_context_data(self, **kwargs) + + +~~class DiffView(DetailView): + model = models.ArticleRevision + pk_url_kwarg = "revision_id" + + def render_to_response(self, context, **response_kwargs): + revision = self.get_object() + other_revision = revision.previous_revision + + baseText = other_revision.content if other_revision is not None else "" + newText = revision.content + + differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) + diff = differ.compare( + baseText.splitlines(keepends=True), newText.splitlines(keepends=True) + ) + other_changes = [] + + if not other_revision or other_revision.title != revision.title: + other_changes.append((_("New title"), revision.title)) + + return object_to_json_response( + {"diff": list(diff), "other_changes": other_changes} + ) + + + + +## ... source file continues with no further DetailView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-edit-createview.markdown b/content/pages/examples/django/django-views-generic-edit-createview.markdown new file mode 100644 index 000000000..252c6f8a6 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-edit-createview.markdown @@ -0,0 +1,132 @@ +title: django.views.generic.edit CreateView Example Code +category: page +slug: django-views-generic-edit-createview-examples +sortorder: 500011534 +toc: False +sidebartitle: django.views.generic.edit CreateView +meta: Python example code for the CreateView class from the django.views.generic.edit module of the Django project. + + +CreateView is a class within the django.views.generic.edit module of the Django project. + + +## Example 1 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / views.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./views.py) + +```python +# views.py +import re +import six +from collections import Counter + +try: + from django.urls import reverse_lazy +except ImportError: + from django.core.urlresolvers import reverse_lazy + +import django +from django.db import DatabaseError +from django.db.models import Count +from django.forms.models import model_to_dict +from django.http import HttpResponse, JsonResponse, HttpResponseRedirect, Http404 +from django.shortcuts import get_object_or_404, render +from django.views.decorators.http import require_POST +from django.utils.decorators import method_decorator +from django.views.generic import ListView +from django.views.generic.base import View +~~from django.views.generic.edit import CreateView, DeleteView +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.core.exceptions import ImproperlyConfigured +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.auth.views import LoginView + +from explorer import app_settings +from explorer.connections import connections +from explorer.exporters import get_exporter_class +from explorer.forms import QueryForm +from explorer.models import Query, QueryLog, MSG_FAILED_BLACKLIST +from explorer.tasks import execute_query +from explorer.utils import ( + url_get_rows, + url_get_query_id, + url_get_log_id, + url_get_params, + safe_login_prompt, + fmt_sql, + allowed_query_pks, + url_get_show, + url_get_fullscreen +) + +from explorer.schema import schema_info + + +## ... source file abbreviated to get to CreateView examples ... + + + 'created_at': q.created_at, + 'is_header': False, + 'run_count': q.run_count, + 'created_by_user': six.text_type(q.created_by_user) if q.created_by_user else None}) + dict_list.append(model_dict) + return dict_list + + model = Query + + +class ListQueryLogView(PermissionRequiredMixin, ExplorerContextMixin, ListView): + + permission_required = 'view_permission' + + def get_queryset(self): + kwargs = {'sql__isnull': False} + if url_get_query_id(self.request): + kwargs['query_id'] = url_get_query_id(self.request) + return QueryLog.objects.filter(**kwargs).all() + + context_object_name = "recent_logs" + model = QueryLog + paginate_by = 20 + + +~~class CreateQueryView(PermissionRequiredMixin, ExplorerContextMixin, CreateView): + + permission_required = 'change_permission' + + def form_valid(self, form): + form.instance.created_by_user = self.request.user + return super(CreateQueryView, self).form_valid(form) + + form_class = QueryForm + template_name = 'explorer/query.html' + + +class DeleteQueryView(PermissionRequiredMixin, ExplorerContextMixin, DeleteView): + + permission_required = 'change_permission' + model = Query + success_url = reverse_lazy("explorer_index") + + +class PlayQueryView(PermissionRequiredMixin, ExplorerContextMixin, View): + + permission_required = 'change_permission' + + def get(self, request): + if url_get_query_id(request): + + +## ... source file continues with no further CreateView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-edit-deleteview.markdown b/content/pages/examples/django/django-views-generic-edit-deleteview.markdown new file mode 100644 index 000000000..56ab75129 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-edit-deleteview.markdown @@ -0,0 +1,132 @@ +title: django.views.generic.edit DeleteView Example Code +category: page +slug: django-views-generic-edit-deleteview-examples +sortorder: 500011535 +toc: False +sidebartitle: django.views.generic.edit DeleteView +meta: Python example code for the DeleteView class from the django.views.generic.edit module of the Django project. + + +DeleteView is a class within the django.views.generic.edit module of the Django project. + + +## Example 1 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / views.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./views.py) + +```python +# views.py +import re +import six +from collections import Counter + +try: + from django.urls import reverse_lazy +except ImportError: + from django.core.urlresolvers import reverse_lazy + +import django +from django.db import DatabaseError +from django.db.models import Count +from django.forms.models import model_to_dict +from django.http import HttpResponse, JsonResponse, HttpResponseRedirect, Http404 +from django.shortcuts import get_object_or_404, render +from django.views.decorators.http import require_POST +from django.utils.decorators import method_decorator +from django.views.generic import ListView +from django.views.generic.base import View +~~from django.views.generic.edit import CreateView, DeleteView +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.core.exceptions import ImproperlyConfigured +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.auth.views import LoginView + +from explorer import app_settings +from explorer.connections import connections +from explorer.exporters import get_exporter_class +from explorer.forms import QueryForm +from explorer.models import Query, QueryLog, MSG_FAILED_BLACKLIST +from explorer.tasks import execute_query +from explorer.utils import ( + url_get_rows, + url_get_query_id, + url_get_log_id, + url_get_params, + safe_login_prompt, + fmt_sql, + allowed_query_pks, + url_get_show, + url_get_fullscreen +) + +from explorer.schema import schema_info + + +## ... source file abbreviated to get to DeleteView examples ... + + + permission_required = 'view_permission' + + def get_queryset(self): + kwargs = {'sql__isnull': False} + if url_get_query_id(self.request): + kwargs['query_id'] = url_get_query_id(self.request) + return QueryLog.objects.filter(**kwargs).all() + + context_object_name = "recent_logs" + model = QueryLog + paginate_by = 20 + + +class CreateQueryView(PermissionRequiredMixin, ExplorerContextMixin, CreateView): + + permission_required = 'change_permission' + + def form_valid(self, form): + form.instance.created_by_user = self.request.user + return super(CreateQueryView, self).form_valid(form) + + form_class = QueryForm + template_name = 'explorer/query.html' + + +~~class DeleteQueryView(PermissionRequiredMixin, ExplorerContextMixin, DeleteView): + + permission_required = 'change_permission' + model = Query + success_url = reverse_lazy("explorer_index") + + +class PlayQueryView(PermissionRequiredMixin, ExplorerContextMixin, View): + + permission_required = 'change_permission' + + def get(self, request): + if url_get_query_id(request): + query = get_object_or_404(Query, pk=url_get_query_id(request)) + return self.render_with_sql(request, query, run_query=False) + + if url_get_log_id(request): + log = get_object_or_404(QueryLog, pk=url_get_log_id(request)) + query = Query(sql=log.sql, title="Playground", connection=log.connection) + return self.render_with_sql(request, query) + + return self.render() + + def post(self, request): + sql = request.POST.get('sql') + + +## ... source file continues with no further DeleteView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-edit-deletionmixin.markdown b/content/pages/examples/django/django-views-generic-edit-deletionmixin.markdown new file mode 100644 index 000000000..c2aa6872a --- /dev/null +++ b/content/pages/examples/django/django-views-generic-edit-deletionmixin.markdown @@ -0,0 +1,120 @@ +title: django.views.generic.edit DeletionMixin Example Code +category: page +slug: django-views-generic-edit-deletionmixin-examples +sortorder: 500011536 +toc: False +sidebartitle: django.views.generic.edit DeletionMixin +meta: Python example code for the DeletionMixin class from the django.views.generic.edit module of the Django project. + + +DeletionMixin is a class within the django.views.generic.edit module of the Django project. + + +## Example 1 from django-mongonaut +[django-mongonaut](https://github.com/jazzband/django-mongonaut) +([project documentation](https://django-mongonaut.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-mongonaut/)) +provides an introspective interface for working with +[MongoDB](/mongodb.html) via mongoengine. The project has its own new code +to map MongoDB to the [Django](/django.html) Admin interface. + +django-mongonaut's highlighted features include automatic introspection of +mongoengine documents, the ability to constrain who sees what and what +they can do and full control for adding, editing and deleting documents. + +The django-mongonaut project is open sourced under the +[MIT License](https://github.com/jazzband/django-mongonaut/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-mongonaut / mongonaut / views.py**](https://github.com/jazzband/django-mongonaut/blob/master/mongonaut/./views.py) + +```python +# views.py +import math + +from django.contrib import messages +from django.urls import reverse +from django.forms import Form +from django.http import HttpResponseForbidden +from django.http import Http404 +from django.utils.functional import cached_property +~~from django.views.generic.edit import DeletionMixin +from django.views.generic import ListView +from django.views.generic import TemplateView +from django.views.generic.edit import FormView +from mongoengine.fields import EmbeddedDocumentField, ListField + +from mongonaut.forms import MongoModelForm +from mongonaut.mixins import MongonautFormViewMixin +from mongonaut.mixins import MongonautViewMixin +from mongonaut.utils import is_valid_object_id + + +class IndexView(MongonautViewMixin, ListView): + + template_name = "mongonaut/index.html" + queryset = [] + permission = 'has_view_permission' + + def get_queryset(self): + return self.get_mongoadmins() + + +class DocumentListView(MongonautViewMixin, FormView): + form_class = Form + success_url = '/' + + +## ... source file abbreviated to get to DeletionMixin examples ... + + + def get_context_data(self, **kwargs): + context = super(DocumentAddFormView, self).get_context_data(**kwargs) + self.set_mongoadmin() + context = self.set_permissions_in_context(context) + self.document_type = getattr(self.models, self.document_name) + + context['app_label'] = self.app_label + context['document_name'] = self.document_name + context['form_action'] = reverse('document_detail_add_form', args=[self.kwargs.get('app_label'), + self.kwargs.get('document_name')]) + + return context + + def get_form(self): + self.set_mongonaut_base() + self.document_type = getattr(self.models, self.document_name) + self.form = Form() + + if self.request.method == 'POST': + self.form = self.process_post_form('Your new document has been added and saved.') + else: + self.form = MongoModelForm(model=self.document_type).get_form() + return self.form + + +~~class DocumentDeleteView(DeletionMixin, MongonautViewMixin, TemplateView): + + success_url = "/" + template_name = "mongonaut/document_delete.html" + + def get_success_url(self): + self.set_mongonaut_base() + messages.add_message(self.request, messages.INFO, 'Your document has been deleted.') + return reverse('document_list', kwargs={'app_label': self.app_label, 'document_name': self.document_name}) + + def get_object(self): + self.set_mongoadmin() + self.document_type = getattr(self.models, self.document_name) + self.ident = self.kwargs.get('id') + self.document = self.document_type.objects.get(pk=self.ident) + return self.document + + + +## ... source file continues with no further DeletionMixin examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-edit-formmixin.markdown b/content/pages/examples/django/django-views-generic-edit-formmixin.markdown new file mode 100644 index 000000000..8206cab3e --- /dev/null +++ b/content/pages/examples/django/django-views-generic-edit-formmixin.markdown @@ -0,0 +1,73 @@ +title: django.views.generic.edit FormMixin Example Code +category: page +slug: django-views-generic-edit-formmixin-examples +sortorder: 500011537 +toc: False +sidebartitle: django.views.generic.edit FormMixin +meta: Python example code for the FormMixin class from the django.views.generic.edit module of the Django project. + + +FormMixin is a class within the django.views.generic.edit module of the Django project. + + +## Example 1 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / generic_views.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./generic_views.py) + +```python +# generic_views.py +from django.conf import settings +from django.core.paginator import Paginator +from django.views.generic import FormView +~~from django.views.generic.edit import FormMixin +from django.views.generic.list import MultipleObjectMixin + +from .forms import FacetedSearchForm, ModelSearchForm +from .query import SearchQuerySet + +RESULTS_PER_PAGE = getattr(settings, "HAYSTACK_SEARCH_RESULTS_PER_PAGE", 20) + + +~~class SearchMixin(MultipleObjectMixin, FormMixin): + + template_name = "search/search.html" + load_all = True + form_class = ModelSearchForm + context_object_name = None + paginate_by = RESULTS_PER_PAGE + paginate_orphans = 0 + paginator_class = Paginator + page_kwarg = "page" + form_name = "form" + search_field = "q" + object_list = None + + def get_queryset(self): + if self.queryset is None: + self.queryset = SearchQuerySet() + return self.queryset + + def get_form_kwargs(self): + kwargs = {"initial": self.get_initial()} + if self.request.method == "GET": + kwargs.update({"data": self.request.GET}) + kwargs.update( + {"searchqueryset": self.get_queryset(), "load_all": self.load_all} + + +## ... source file continues with no further FormMixin examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-edit-formview.markdown b/content/pages/examples/django/django-views-generic-edit-formview.markdown new file mode 100644 index 000000000..f1ab5dcf0 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-edit-formview.markdown @@ -0,0 +1,317 @@ +title: django.views.generic.edit FormView Example Code +category: page +slug: django-views-generic-edit-formview-examples +sortorder: 500011538 +toc: False +sidebartitle: django.views.generic.edit FormView +meta: Python example code for the FormView class from the django.views.generic.edit module of the Django project. + + +FormView is a class within the django.views.generic.edit module of the Django project. + + +## Example 1 from django-allauth +[django-allauth](https://github.com/pennersr/django-allauth) +([project website](https://www.intenct.nl/projects/django-allauth/)) is a +[Django](/django.html) library for easily adding local and social authentication +flows to Django projects. It is open source under the +[MIT License](https://github.com/pennersr/django-allauth/blob/master/LICENSE). + + +[**django-allauth / allauth / socialaccount / views.py**](https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/views.py) + +```python +# views.py +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.sites.shortcuts import get_current_site +from django.http import HttpResponseRedirect +from django.urls import reverse, reverse_lazy +from django.views.generic.base import TemplateView +~~from django.views.generic.edit import FormView + +from ..account import app_settings as account_settings +from ..account.adapter import get_adapter as get_account_adapter +from ..account.views import ( + AjaxCapableProcessFormViewMixin, + CloseableSignupMixin, + RedirectAuthenticatedUserMixin, +) +from ..utils import get_form_class +from . import app_settings, helpers +from .adapter import get_adapter +from .forms import DisconnectForm, SignupForm +from .models import SocialAccount, SocialLogin + + +class SignupView(RedirectAuthenticatedUserMixin, CloseableSignupMixin, +~~ AjaxCapableProcessFormViewMixin, FormView): + form_class = SignupForm + template_name = ( + 'socialaccount/signup.' + account_settings.TEMPLATE_EXTENSION) + + def get_form_class(self): + return get_form_class(app_settings.FORMS, + 'signup', + self.form_class) + + def dispatch(self, request, *args, **kwargs): + self.sociallogin = None + data = request.session.get('socialaccount_sociallogin') + if data: + self.sociallogin = SocialLogin.deserialize(data) + if not self.sociallogin: + return HttpResponseRedirect(reverse('account_login')) + return super(SignupView, self).dispatch(request, *args, **kwargs) + + def is_open(self): + return get_adapter(self.request).is_open_for_signup( + self.request, + self.sociallogin) + + def get_form_kwargs(self): + + +## ... source file abbreviated to get to FormView examples ... + + + + def get_authenticated_redirect_url(self): + return reverse(connections) + + +signup = SignupView.as_view() + + +class LoginCancelledView(TemplateView): + template_name = ( + "socialaccount/login_cancelled." + account_settings.TEMPLATE_EXTENSION) + + +login_cancelled = LoginCancelledView.as_view() + + +class LoginErrorView(TemplateView): + template_name = ( + "socialaccount/authentication_error." + + account_settings.TEMPLATE_EXTENSION) + + +login_error = LoginErrorView.as_view() + + +~~class ConnectionsView(AjaxCapableProcessFormViewMixin, FormView): + template_name = ( + "socialaccount/connections." + + account_settings.TEMPLATE_EXTENSION) + form_class = DisconnectForm + success_url = reverse_lazy("socialaccount_connections") + + def get_form_class(self): + return get_form_class(app_settings.FORMS, + 'disconnect', + self.form_class) + + def get_form_kwargs(self): + kwargs = super(ConnectionsView, self).get_form_kwargs() + kwargs["request"] = self.request + return kwargs + + def form_valid(self, form): + get_account_adapter().add_message(self.request, + messages.INFO, + 'socialaccount/messages/' + 'account_disconnected.txt') + form.save() + return super(ConnectionsView, self).form_valid(form) + + + +## ... source file continues with no further FormView examples... + +``` + + +## Example 2 from django-import-export +[django-import-export](https://github.com/django-import-export/django-import-export) +([documentation](https://django-import-export.readthedocs.io/en/latest/) +and [PyPI page](https://pypi.org/project/django-import-export/)) +is a [Django](/django.html) code library for importing and exporting data +from the Django Admin. The tool supports many export and import formats +such as CSV, JSON and YAML. django-import-export is open source under the +[BSD 2-Clause "Simplified" License](https://github.com/django-import-export/django-import-export/blob/master/LICENSE). + +[**django-import-export / import_export / mixins.py**](https://github.com/django-import-export/django-import-export/blob/master/import_export/./mixins.py) + +```python +# mixins.py +from django.http import HttpResponse +from django.utils.timezone import now +~~from django.views.generic.edit import FormView + +from .formats import base_formats +from .forms import ExportForm +from .resources import modelresource_factory +from .signals import post_export + + +class ExportViewMixin: + formats = base_formats.DEFAULT_FORMATS + form_class = ExportForm + resource_class = None + + def get_export_formats(self): + return [f for f in self.formats if f().can_export()] + + def get_resource_class(self): + if not self.resource_class: + return modelresource_factory(self.model) + return self.resource_class + + def get_export_resource_class(self): + return self.get_resource_class() + + def get_resource_kwargs(self, request, *args, **kwargs): + + +## ... source file abbreviated to get to FormView examples ... + + + + def get_export_data(self, file_format, queryset, *args, **kwargs): + resource_class = self.get_export_resource_class() + data = resource_class(**self.get_export_resource_kwargs(self.request))\ + .export(queryset, *args, **kwargs) + export_data = file_format.export_data(data) + return export_data + + def get_export_filename(self, file_format): + date_str = now().strftime('%Y-%m-%d') + filename = "%s-%s.%s" % (self.model.__name__, + date_str, + file_format.get_extension()) + return filename + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + return context + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs['formats'] = self.get_export_formats() + return kwargs + + +~~class ExportViewFormMixin(ExportViewMixin, FormView): + def form_valid(self, form): + formats = self.get_export_formats() + file_format = formats[ + int(form.cleaned_data['file_format']) + ]() + if hasattr(self, 'get_filterset'): + queryset = self.get_filterset(self.get_filterset_class()).qs + else: + queryset = self.get_queryset() + export_data = self.get_export_data(file_format, queryset) + content_type = file_format.get_content_type() + try: + response = HttpResponse(export_data, content_type=content_type) + except TypeError: + response = HttpResponse(export_data, mimetype=content_type) + response['Content-Disposition'] = 'attachment; filename="%s"' % ( + self.get_export_filename(file_format), + ) + + post_export.send(sender=None, model=self.model) + return response + + + +## ... source file continues with no further FormView examples... + +``` + + +## Example 3 from django-mongonaut +[django-mongonaut](https://github.com/jazzband/django-mongonaut) +([project documentation](https://django-mongonaut.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-mongonaut/)) +provides an introspective interface for working with +[MongoDB](/mongodb.html) via mongoengine. The project has its own new code +to map MongoDB to the [Django](/django.html) Admin interface. + +django-mongonaut's highlighted features include automatic introspection of +mongoengine documents, the ability to constrain who sees what and what +they can do and full control for adding, editing and deleting documents. + +The django-mongonaut project is open sourced under the +[MIT License](https://github.com/jazzband/django-mongonaut/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-mongonaut / mongonaut / views.py**](https://github.com/jazzband/django-mongonaut/blob/master/mongonaut/./views.py) + +```python +# views.py +import math + +from django.contrib import messages +from django.urls import reverse +from django.forms import Form +from django.http import HttpResponseForbidden +from django.http import Http404 +from django.utils.functional import cached_property +from django.views.generic.edit import DeletionMixin +from django.views.generic import ListView +from django.views.generic import TemplateView +~~from django.views.generic.edit import FormView +from mongoengine.fields import EmbeddedDocumentField, ListField + +from mongonaut.forms import MongoModelForm +from mongonaut.mixins import MongonautFormViewMixin +from mongonaut.mixins import MongonautViewMixin +from mongonaut.utils import is_valid_object_id + + +class IndexView(MongonautViewMixin, ListView): + + template_name = "mongonaut/index.html" + queryset = [] + permission = 'has_view_permission' + + def get_queryset(self): + return self.get_mongoadmins() + + +~~class DocumentListView(MongonautViewMixin, FormView): + form_class = Form + success_url = '/' + template_name = "mongonaut/document_list.html" + permission = 'has_view_permission' + + documents_per_page = 25 + + + def get_qset(self, queryset, q): + if self.mongoadmin.search_fields and q: + params = {} + for field in self.mongoadmin.search_fields: + if field == 'id': + if is_valid_object_id(q): + return queryset.filter(pk=q) + continue + search_key = "{field}__icontains".format(field=field) + params[search_key] = q + + queryset = queryset.filter(**params) + return queryset + + @cached_property + def get_queryset(self): + + +## ... source file continues with no further FormView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-formview.markdown b/content/pages/examples/django/django-views-generic-formview.markdown new file mode 100644 index 000000000..8c9fe881f --- /dev/null +++ b/content/pages/examples/django/django-views-generic-formview.markdown @@ -0,0 +1,383 @@ +title: django.views.generic FormView Example Code +category: page +slug: django-views-generic-formview-examples +sortorder: 500011523 +toc: False +sidebartitle: django.views.generic FormView +meta: Python example code for the FormView class from the django.views.generic module of the Django project. + + +FormView is a class within the django.views.generic module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / views / crud.py**](https://github.com/jrief/django-angular/blob/master/djng/views/crud.py) + +```python +# crud.py +import json + +from django.core.exceptions import ValidationError +from django.core import serializers +from django.forms.models import modelform_factory +~~from django.views.generic import FormView + +from djng.views.mixins import JSONBaseMixin, JSONResponseException + + +class NgMissingParameterError(ValueError): + pass + + +~~class NgCRUDView(JSONBaseMixin, FormView): + model = None + fields = None + form_class = None + slug_field = 'slug' + serializer_name = 'python' + serialize_natural_keys = False + + allowed_methods = ['GET', 'POST', 'DELETE'] + exclude_methods = [] + + def get_allowed_methods(self): + return [method for method in self.allowed_methods if method not in self.exclude_methods] + + def dispatch(self, request, *args, **kwargs): + allowed_methods = self.get_allowed_methods() + try: + if request.method == 'GET' and 'GET' in allowed_methods: + if 'pk' in request.GET or self.slug_field in request.GET: + return self.ng_get(request, *args, **kwargs) + return self.ng_query(request, *args, **kwargs) + elif request.method == 'POST' and 'POST' in allowed_methods: + return self.ng_save(request, *args, **kwargs) + elif request.method == 'DELETE' and 'DELETE' in allowed_methods: + return self.ng_delete(request, *args, **kwargs) + + +## ... source file continues with no further FormView examples... + +``` + + +## Example 2 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / generic_views.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./generic_views.py) + +```python +# generic_views.py +from django.conf import settings +from django.core.paginator import Paginator +~~from django.views.generic import FormView +from django.views.generic.edit import FormMixin +from django.views.generic.list import MultipleObjectMixin + +from .forms import FacetedSearchForm, ModelSearchForm +from .query import SearchQuerySet + +RESULTS_PER_PAGE = getattr(settings, "HAYSTACK_SEARCH_RESULTS_PER_PAGE", 20) + + +class SearchMixin(MultipleObjectMixin, FormMixin): + + template_name = "search/search.html" + load_all = True + form_class = ModelSearchForm + context_object_name = None + paginate_by = RESULTS_PER_PAGE + paginate_orphans = 0 + paginator_class = Paginator + page_kwarg = "page" + form_name = "form" + search_field = "q" + object_list = None + + def get_queryset(self): + + +## ... source file abbreviated to get to FormView examples ... + + + return self.render_to_response(context) + + +class FacetedSearchMixin(SearchMixin): + + form_class = FacetedSearchForm + facet_fields = None + + def get_form_kwargs(self): + kwargs = super(FacetedSearchMixin, self).get_form_kwargs() + kwargs.update({"selected_facets": self.request.GET.getlist("selected_facets")}) + return kwargs + + def get_context_data(self, **kwargs): + context = super(FacetedSearchMixin, self).get_context_data(**kwargs) + context.update({"facets": self.queryset.facet_counts()}) + return context + + def get_queryset(self): + qs = super(FacetedSearchMixin, self).get_queryset() + for field in self.facet_fields: + qs = qs.facet(field) + return qs + + +~~class SearchView(SearchMixin, FormView): + + def get(self, request, *args, **kwargs): + form_class = self.get_form_class() + form = self.get_form(form_class) + + if form.is_valid(): + return self.form_valid(form) + else: + return self.form_invalid(form) + + +class FacetedSearchView(FacetedSearchMixin, SearchView): + + pass + + + +## ... source file continues with no further FormView examples... + +``` + + +## Example 3 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / views / base.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/views/base.py) + +```python +# base.py +import json +import logging +import urllib.parse + +from django.contrib.auth.mixins import LoginRequiredMixin +from django.http import HttpResponse, JsonResponse +from django.shortcuts import render +from django.urls import reverse +from django.utils import timezone +from django.utils.decorators import method_decorator +from django.views.decorators.csrf import csrf_exempt +from django.views.decorators.debug import sensitive_post_parameters +~~from django.views.generic import FormView, View + +from ..exceptions import OAuthToolkitError +from ..forms import AllowForm +from ..http import OAuth2ResponseRedirect +from ..models import get_access_token_model, get_application_model +from ..scopes import get_scopes_backend +from ..settings import oauth2_settings +from ..signals import app_authorized +from .mixins import OAuthLibMixin + + +log = logging.getLogger("oauth2_provider") + + +class BaseAuthorizationView(LoginRequiredMixin, OAuthLibMixin, View): + + def dispatch(self, request, *args, **kwargs): + self.oauth2_data = {} + return super().dispatch(request, *args, **kwargs) + + def error_response(self, error, application, **kwargs): + redirect, error_response = super().error_response(error, **kwargs) + + if redirect: + return self.redirect(error_response["url"], application) + + status = error_response["error"].status_code + return self.render_to_response(error_response, status=status) + + def redirect(self, redirect_to, application): + if application is None: + allowed_schemes = oauth2_settings.ALLOWED_REDIRECT_URI_SCHEMES + else: + allowed_schemes = application.get_allowed_schemes() + return OAuth2ResponseRedirect(redirect_to, allowed_schemes) + + +RFC3339 = "%Y-%m-%dT%H:%M:%SZ" + + +~~class AuthorizationView(BaseAuthorizationView, FormView): + template_name = "oauth2_provider/authorize.html" + form_class = AllowForm + + server_class = oauth2_settings.OAUTH2_SERVER_CLASS + validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS + oauthlib_backend_class = oauth2_settings.OAUTH2_BACKEND_CLASS + + skip_authorization_completely = False + + def get_initial(self): + scopes = self.oauth2_data.get("scope", self.oauth2_data.get("scopes", [])) + initial_data = { + "redirect_uri": self.oauth2_data.get("redirect_uri", None), + "scope": " ".join(scopes), + "client_id": self.oauth2_data.get("client_id", None), + "state": self.oauth2_data.get("state", None), + "response_type": self.oauth2_data.get("response_type", None), + "code_challenge": self.oauth2_data.get("code_challenge", None), + "code_challenge_method": self.oauth2_data.get("code_challenge_method", None), + } + return initial_data + + def form_valid(self, form): + client_id = form.cleaned_data["client_id"] + + +## ... source file continues with no further FormView examples... + +``` + + +## Example 4 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / accounts.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/accounts.py) + +```python +# accounts.py +from django.conf import settings as django_settings +from django.contrib import messages +from django.contrib.auth import get_user_model +from django.contrib.auth import login as auth_login +from django.contrib.auth import logout as auth_logout +from django.contrib.auth.forms import AuthenticationForm +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.shortcuts import render +from django.urls import reverse +from django.utils.translation import gettext as _ +from django.views.generic import CreateView +~~from django.views.generic import FormView +from django.views.generic import UpdateView +from django.views.generic import View +from wiki import forms +from wiki.conf import settings + +User = get_user_model() + + +class Signup(CreateView): + model = User + form_class = forms.UserCreationForm + template_name = "wiki/accounts/signup.html" + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_anonymous and not request.user.is_superuser: + return redirect("wiki:root") + if not settings.ACCOUNT_HANDLING: + return redirect(settings.SIGNUP_URL) + if not request.user.is_superuser and not settings.ACCOUNT_SIGNUP_ALLOWED: + c = {"error_msg": _("Account signup is only allowed for administrators.")} + return render(request, "wiki/error.html", context=c) + + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["honeypot_class"] = context["form"].honeypot_class + context["honeypot_jsfunction"] = context["form"].honeypot_jsfunction + return context + + def get_success_url(self, *args): + messages.success( + self.request, _("You are now signed up... and now you can sign in!") + ) + return reverse("wiki:login") + + +class Logout(View): + def dispatch(self, request, *args, **kwargs): + if not settings.ACCOUNT_HANDLING: + return redirect(settings.LOGOUT_URL) + return super().dispatch(request, *args, **kwargs) + + def get(self, request, *args, **kwargs): + auth_logout(request) + messages.info(request, _("You are no longer logged in. Bye bye!")) + return redirect("wiki:root") + + +~~class Login(FormView): + + form_class = AuthenticationForm + template_name = "wiki/accounts/login.html" + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_anonymous: + return redirect("wiki:root") + if not settings.ACCOUNT_HANDLING: + return redirect(settings.LOGIN_URL) + return super().dispatch(request, *args, **kwargs) + + def get_form_kwargs(self): + self.request.session.set_test_cookie() + kwargs = super().get_form_kwargs() + kwargs["request"] = self.request + return kwargs + + def post(self, request, *args, **kwargs): + self.referer = request.session.get("login_referer", "") + return super().post(request, *args, **kwargs) + + def get(self, request, *args, **kwargs): + self.referer = request.META.get("HTTP_REFERER", "") + request.session["login_referer"] = self.referer + + +## ... source file continues with no further FormView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-list-listview.markdown b/content/pages/examples/django/django-views-generic-list-listview.markdown new file mode 100644 index 000000000..bb0fe0f78 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-list-listview.markdown @@ -0,0 +1,163 @@ +title: django.views.generic.list ListView Example Code +category: page +slug: django-views-generic-list-listview-examples +sortorder: 500011539 +toc: False +sidebartitle: django.views.generic.list ListView +meta: Python example code for the ListView class from the django.views.generic.list module of the Django project. + + +ListView is a class within the django.views.generic.list module of the Django project. + + +## Example 1 from django-tables2 +[django-tables2](https://github.com/jieter/django-tables2) +([projection documentation](https://django-tables2.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/django-tables2/)) +is a code library for [Django](/django.html) that simplifies creating and +displaying tables in [Django templates](/django-templates.html), +especially with more advanced features such as pagination and sorting. +The project and its code are +[available as open source](https://github.com/jieter/django-tables2/blob/master/LICENSE). + +[**django-tables2 / django_tables2 / views.py**](https://github.com/jieter/django-tables2/blob/master/django_tables2/./views.py) + +```python +# views.py +from itertools import count + +from django.core.exceptions import ImproperlyConfigured +~~from django.views.generic.list import ListView + +from . import tables +from .config import RequestConfig + + +class TableMixinBase: + + context_table_name = "table" + table_pagination = None + + def get_context_table_name(self, table): + return self.context_table_name + + def get_table_pagination(self, table): + paginate = self.table_pagination + if paginate is False: + return False + + paginate = {} + if getattr(self, "paginate_by", None) is not None: + paginate["per_page"] = self.paginate_by + if hasattr(self, "paginator_class"): + paginate["paginator_class"] = self.paginator_class + if getattr(self, "paginate_orphans", 0) != 0: + + +## ... source file abbreviated to get to ListView examples ... + + + ) + + def get_table_data(self): + if self.table_data is not None: + return self.table_data + elif hasattr(self, "object_list"): + return self.object_list + elif hasattr(self, "get_queryset"): + return self.get_queryset() + + klass = type(self).__name__ + raise ImproperlyConfigured( + "Table data was not specified. Define {}.table_data".format(klass) + ) + + def get_table_kwargs(self): + return {} + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + table = self.get_table(**self.get_table_kwargs()) + context[self.get_context_table_name(table)] = table + return context + + +~~class SingleTableView(SingleTableMixin, ListView): + + +class MultiTableMixin(TableMixinBase): + + tables = None + tables_data = None + + table_prefix = "table_{}-" + + context_table_name = "tables" + + def get_tables(self): + if self.tables is None: + klass = type(self).__name__ + raise ImproperlyConfigured("No tables were specified. Define {}.tables".format(klass)) + data = self.get_tables_data() + + if data is None: + return self.tables + + if len(data) != len(self.tables): + klass = type(self).__name__ + raise ImproperlyConfigured("len({}.tables_data) != len({}.tables)".format(klass, klass)) + return list(Table(data[i]) for i, Table in enumerate(self.tables)) + + +## ... source file continues with no further ListView examples... + +``` + + +## Example 2 from django-taggit +[django-taggit](https://github.com/jazzband/django-taggit/) +([PyPI page](https://pypi.org/project/django-taggit/)) provides a way +to create, store, manage and use tags in a [Django](/django.html) project. +The code for django-taggit is +[open source](https://github.com/jazzband/django-taggit/blob/master/LICENSE) +and maintained by the collaborative developer community group +[Jazzband](https://jazzband.co/). + +[**django-taggit / taggit / views.py**](https://github.com/jazzband/django-taggit/blob/master/taggit/./views.py) + +```python +# views.py +from django.contrib.contenttypes.models import ContentType +from django.shortcuts import get_object_or_404 +~~from django.views.generic.list import ListView + +from taggit.models import Tag, TaggedItem + + +def tagged_object_list(request, slug, queryset, **kwargs): + if callable(queryset): + queryset = queryset() + kwargs["slug"] = slug + tag_list_view = type( + "TagListView", + (TagListMixin, ListView), + {"model": queryset.model, "queryset": queryset}, + ) + return tag_list_view.as_view()(request, **kwargs) + + +class TagListMixin: + tag_suffix = "_tag" + + def dispatch(self, request, *args, **kwargs): + slug = kwargs.pop("slug") + self.tag = get_object_or_404(Tag, slug=slug) + return super().dispatch(request, *args, **kwargs) + + + +## ... source file continues with no further ListView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-list-multipleobjectmixin.markdown b/content/pages/examples/django/django-views-generic-list-multipleobjectmixin.markdown new file mode 100644 index 000000000..bef2df0d1 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-list-multipleobjectmixin.markdown @@ -0,0 +1,73 @@ +title: django.views.generic.list MultipleObjectMixin Example Code +category: page +slug: django-views-generic-list-multipleobjectmixin-examples +sortorder: 500011540 +toc: False +sidebartitle: django.views.generic.list MultipleObjectMixin +meta: Python example code for the MultipleObjectMixin class from the django.views.generic.list module of the Django project. + + +MultipleObjectMixin is a class within the django.views.generic.list module of the Django project. + + +## Example 1 from django-haystack +[django-haystack](https://github.com/django-haystack/django-haystack) +([project website](http://haystacksearch.org/) and +[PyPI page](https://pypi.org/project/django-haystack/)) +is a search abstraction layer that separates the Python search code +in a [Django](/django.html) web application from the search engine +implementation that it runs on, such as +[Apache Solr](http://lucene.apache.org/solr/), +[Elasticsearch](https://www.elastic.co/) +or [Whoosh](https://whoosh.readthedocs.io/en/latest/intro.html). + +The django-haystack project is open source under the +[BSD license](https://github.com/django-haystack/django-haystack/blob/master/LICENSE). + +[**django-haystack / haystack / generic_views.py**](https://github.com/django-haystack/django-haystack/blob/master/haystack/./generic_views.py) + +```python +# generic_views.py +from django.conf import settings +from django.core.paginator import Paginator +from django.views.generic import FormView +from django.views.generic.edit import FormMixin +~~from django.views.generic.list import MultipleObjectMixin + +from .forms import FacetedSearchForm, ModelSearchForm +from .query import SearchQuerySet + +RESULTS_PER_PAGE = getattr(settings, "HAYSTACK_SEARCH_RESULTS_PER_PAGE", 20) + + +~~class SearchMixin(MultipleObjectMixin, FormMixin): + + template_name = "search/search.html" + load_all = True + form_class = ModelSearchForm + context_object_name = None + paginate_by = RESULTS_PER_PAGE + paginate_orphans = 0 + paginator_class = Paginator + page_kwarg = "page" + form_name = "form" + search_field = "q" + object_list = None + + def get_queryset(self): + if self.queryset is None: + self.queryset = SearchQuerySet() + return self.queryset + + def get_form_kwargs(self): + kwargs = {"initial": self.get_initial()} + if self.request.method == "GET": + kwargs.update({"data": self.request.GET}) + kwargs.update( + {"searchqueryset": self.get_queryset(), "load_all": self.load_all} + + +## ... source file continues with no further MultipleObjectMixin examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-listview.markdown b/content/pages/examples/django/django-views-generic-listview.markdown new file mode 100644 index 000000000..602381d0a --- /dev/null +++ b/content/pages/examples/django/django-views-generic-listview.markdown @@ -0,0 +1,509 @@ +title: django.views.generic ListView Example Code +category: page +slug: django-views-generic-listview-examples +sortorder: 500011524 +toc: False +sidebartitle: django.views.generic ListView +meta: Python example code for the ListView class from the django.views.generic module of the Django project. + + +ListView is a class within the django.views.generic module of the Django project. + + +## Example 1 from django-mongonaut +[django-mongonaut](https://github.com/jazzband/django-mongonaut) +([project documentation](https://django-mongonaut.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-mongonaut/)) +provides an introspective interface for working with +[MongoDB](/mongodb.html) via mongoengine. The project has its own new code +to map MongoDB to the [Django](/django.html) Admin interface. + +django-mongonaut's highlighted features include automatic introspection of +mongoengine documents, the ability to constrain who sees what and what +they can do and full control for adding, editing and deleting documents. + +The django-mongonaut project is open sourced under the +[MIT License](https://github.com/jazzband/django-mongonaut/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-mongonaut / mongonaut / views.py**](https://github.com/jazzband/django-mongonaut/blob/master/mongonaut/./views.py) + +```python +# views.py +import math + +from django.contrib import messages +from django.urls import reverse +from django.forms import Form +from django.http import HttpResponseForbidden +from django.http import Http404 +from django.utils.functional import cached_property +from django.views.generic.edit import DeletionMixin +~~from django.views.generic import ListView +from django.views.generic import TemplateView +from django.views.generic.edit import FormView +from mongoengine.fields import EmbeddedDocumentField, ListField + +from mongonaut.forms import MongoModelForm +from mongonaut.mixins import MongonautFormViewMixin +from mongonaut.mixins import MongonautViewMixin +from mongonaut.utils import is_valid_object_id + + +~~class IndexView(MongonautViewMixin, ListView): + + template_name = "mongonaut/index.html" + queryset = [] + permission = 'has_view_permission' + + def get_queryset(self): + return self.get_mongoadmins() + + +class DocumentListView(MongonautViewMixin, FormView): + form_class = Form + success_url = '/' + template_name = "mongonaut/document_list.html" + permission = 'has_view_permission' + + documents_per_page = 25 + + + def get_qset(self, queryset, q): + if self.mongoadmin.search_fields and q: + params = {} + for field in self.mongoadmin.search_fields: + if field == 'id': + if is_valid_object_id(q): + + +## ... source file continues with no further ListView examples... + +``` + + +## Example 2 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / views / token.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/views/token.py) + +```python +# token.py +from django.contrib.auth.mixins import LoginRequiredMixin +from django.urls import reverse_lazy +~~from django.views.generic import DeleteView, ListView + +from ..models import get_access_token_model + + +~~class AuthorizedTokensListView(LoginRequiredMixin, ListView): + context_object_name = "authorized_tokens" + template_name = "oauth2_provider/authorized-tokens.html" + model = get_access_token_model() + + def get_queryset(self): + return super().get_queryset().select_related("application").filter( + user=self.request.user + ) + + +class AuthorizedTokenDeleteView(LoginRequiredMixin, DeleteView): + template_name = "oauth2_provider/authorized-token-delete.html" + success_url = reverse_lazy("oauth2_provider:authorized-token-list") + model = get_access_token_model() + + def get_queryset(self): + return super().get_queryset().filter(user=self.request.user) + + + +## ... source file continues with no further ListView examples... + +``` + + +## Example 3 from django-sql-explorer +[django-sql-explorer](https://github.com/groveco/django-sql-explorer) +([PyPI page](https://pypi.org/project/django-sql-explorer/0.2/)), +also referred to as "SQL Explorer", +is a code library for the [Django](/django.html) Admin that allows +approved, authenticated users to view and execute direct database SQL +queries. The tool keeps track of executed queries so users can share them +with each other, as well as export results to downloadable formats. +django-sql-explorer is provided as open source under the +[MIT license](https://github.com/groveco/django-sql-explorer/blob/master/LICENSE). + +[**django-sql-explorer / explorer / views.py**](https://github.com/groveco/django-sql-explorer/blob/master/explorer/./views.py) + +```python +# views.py +import re +import six +from collections import Counter + +try: + from django.urls import reverse_lazy +except ImportError: + from django.core.urlresolvers import reverse_lazy + +import django +from django.db import DatabaseError +from django.db.models import Count +from django.forms.models import model_to_dict +from django.http import HttpResponse, JsonResponse, HttpResponseRedirect, Http404 +from django.shortcuts import get_object_or_404, render +from django.views.decorators.http import require_POST +from django.utils.decorators import method_decorator +~~from django.views.generic import ListView +from django.views.generic.base import View +from django.views.generic.edit import CreateView, DeleteView +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.core.exceptions import ImproperlyConfigured +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.auth.views import LoginView + +from explorer import app_settings +from explorer.connections import connections +from explorer.exporters import get_exporter_class +from explorer.forms import QueryForm +from explorer.models import Query, QueryLog, MSG_FAILED_BLACKLIST +from explorer.tasks import execute_query +from explorer.utils import ( + url_get_rows, + url_get_query_id, + url_get_log_id, + url_get_params, + safe_login_prompt, + fmt_sql, + allowed_query_pks, + url_get_show, + url_get_fullscreen +) + + +## ... source file abbreviated to get to ListView examples ... + + + permission_required = 'change_permission' + + @method_decorator(xframe_options_sameorigin) + def dispatch(self, *args, **kwargs): + return super(SchemaView, self).dispatch(*args, **kwargs) + + def get(self, request, *args, **kwargs): + connection = kwargs.get('connection') + if connection not in connections: + raise Http404 + schema = schema_info(connection) + if schema: + return render(None, 'explorer/schema.html', + {'schema': schema_info(connection)}) + else: + return render(None, 'explorer/schema_building.html') + + +@require_POST +def format_sql(request): + sql = request.POST.get('sql', '') + formatted = fmt_sql(sql) + return JsonResponse({"formatted": formatted}) + + +~~class ListQueryView(PermissionRequiredMixin, ExplorerContextMixin, ListView): + + permission_required = 'view_permission_list' + + def recently_viewed(self): + qll = QueryLog.objects.filter(run_by_user=self.request.user, query_id__isnull=False).order_by( + '-run_at').select_related('query') + ret = [] + tracker = [] + for ql in qll: + if len(ret) == app_settings.EXPLORER_RECENT_QUERY_COUNT: + break + + if ql.query_id not in tracker: + ret.append(ql) + tracker.append(ql.query_id) + return ret + + def get_context_data(self, **kwargs): + context = super(ListQueryView, self).get_context_data(**kwargs) + context['object_list'] = self._build_queries_and_headers() + context['recent_queries'] = self.recently_viewed() + context['tasks_enabled'] = app_settings.ENABLE_TASKS + return context + + + +## ... source file abbreviated to get to ListView examples ... + + + for q in self.object_list: + model_dict = model_to_dict(q) + header = q.title.split(' - ')[0] + collapse_target = pattern.sub('', header) + + if headers[header] > 1 and header not in rendered_headers: + dict_list.append({'title': header, + 'is_header': True, + 'is_in_category': False, + 'collapse_target': collapse_target, + 'count': headers[header]}) + rendered_headers.append(header) + + model_dict.update({'is_in_category': headers[header] > 1, + 'collapse_target': collapse_target, + 'created_at': q.created_at, + 'is_header': False, + 'run_count': q.run_count, + 'created_by_user': six.text_type(q.created_by_user) if q.created_by_user else None}) + dict_list.append(model_dict) + return dict_list + + model = Query + + +~~class ListQueryLogView(PermissionRequiredMixin, ExplorerContextMixin, ListView): + + permission_required = 'view_permission' + + def get_queryset(self): + kwargs = {'sql__isnull': False} + if url_get_query_id(self.request): + kwargs['query_id'] = url_get_query_id(self.request) + return QueryLog.objects.filter(**kwargs).all() + + context_object_name = "recent_logs" + model = QueryLog + paginate_by = 20 + + +class CreateQueryView(PermissionRequiredMixin, ExplorerContextMixin, CreateView): + + permission_required = 'change_permission' + + def form_valid(self, form): + form.instance.created_by_user = self.request.user + return super(CreateQueryView, self).form_valid(form) + + form_class = QueryForm + template_name = 'explorer/query.html' + + +## ... source file continues with no further ListView examples... + +``` + + +## Example 4 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / article.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/article.py) + +```python +# article.py +import difflib +import logging +from urllib.parse import urljoin + +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.db import transaction +from django.db.models import Q +from django.http import Http404 +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.shortcuts import render +from django.urls import reverse +from django.utils.decorators import method_decorator +from django.utils.translation import gettext as _ +from django.utils.translation import ngettext +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.generic import DetailView +from django.views.generic import FormView +~~from django.views.generic import ListView +from django.views.generic import RedirectView +from django.views.generic import TemplateView +from django.views.generic import View +from wiki import editors +from wiki import forms +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.exceptions import NoRootURL +from wiki.core.paginator import WikiPaginator +from wiki.core.plugins import registry as plugin_registry +from wiki.core.utils import object_to_json_response +from wiki.decorators import get_article +from wiki.views.mixins import ArticleMixin + +log = logging.getLogger(__name__) + + +class ArticleView(ArticleMixin, TemplateView): + + template_name = "wiki/view.html" + + @method_decorator(get_article(can_read=True)) + + +## ... source file abbreviated to get to ListView examples ... + + + + @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + def get_context_data(self, **kwargs): + kwargs["selected_tab"] = "source" + return super().get_context_data(**kwargs) + + +~~class History(ListView, ArticleMixin): + + template_name = "wiki/history.html" + allow_empty = True + context_object_name = "revisions" + paginator_class = WikiPaginator + paginate_by = 10 + + def get_queryset(self): + return models.ArticleRevision.objects.filter(article=self.article).order_by( + "-created" + ) + + def get_context_data(self, **kwargs): + kwargs_article = ArticleMixin.get_context_data(self, **kwargs) +~~ kwargs_listview = ListView.get_context_data(self, **kwargs) + kwargs.update(kwargs_article) + kwargs.update(kwargs_listview) + kwargs["selected_tab"] = "history" + return kwargs + + @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + +~~class Dir(ListView, ArticleMixin): + + template_name = "wiki/dir.html" + allow_empty = True + context_object_name = "directory" + model = models.URLPath + paginator_class = WikiPaginator + paginate_by = 30 + + @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + self.filter_form = forms.DirFilterForm(request.GET) + if self.filter_form.is_valid(): + self.query = self.filter_form.cleaned_data["query"] + else: + self.query = None + return super().dispatch(request, article, *args, **kwargs) + + def get_queryset(self): + children = self.urlpath.get_children().can_read(self.request.user) + if self.query: + children = children.filter( + Q(article__current_revision__title__icontains=self.query) + | Q(slug__icontains=self.query) + ) + if not self.article.can_moderate(self.request.user): + children = children.active() + children = children.select_related_common().order_by( + "article__current_revision__title" + ) + return children + + def get_context_data(self, **kwargs): + kwargs_article = ArticleMixin.get_context_data(self, **kwargs) +~~ kwargs_listview = ListView.get_context_data(self, **kwargs) + kwargs.update(kwargs_article) + kwargs.update(kwargs_listview) + kwargs["filter_query"] = self.query + kwargs["filter_form"] = self.filter_form + + updated_children = kwargs[self.context_object_name] + for child in updated_children: + child.set_cached_ancestors_from_parent(self.urlpath) + kwargs[self.context_object_name] = updated_children + + return kwargs + + +~~class SearchView(ListView): + + template_name = "wiki/search.html" + paginator_class = WikiPaginator + paginate_by = 25 + context_object_name = "articles" + + def dispatch(self, request, *args, **kwargs): + self.urlpath = None + if request.user.is_anonymous and not settings.ANONYMOUS: + return redirect(settings.LOGIN_URL) + self.search_form = forms.SearchForm(request.GET) + if self.search_form.is_valid(): + self.query = self.search_form.cleaned_data["q"] + else: + self.query = None + return super().dispatch(request, *args, **kwargs) + + def get_queryset(self): + if not self.query: + return models.Article.objects.none().order_by("-current_revision__created") + articles = models.Article.objects + path = self.kwargs.get("path", None) + if path: + try: + + def get_initial(self): + return { + "revision": self.article.current_revision, + "purge": True, + } + + def get_context_data(self, **kwargs): + kwargs["purge_form"] = self.get_form() + kwargs["form"] = kwargs["purge_form"] + return super().get_context_data(**kwargs) + + +class Source(ArticleMixin, TemplateView): + template_name = "wiki/source.html" + + +## ... source file continues with no further ListView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-redirectview.markdown b/content/pages/examples/django/django-views-generic-redirectview.markdown new file mode 100644 index 000000000..360902c83 --- /dev/null +++ b/content/pages/examples/django/django-views-generic-redirectview.markdown @@ -0,0 +1,167 @@ +title: django.views.generic RedirectView Example Code +category: page +slug: django-views-generic-redirectview-examples +sortorder: 500011525 +toc: False +sidebartitle: django.views.generic RedirectView +meta: Python example code for the RedirectView class from the django.views.generic module of the Django project. + + +RedirectView is a class within the django.views.generic module of the Django project. + + +## Example 1 from dccnsys +[dccnsys](https://github.com/dccnconf/dccnsys) is a conference registration +system built with [Django](/django.html). The code is open source under the +[MIT license](https://github.com/dccnconf/dccnsys/blob/master/LICENSE). + +[**dccnsys / wwwdccn / registration / urls.py**](https://github.com/dccnconf/dccnsys/blob/master/wwwdccn/registration/urls.py) + +```python +# urls.py +from django.urls import path +~~from django.views.generic import RedirectView + +from . import views + +urlpatterns = [ +~~ path('', RedirectView.as_view(pattern_name='register-personal'), + name='register'), + path('personal/', views.personal, name='register-personal'), + path('professional/', views.professional, name='register-professional'), + path('subscriptions/', views.subscriptions, name='register-subscriptions'), +] + + + +## ... source file continues with no further RedirectView examples... + +``` + + +## Example 2 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / article.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/article.py) + +```python +# article.py +import difflib +import logging +from urllib.parse import urljoin + +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.db import transaction +from django.db.models import Q +from django.http import Http404 +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.shortcuts import render +from django.urls import reverse +from django.utils.decorators import method_decorator +from django.utils.translation import gettext as _ +from django.utils.translation import ngettext +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.generic import DetailView +from django.views.generic import FormView +from django.views.generic import ListView +~~from django.views.generic import RedirectView +from django.views.generic import TemplateView +from django.views.generic import View +from wiki import editors +from wiki import forms +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.exceptions import NoRootURL +from wiki.core.paginator import WikiPaginator +from wiki.core.plugins import registry as plugin_registry +from wiki.core.utils import object_to_json_response +from wiki.decorators import get_article +from wiki.views.mixins import ArticleMixin + +log = logging.getLogger(__name__) + + +class ArticleView(ArticleMixin, TemplateView): + + template_name = "wiki/view.html" + + @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + + +## ... source file abbreviated to get to RedirectView examples ... + + + form = form_class(self.article, self.request) + self.forms.append(form) + return super().get(*args, **kwargs) + + def get(self, *args, **kwargs): + self.forms = [] + + new_article = models.Article.objects.get(id=self.article.id) + + for Form in self.get_form_classes(): + self.forms.append(Form(new_article, self.request)) + + return super().get(*args, **kwargs) + + def get_success_url(self): + if self.urlpath: + return redirect("wiki:settings", path=self.urlpath.path) + return redirect("wiki:settings", article_id=self.article.id) + + def get_context_data(self, **kwargs): + kwargs["selected_tab"] = "settings" + kwargs["forms"] = self.forms + return super().get_context_data(**kwargs) + + +~~class ChangeRevisionView(RedirectView): + + permanent = False + + @method_decorator(get_article(can_write=True, not_locked=True)) + def dispatch(self, request, article, *args, **kwargs): + self.article = article + self.urlpath = kwargs.pop("kwargs", False) + self.change_revision() + + return super().dispatch(request, *args, **kwargs) + + def get_redirect_url(self, **kwargs): + if self.urlpath: + return reverse("wiki:history", kwargs={"path": self.urlpath.path}) + else: + return reverse("wiki:history", kwargs={"article_id": self.article.id}) + + def change_revision(self): + revision = get_object_or_404( + models.ArticleRevision, article=self.article, id=self.kwargs["revision_id"] + ) + self.article.current_revision = revision + self.article.save() + messages.success( + + +## ... source file continues with no further RedirectView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-templateview.markdown b/content/pages/examples/django/django-views-generic-templateview.markdown new file mode 100644 index 000000000..1b7772dde --- /dev/null +++ b/content/pages/examples/django/django-views-generic-templateview.markdown @@ -0,0 +1,558 @@ +title: django.views.generic TemplateView Example Code +category: page +slug: django-views-generic-templateview-examples +sortorder: 500011526 +toc: False +sidebartitle: django.views.generic TemplateView +meta: Python example code for the TemplateView class from the django.views.generic module of the Django project. + + +TemplateView is a class within the django.views.generic module of the Django project. + + +## Example 1 from django-markdown-view +[django-markdown-view](https://github.com/rgs258/django-markdown-view) +([PyPI package information](https://pypi.org/project/django-markdown-view/)) +is a Django extension for serving [Markdown](/markdown.html) files as +[Django templates](/django-templates.html). The project is open +sourced under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/rgs258/django-markdown-view/blob/master/LICENSE). + +[**django-markdown-view / markdown_view / views.py**](https://github.com/rgs258/django-markdown-view/blob/master/markdown_view/./views.py) + +```python +# views.py +import logging + +import markdown +from django.conf import settings +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin +from django.template import Engine, Template, Context +from django.template.loader import render_to_string +from django.utils.safestring import mark_safe +~~from django.views.generic import TemplateView +from markdown_view.constants import ( + DEFAULT_MARKDOWN_VIEW_LOADERS, + DEFAULT_MARKDOWN_VIEW_EXTENSIONS, DEFAULT_MARKDOWN_VIEW_TEMPLATE, + DEFAULT_MARKDOWN_VIEW_USE_REQUEST_CONTEXT, DEFAULT_MARKDOWN_VIEW_EXTRA_CONTEXT, +) + +logger = logging.getLogger(__name__) + + +~~class MarkdownView(TemplateView): + file_name = None + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + if self.file_name: + engine = Engine(loaders=getattr( + settings, "MARKDOWN_VIEW_LOADERS", DEFAULT_MARKDOWN_VIEW_LOADERS) + ) + template = engine.get_template(self.file_name) + md = markdown.Markdown(extensions=getattr( + settings, + "MARKDOWN_VIEW_EXTENSIONS", + DEFAULT_MARKDOWN_VIEW_EXTENSIONS + )) + template = Template( + "{{% load static %}}{}".format(md.convert(template.source)) + ) + render_context_base = {} + if getattr( + settings, + "MARKDOWN_VIEW_USE_REQUEST_CONTEXT", + DEFAULT_MARKDOWN_VIEW_USE_REQUEST_CONTEXT + ): + render_context_base = context + + +## ... source file continues with no further TemplateView examples... + +``` + + +## Example 2 from django-mongonaut +[django-mongonaut](https://github.com/jazzband/django-mongonaut) +([project documentation](https://django-mongonaut.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-mongonaut/)) +provides an introspective interface for working with +[MongoDB](/mongodb.html) via mongoengine. The project has its own new code +to map MongoDB to the [Django](/django.html) Admin interface. + +django-mongonaut's highlighted features include automatic introspection of +mongoengine documents, the ability to constrain who sees what and what +they can do and full control for adding, editing and deleting documents. + +The django-mongonaut project is open sourced under the +[MIT License](https://github.com/jazzband/django-mongonaut/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-mongonaut / mongonaut / views.py**](https://github.com/jazzband/django-mongonaut/blob/master/mongonaut/./views.py) + +```python +# views.py +import math + +from django.contrib import messages +from django.urls import reverse +from django.forms import Form +from django.http import HttpResponseForbidden +from django.http import Http404 +from django.utils.functional import cached_property +from django.views.generic.edit import DeletionMixin +from django.views.generic import ListView +~~from django.views.generic import TemplateView +from django.views.generic.edit import FormView +from mongoengine.fields import EmbeddedDocumentField, ListField + +from mongonaut.forms import MongoModelForm +from mongonaut.mixins import MongonautFormViewMixin +from mongonaut.mixins import MongonautViewMixin +from mongonaut.utils import is_valid_object_id + + +class IndexView(MongonautViewMixin, ListView): + + template_name = "mongonaut/index.html" + queryset = [] + permission = 'has_view_permission' + + def get_queryset(self): + return self.get_mongoadmins() + + +class DocumentListView(MongonautViewMixin, FormView): + form_class = Form + success_url = '/' + template_name = "mongonaut/document_list.html" + permission = 'has_view_permission' + + +## ... source file abbreviated to get to TemplateView examples ... + + + for key in [x for x in self.mongoadmin.list_fields if x != 'id' and x in self.document._fields.keys()]: + + if isinstance(self.document._fields[key], EmbeddedDocumentField): + continue + if isinstance(self.document._fields[key], ListField): + continue + context['keys'].append(key) + + if self.mongoadmin.search_fields: + context['search_field'] = True + + return context + + def post(self, request, *args, **kwargs): + form_class = self.get_form_class() + form = self.get_form(form_class) + mongo_ids = self.get_initial()['mongo_id'] + for form_mongo_id in form.data.getlist('mongo_id'): + for mongo_id in mongo_ids: + if form_mongo_id == mongo_id: + self.document.objects.get(pk=mongo_id).delete() + + return self.form_invalid(form) + + +~~class DocumentDetailView(MongonautViewMixin, TemplateView): + template_name = "mongonaut/document_detail.html" + permission = 'has_view_permission' + + def get_context_data(self, **kwargs): + context = super(DocumentDetailView, self).get_context_data(**kwargs) + self.set_mongoadmin() + context = self.set_permissions_in_context(context) + self.document_type = getattr(self.models, self.document_name) + self.ident = self.kwargs.get('id') + self.document = self.document_type.objects.get(pk=self.ident) + + context['document'] = self.document + context['app_label'] = self.app_label + context['document_name'] = self.document_name + context['keys'] = ['id', ] + context['embedded_documents'] = [] + context['list_fields'] = [] + for key in sorted([x for x in self.document._fields.keys() if x != 'id']): + if isinstance(self.document._fields[key], EmbeddedDocumentField): + context['embedded_documents'].append(key) + continue + if isinstance(self.document._fields[key], ListField): + context['list_fields'].append(key) + continue + + +## ... source file abbreviated to get to TemplateView examples ... + + + def get_context_data(self, **kwargs): + context = super(DocumentAddFormView, self).get_context_data(**kwargs) + self.set_mongoadmin() + context = self.set_permissions_in_context(context) + self.document_type = getattr(self.models, self.document_name) + + context['app_label'] = self.app_label + context['document_name'] = self.document_name + context['form_action'] = reverse('document_detail_add_form', args=[self.kwargs.get('app_label'), + self.kwargs.get('document_name')]) + + return context + + def get_form(self): + self.set_mongonaut_base() + self.document_type = getattr(self.models, self.document_name) + self.form = Form() + + if self.request.method == 'POST': + self.form = self.process_post_form('Your new document has been added and saved.') + else: + self.form = MongoModelForm(model=self.document_type).get_form() + return self.form + + +~~class DocumentDeleteView(DeletionMixin, MongonautViewMixin, TemplateView): + + success_url = "/" + template_name = "mongonaut/document_delete.html" + + def get_success_url(self): + self.set_mongonaut_base() + messages.add_message(self.request, messages.INFO, 'Your document has been deleted.') + return reverse('document_list', kwargs={'app_label': self.app_label, 'document_name': self.document_name}) + + def get_object(self): + self.set_mongoadmin() + self.document_type = getattr(self.models, self.document_name) + self.ident = self.kwargs.get('id') + self.document = self.document_type.objects.get(pk=self.ident) + return self.document + + + +## ... source file continues with no further TemplateView examples... + +``` + + +## Example 3 from django-smithy +[django-smithy](https://github.com/jamiecounsell/django-smithy) is +a [Django](/django.html) code library that allows users to send +HTTP requests from the Django admin user interface. The code for +the project is open source under the +[MIT license](https://github.com/jamiecounsell/django-smithy/blob/master/LICENSE). + +[**django-smithy / smithy / urls.py**](https://github.com/jamiecounsell/django-smithy/blob/master/smithy/./urls.py) + +```python +# urls.py +from django.conf.urls import url +~~from django.views.generic import TemplateView + +from . import views + + +app_name = 'smithy' + +urlpatterns = [ + +] + + + +## ... source file continues with no further TemplateView examples... + +``` + + +## Example 4 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / article.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/article.py) + +```python +# article.py +import difflib +import logging +from urllib.parse import urljoin + +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.db import transaction +from django.db.models import Q +from django.http import Http404 +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.shortcuts import render +from django.urls import reverse +from django.utils.decorators import method_decorator +from django.utils.translation import gettext as _ +from django.utils.translation import ngettext +from django.views.decorators.clickjacking import xframe_options_sameorigin +from django.views.generic import DetailView +from django.views.generic import FormView +from django.views.generic import ListView +from django.views.generic import RedirectView +~~from django.views.generic import TemplateView +from django.views.generic import View +from wiki import editors +from wiki import forms +from wiki import models +from wiki.conf import settings +from wiki.core import permissions +from wiki.core.diff import simple_merge +from wiki.core.exceptions import NoRootURL +from wiki.core.paginator import WikiPaginator +from wiki.core.plugins import registry as plugin_registry +from wiki.core.utils import object_to_json_response +from wiki.decorators import get_article +from wiki.views.mixins import ArticleMixin + +log = logging.getLogger(__name__) + + +~~class ArticleView(ArticleMixin, TemplateView): + + template_name = "wiki/view.html" + + @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + +## ... source file abbreviated to get to TemplateView examples ... + + + try: + root = models.URLPath.root() + except NoRootURL: + pass + else: + if root.article: + return redirect("wiki:get", path=root.path) + + root.delete() + return super().dispatch(request, *args, **kwargs) + + def form_valid(self, form): + models.URLPath.create_root( + title=form.cleaned_data["title"], + content=form.cleaned_data["content"], + request=self.request, + ) + return redirect("wiki:root") + + def get_context_data(self, **kwargs): + kwargs = super().get_context_data(**kwargs) + kwargs["editor"] = editors.getEditor() + return kwargs + + +~~class MissingRootView(TemplateView): + template_name = "wiki/root_missing.html" + + + def get_context_data(self, **kwargs): + kwargs["selected_tab"] = "view" + return ArticleMixin.get_context_data(self, **kwargs) + + +class Create(FormView, ArticleMixin): + form_class = forms.CreateForm + template_name = "wiki/create.html" + + @method_decorator(get_article(can_write=True, can_create=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + def get_form(self, form_class=None): + if form_class is None: + form_class = self.get_form_class() + kwargs = self.get_form_kwargs() + + +## ... source file abbreviated to get to TemplateView examples ... + + + self.article.add_revision(revision) + messages.success( + request, + _('The article "%s" and its children are now restored.') + % revision.title, + ) + if self.urlpath: + return redirect("wiki:get", path=self.urlpath.path) + else: + return redirect("wiki:get", article_id=article.id) + + return super().dispatch1(request, article, *args, **kwargs) + + def get_initial(self): + return { + "revision": self.article.current_revision, + "purge": True, + } + + def get_context_data(self, **kwargs): + kwargs["purge_form"] = self.get_form() + kwargs["form"] = kwargs["purge_form"] + return super().get_context_data(**kwargs) + + +~~class Source(ArticleMixin, TemplateView): + template_name = "wiki/source.html" + + @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + def get_context_data(self, **kwargs): + kwargs["selected_tab"] = "source" + return super().get_context_data(**kwargs) + + +class History(ListView, ArticleMixin): + + template_name = "wiki/history.html" + allow_empty = True + context_object_name = "revisions" + paginator_class = WikiPaginator + paginate_by = 10 + + def get_queryset(self): + return models.ArticleRevision.objects.filter(article=self.article).order_by( + "-created" + ) + + + +## ... source file abbreviated to get to TemplateView examples ... + + + | Q(current_revision__content__icontains=self.query) + ) + if not permissions.can_moderate( + models.URLPath.root().article, self.request.user + ): + articles = articles.active().can_read(self.request.user) + return articles.order_by("-current_revision__created") + + def get_context_data(self, **kwargs): + kwargs = super().get_context_data(**kwargs) + kwargs["search_form"] = self.search_form + kwargs["search_query"] = self.query + kwargs["urlpath"] = self.urlpath + return kwargs + + +class Plugin(View): + def dispatch(self, request, path=None, slug=None, **kwargs): + kwargs["path"] = path + for plugin in list(plugin_registry.get_plugins().values()): + if getattr(plugin, "slug", None) == slug: + return plugin.article_view(request, **kwargs) + raise Http404() + + +~~class Settings(ArticleMixin, TemplateView): + + permission_form_class = forms.PermissionsForm + template_name = "wiki/settings.html" + + @method_decorator(login_required) + @method_decorator(get_article(can_read=True)) + def dispatch(self, request, article, *args, **kwargs): + return super().dispatch(request, article, *args, **kwargs) + + def get_form_classes(self): + settings_forms = [] + if permissions.can_change_permissions(self.article, self.request.user): + settings_forms.append(self.permission_form_class) + plugin_forms = [F for F in plugin_registry.get_settings_forms()] + plugin_forms.sort(key=lambda form: form.settings_order) + settings_forms += plugin_forms + for i in range(len(settings_forms)): + setattr(settings_forms[i], "action", "form%d" % i) + + return settings_forms + + def post(self, *args, **kwargs): + self.forms = [] + for form_class in self.get_form_classes(): + + +## ... source file abbreviated to get to TemplateView examples ... + + + self.change_revision() + + return super().dispatch(request, *args, **kwargs) + + def get_redirect_url(self, **kwargs): + if self.urlpath: + return reverse("wiki:history", kwargs={"path": self.urlpath.path}) + else: + return reverse("wiki:history", kwargs={"article_id": self.article.id}) + + def change_revision(self): + revision = get_object_or_404( + models.ArticleRevision, article=self.article, id=self.kwargs["revision_id"] + ) + self.article.current_revision = revision + self.article.save() + messages.success( + self.request, + _( + "The article %(title)s is now set to display revision #%(revision_number)d" + ) + % {"title": revision.title, "revision_number": revision.revision_number}, + ) + + +~~class Preview(ArticleMixin, TemplateView): + + template_name = "wiki/preview_inline.html" + + @method_decorator(xframe_options_sameorigin) + @method_decorator(get_article(can_read=True, deleted_contents=True)) + def dispatch(self, request, article, *args, **kwargs): + revision_id = request.GET.get("r", None) + self.title = None + self.content = None + self.preview = False + if revision_id: + try: + revision_id = int(revision_id) + except ValueError: + raise Http404() + self.revision = get_object_or_404( + models.ArticleRevision, article=article, id=revision_id + ) + else: + self.revision = None + return super().dispatch(request, article, *args, **kwargs) + + def post(self, request, *args, **kwargs): + edit_form = forms.EditForm( + + +## ... source file continues with no further TemplateView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-updateview.markdown b/content/pages/examples/django/django-views-generic-updateview.markdown new file mode 100644 index 000000000..c6611223b --- /dev/null +++ b/content/pages/examples/django/django-views-generic-updateview.markdown @@ -0,0 +1,195 @@ +title: django.views.generic UpdateView Example Code +category: page +slug: django-views-generic-updateview-examples +sortorder: 500011527 +toc: False +sidebartitle: django.views.generic UpdateView +meta: Python example code for the UpdateView class from the django.views.generic module of the Django project. + + +UpdateView is a class within the django.views.generic module of the Django project. + + +## Example 1 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / dashboard / views.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/dashboard/views.py) + +```python +# views.py +from django.contrib import messages +from django.core.exceptions import ValidationError +try: + from django.core.urlresolvers import reverse +except ImportError: # Django 1.11 + from django.urls import reverse + +from django.forms.formsets import formset_factory +from django.http import HttpResponseRedirect +from django.views.decorators.http import require_POST, require_GET +from jet.dashboard.forms import UpdateDashboardModulesForm, AddUserDashboardModuleForm, \ + UpdateDashboardModuleCollapseForm, RemoveDashboardModuleForm, ResetDashboardForm +from jet.dashboard.models import UserDashboardModule +from jet.utils import JsonResponse, get_app_list, SuccessMessageMixin, user_is_authenticated +~~from django.views.generic import UpdateView +from django.utils.translation import ugettext_lazy as _ + + +~~class UpdateDashboardModuleView(SuccessMessageMixin, UpdateView): + model = UserDashboardModule + fields = ('title',) + template_name = 'jet.dashboard/update_module.html' + success_message = _('Widget was successfully updated') + object = None + module = None + + def has_permission(self, request): + return request.user.is_active and request.user.is_staff + + def get_success_url(self): + if self.object.app_label: + return reverse('admin:app_list', kwargs={'app_label': self.object.app_label}) + else: + return reverse('admin:index') + + def get_module(self): + object = self.object if getattr(self, 'object', None) is not None else self.get_object() + return object.load_module() + + def get_settings_form_kwargs(self): + kwargs = { + 'initial': self.module.settings + } + + +## ... source file continues with no further UpdateView examples... + +``` + + +## Example 2 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / accounts.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/accounts.py) + +```python +# accounts.py +from django.conf import settings as django_settings +from django.contrib import messages +from django.contrib.auth import get_user_model +from django.contrib.auth import login as auth_login +from django.contrib.auth import logout as auth_logout +from django.contrib.auth.forms import AuthenticationForm +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.shortcuts import render +from django.urls import reverse +from django.utils.translation import gettext as _ +from django.views.generic import CreateView +from django.views.generic import FormView +~~from django.views.generic import UpdateView +from django.views.generic import View +from wiki import forms +from wiki.conf import settings + +User = get_user_model() + + +class Signup(CreateView): + model = User + form_class = forms.UserCreationForm + template_name = "wiki/accounts/signup.html" + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_anonymous and not request.user.is_superuser: + return redirect("wiki:root") + if not settings.ACCOUNT_HANDLING: + return redirect(settings.SIGNUP_URL) + if not request.user.is_superuser and not settings.ACCOUNT_SIGNUP_ALLOWED: + c = {"error_msg": _("Account signup is only allowed for administrators.")} + return render(request, "wiki/error.html", context=c) + + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + + +## ... source file abbreviated to get to UpdateView examples ... + + + kwargs["request"] = self.request + return kwargs + + def post(self, request, *args, **kwargs): + self.referer = request.session.get("login_referer", "") + return super().post(request, *args, **kwargs) + + def get(self, request, *args, **kwargs): + self.referer = request.META.get("HTTP_REFERER", "") + request.session["login_referer"] = self.referer + return super().get(request, *args, **kwargs) + + def form_valid(self, form, *args, **kwargs): + auth_login(self.request, form.get_user()) + messages.info(self.request, _("You are now logged in! Have fun!")) + if self.request.GET.get("next", None): + return redirect(self.request.GET["next"]) + if django_settings.LOGIN_REDIRECT_URL: + return redirect(django_settings.LOGIN_REDIRECT_URL) + else: + if not self.referer: + return redirect("wiki:root") + return redirect(self.referer) + + +~~class Update(UpdateView): + model = User + form_class = forms.UserUpdateForm + template_name = "wiki/accounts/account_settings.html" + + def get_object(self, queryset=None): + return get_object_or_404(self.model, pk=self.request.user.pk) + + def get(self, request, *args, **kwargs): + self.referer = request.META.get("HTTP_REFERER", "") + request.session["login_referer"] = self.referer + return super().get(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + self.referer = request.session.get("login_referer", "") + return super().post(request, *args, **kwargs) + + def form_valid(self, form): + pw = form.cleaned_data["password1"] + if pw != "": + self.object.set_password(pw) + self.object.save() + + messages.info(self.request, _("Account info saved!")) + + + +## ... source file continues with no further UpdateView examples... + +``` + diff --git a/content/pages/examples/django/django-views-generic-view.markdown b/content/pages/examples/django/django-views-generic-view.markdown new file mode 100644 index 000000000..31740938d --- /dev/null +++ b/content/pages/examples/django/django-views-generic-view.markdown @@ -0,0 +1,427 @@ +title: django.views.generic View Example Code +category: page +slug: django-views-generic-view-examples +sortorder: 500011528 +toc: False +sidebartitle: django.views.generic View +meta: Python example code for the View class from the django.views.generic module of the Django project. + + +View is a class within the django.views.generic module of the Django project. + + +## Example 1 from django-angular +[django-angular](https://github.com/jrief/django-angular) +([project examples website](https://django-angular.awesto.com/classic_form/)) +is a library with helper code to make it easier to use +[Angular](/angular.html) as the front-end to [Django](/django.html) projects. +The code for django-angular is +[open source under the MIT license](https://github.com/jrief/django-angular/blob/master/LICENSE.txt). + +[**django-angular / djng / views / upload.py**](https://github.com/jrief/django-angular/blob/master/djng/views/upload.py) + +```python +# upload.py +from django.core.exceptions import SuspiciousMultipartForm +from django.core import signing +~~from django.views.generic import View +from django.http import JsonResponse + +from djng import app_settings +from djng.forms.fields import FileField, ImageField + + +~~class FileUploadView(View): + storage = app_settings.upload_storage + thumbnail_size = app_settings.THUMBNAIL_OPTIONS + signer = signing.Signer() + + def post(self, request, *args, **kwargs): + if request.POST.get('filetype') == 'file': + field = FileField + elif request.POST.get('filetype') == 'image': + field = ImageField + else: + raise SuspiciousMultipartForm("Missing attribute 'filetype' in form data.") + data = {} + for name, file_obj in request.FILES.items(): + data[name] = field.preview(file_obj) + return JsonResponse(data) + + + +## ... source file continues with no further View examples... + +``` + + +## Example 2 from django-filter +[django-filter](https://github.com/carltongibson/django-filter) +([project documentation](https://django-filter.readthedocs.io/en/master/) +and +[PyPI page](https://pypi.org/project/django-filter/2.2.0/)) +makes it easier to filter down querysets from the +[Django ORM](/django-orm.html) by providing common bits of boilerplate +code. django-filter is provided as +[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE). + +[**django-filter / django_filters / views.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./views.py) + +```python +# views.py +from django.core.exceptions import ImproperlyConfigured +~~from django.views.generic import View +from django.views.generic.list import ( + MultipleObjectMixin, + MultipleObjectTemplateResponseMixin +) + +from .constants import ALL_FIELDS +from .filterset import filterset_factory +from .utils import MigrationNotice, RenameAttributesBase + + +class FilterMixinRenames(RenameAttributesBase): + renamed_attributes = ( + ('filter_fields', 'filterset_fields', MigrationNotice), + ) + + +class FilterMixin(metaclass=FilterMixinRenames): + filterset_class = None + filterset_fields = ALL_FIELDS + strict = True + + def get_filterset_class(self): + if self.filterset_class: + return self.filterset_class + + +## ... source file abbreviated to get to View examples ... + + + kwargs = self.get_filterset_kwargs(filterset_class) + return filterset_class(**kwargs) + + def get_filterset_kwargs(self, filterset_class): + kwargs = { + 'data': self.request.GET or None, + 'request': self.request, + } + try: + kwargs.update({ + 'queryset': self.get_queryset(), + }) + except ImproperlyConfigured: + if filterset_class._meta.model is None: + msg = ("'%s' does not define a 'model' and the view '%s' does " + "not return a valid queryset from 'get_queryset'. You " + "must fix one of them.") + args = (filterset_class.__name__, self.__class__.__name__) + raise ImproperlyConfigured(msg % args) + return kwargs + + def get_strict(self): + return self.strict + + +~~class BaseFilterView(FilterMixin, MultipleObjectMixin, View): + + def get(self, request, *args, **kwargs): + filterset_class = self.get_filterset_class() + self.filterset = self.get_filterset(filterset_class) + + if not self.filterset.is_bound or self.filterset.is_valid() or not self.get_strict(): + self.object_list = self.filterset.qs + else: + self.object_list = self.filterset.queryset.none() + + context = self.get_context_data(filter=self.filterset, + object_list=self.object_list) + return self.render_to_response(context) + + +class FilterView(MultipleObjectTemplateResponseMixin, BaseFilterView): + template_name_suffix = '_filter' + + +def object_filter(request, model=None, queryset=None, template_name=None, + extra_context=None, context_processors=None, + filter_class=None): + class ECFilterView(FilterView): + def get_context_data(self, **kwargs): + + +## ... source file continues with no further View examples... + +``` + + +## Example 3 from django-oauth-toolkit +[django-oauth-toolkit](https://github.com/jazzband/django-oauth-toolkit) +([project website](http://dot.evonove.it/) and +[PyPI package information](https://pypi.org/project/django-oauth-toolkit/1.2.0/)) +is a code library for adding and handling [OAuth2](https://oauth.net/) +flows within your [Django](/django.html) web application and +[API](/application-programming-interfaces.html). + +The django-oauth-toolkit project is open sourced under the +[FreeBSD license](https://github.com/jazzband/django-oauth-toolkit/blob/master/LICENSE) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-oauth-toolkit / oauth2_provider / views / generic.py**](https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/views/generic.py) + +```python +# generic.py +~~from django.views.generic import View + +from ..settings import oauth2_settings +from .mixins import ( + ClientProtectedResourceMixin, OAuthLibMixin, ProtectedResourceMixin, + ReadWriteScopedResourceMixin, ScopedResourceMixin +) + + +class InitializationMixin(OAuthLibMixin): + + + server_class = oauth2_settings.OAUTH2_SERVER_CLASS + validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS + oauthlib_backend_class = oauth2_settings.OAUTH2_BACKEND_CLASS + + +~~class ProtectedResourceView(ProtectedResourceMixin, InitializationMixin, View): + pass + + +class ScopedProtectedResourceView(ScopedResourceMixin, ProtectedResourceView): + pass + + +class ReadWriteScopedResourceView(ReadWriteScopedResourceMixin, ProtectedResourceView): + pass + + +~~class ClientProtectedResourceView(ClientProtectedResourceMixin, InitializationMixin, View): + + + pass + + +class ClientProtectedScopedResourceView(ScopedResourceMixin, ClientProtectedResourceView): + + + pass + + + +## ... source file continues with no further View examples... + +``` + + +## Example 4 from django-rest-framework +[Django REST Framework](https://github.com/encode/django-rest-framework) +([project homepage and documentation](https://www.django-rest-framework.org/), +[PyPI package information](https://pypi.org/project/djangorestframework/) +and [more resources on Full Stack Python](/django-rest-framework-drf.html)), +often abbreviated as "DRF", is a popular [Django](/django.html) extension +for building [web APIs](/application-programming-interfaces.html). +The project has fantastic documentation and a wonderful +[quickstart](https://www.django-rest-framework.org/tutorial/quickstart/) +that serve as examples of how to make it easier for newcomers +to get started. + +The project is open sourced under the +[Encode OSS Ltd. license](https://github.com/encode/django-rest-framework/blob/master/LICENSE.md). + +[**django-rest-framework / rest_framework / compat.py**](https://github.com/encode/django-rest-framework/blob/master/rest_framework/./compat.py) + +```python +# compat.py +from django.conf import settings +~~from django.views.generic import View + + +def unicode_http_header(value): + if isinstance(value, bytes): + return value.decode('iso-8859-1') + return value + + +def distinct(queryset, base): + if settings.DATABASES[queryset.db]["ENGINE"] == "django.db.backends.oracle": + return base.filter(pk__in=set(queryset.values_list('pk', flat=True))) + return queryset.distinct() + + +try: + from django.contrib.postgres import fields as postgres_fields +except ImportError: + postgres_fields = None + + +try: + import coreapi +except ImportError: + coreapi = None + +try: + import uritemplate +except ImportError: + uritemplate = None + + +try: + import coreschema +except ImportError: + coreschema = None + + +try: + import yaml +except ImportError: + yaml = None + + +try: + import requests +except ImportError: + requests = None + + +~~if 'patch' not in View.http_method_names: +~~ View.http_method_names = View.http_method_names + ['patch'] + + +try: + import markdown + + HEADERID_EXT_PATH = 'markdown.extensions.toc' + LEVEL_PARAM = 'baselevel' + + def apply_markdown(text): + extensions = [HEADERID_EXT_PATH] + extension_configs = { + HEADERID_EXT_PATH: { + LEVEL_PARAM: '2' + } + } + md = markdown.Markdown( + extensions=extensions, extension_configs=extension_configs + ) + md_filter_add_syntax_highlight(md) + return md.convert(text) +except ImportError: + apply_markdown = None + markdown = None + + + +## ... source file continues with no further View examples... + +``` + + +## Example 5 from django-wiki +[django-wiki](https://github.com/django-wiki/django-wiki) +([project documentation](https://django-wiki.readthedocs.io/en/master/), +[demo](https://demo.django-wiki.org/), +and [PyPI page](https://pypi.org/project/django-wiki/)) +is a wiki system code library for [Django](/django.html) +projects that makes it easier to create user-editable content. +The project aims to provide necessary core features and then +have an easy plugin format for additional features, rather than +having every exhaustive feature built into the core system. +django-wiki is a rewrite of an earlier now-defunct project +named [django-simplewiki](https://code.google.com/p/django-simple-wiki/). + +The code for django-wiki is provided as open source under the +[GNU General Public License 3.0](https://github.com/django-wiki/django-wiki/blob/master/COPYING). + +[**django-wiki / src/wiki / views / accounts.py**](https://github.com/django-wiki/django-wiki/blob/master/src/wiki/views/accounts.py) + +```python +# accounts.py +from django.conf import settings as django_settings +from django.contrib import messages +from django.contrib.auth import get_user_model +from django.contrib.auth import login as auth_login +from django.contrib.auth import logout as auth_logout +from django.contrib.auth.forms import AuthenticationForm +from django.shortcuts import get_object_or_404 +from django.shortcuts import redirect +from django.shortcuts import render +from django.urls import reverse +from django.utils.translation import gettext as _ +from django.views.generic import CreateView +from django.views.generic import FormView +from django.views.generic import UpdateView +~~from django.views.generic import View +from wiki import forms +from wiki.conf import settings + +User = get_user_model() + + +class Signup(CreateView): + model = User + form_class = forms.UserCreationForm + template_name = "wiki/accounts/signup.html" + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_anonymous and not request.user.is_superuser: + return redirect("wiki:root") + if not settings.ACCOUNT_HANDLING: + return redirect(settings.SIGNUP_URL) + if not request.user.is_superuser and not settings.ACCOUNT_SIGNUP_ALLOWED: + c = {"error_msg": _("Account signup is only allowed for administrators.")} + return render(request, "wiki/error.html", context=c) + + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["honeypot_class"] = context["form"].honeypot_class + context["honeypot_jsfunction"] = context["form"].honeypot_jsfunction + return context + + def get_success_url(self, *args): + messages.success( + self.request, _("You are now signed up... and now you can sign in!") + ) + return reverse("wiki:login") + + +~~class Logout(View): + def dispatch(self, request, *args, **kwargs): + if not settings.ACCOUNT_HANDLING: + return redirect(settings.LOGOUT_URL) + return super().dispatch(request, *args, **kwargs) + + def get(self, request, *args, **kwargs): + auth_logout(request) + messages.info(request, _("You are no longer logged in. Bye bye!")) + return redirect("wiki:root") + + +class Login(FormView): + + form_class = AuthenticationForm + template_name = "wiki/accounts/login.html" + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_anonymous: + return redirect("wiki:root") + if not settings.ACCOUNT_HANDLING: + return redirect(settings.LOGIN_URL) + return super().dispatch(request, *args, **kwargs) + + def get_form_kwargs(self): + + +## ... source file continues with no further View examples... + +``` + diff --git a/content/pages/examples/django/django-views-i18n-javascriptcatalog.markdown b/content/pages/examples/django/django-views-i18n-javascriptcatalog.markdown new file mode 100644 index 000000000..192f42952 --- /dev/null +++ b/content/pages/examples/django/django-views-i18n-javascriptcatalog.markdown @@ -0,0 +1,62 @@ +title: django.views.i18n JavaScriptCatalog Example Code +category: page +slug: django-views-i18n-javascriptcatalog-examples +sortorder: 500011541 +toc: False +sidebartitle: django.views.i18n JavaScriptCatalog +meta: Python example code for the JavaScriptCatalog class from the django.views.i18n module of the Django project. + + +JavaScriptCatalog is a class within the django.views.i18n module of the Django project. + + +## Example 1 from django-jet +[django-jet](https://github.com/geex-arts/django-jet) +([project documentation](https://jet.readthedocs.io/en/latest/), +[PyPI project page](https://pypi.org/project/django-jet/) and +[more information](http://jet.geex-arts.com/)) +is a fancy [Django](/django.html) Admin panel replacement. + +The django-jet project is open source under the +[GNU Affero General Public License v3.0](https://github.com/geex-arts/django-jet/blob/dev/LICENSE). + +[**django-jet / jet / urls.py**](https://github.com/geex-arts/django-jet/blob/dev/jet/./urls.py) + +```python +# urls.py +import django +from django.conf.urls import url + +try: +~~ from django.views.i18n import JavaScriptCatalog +~~ javascript_catalog = JavaScriptCatalog.as_view() +except ImportError: # Django < 2.0 + from django.views.i18n import javascript_catalog + +from jet.views import add_bookmark_view, remove_bookmark_view, toggle_application_pin_view, model_lookup_view + + +app_name = 'jet' + +urlpatterns = [ + url( + r'^add_bookmark/$', + add_bookmark_view, + name='add_bookmark' + ), + url( + r'^remove_bookmark/$', + remove_bookmark_view, + name='remove_bookmark' + ), + url( + r'^toggle_application_pin/$', + toggle_application_pin_view, + name='toggle_application_pin' + ), + + +## ... source file continues with no further JavaScriptCatalog examples... + +``` + diff --git a/content/pages/examples/django/django-views-static-serve.markdown b/content/pages/examples/django/django-views-static-serve.markdown new file mode 100644 index 000000000..2721f610f --- /dev/null +++ b/content/pages/examples/django/django-views-static-serve.markdown @@ -0,0 +1,56 @@ +title: django.views.static serve Example Code +category: page +slug: django-views-static-serve-examples +sortorder: 500011542 +toc: False +sidebartitle: django.views.static serve +meta: Python example code for the serve callable from the django.views.static module of the Django project. + + +serve is a callable within the django.views.static module of the Django project. + + +## Example 1 from django-pipeline +[django-pipeline](https://github.com/jazzband/django-pipeline) +([project documentation](https://django-pipeline.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/django-pipeline/)) +is a code library for handling and compressing +[static content assets](/static-content.html) when handling requests in +[Django](/django.html) web applications. + +The django-pipeline project is open sourced under the +[MIT License](https://github.com/jazzband/django-pipeline/blob/master/LICENSE.txt) +and it is maintained by the developer community group +[Jazzband](https://jazzband.co/). + +[**django-pipeline / pipeline / views.py**](https://github.com/jazzband/django-pipeline/blob/master/pipeline/./views.py) + +```python +# views.py +from django.conf import settings as django_settings +from django.core.exceptions import ImproperlyConfigured +~~from django.views.static import serve + +from .collector import default_collector +from .conf import settings + + +def serve_static(request, path, insecure=False, **kwargs): + if not django_settings.DEBUG and not insecure: + raise ImproperlyConfigured("The staticfiles view can only be used in " + "debug mode or if the --insecure " + "option of 'runserver' is used") + + if not settings.PIPELINE_ENABLED and settings.PIPELINE_COLLECTOR_ENABLED: + default_collector.collect(request, files=[path]) + +~~ return serve(request, path, document_root=django_settings.STATIC_ROOT, + **kwargs) + + + +## ... source file continues with no further serve examples... + +``` + diff --git a/content/pages/examples/django/django-views-static-was-modified-since.markdown b/content/pages/examples/django/django-views-static-was-modified-since.markdown new file mode 100644 index 000000000..53b0c42e0 --- /dev/null +++ b/content/pages/examples/django/django-views-static-was-modified-since.markdown @@ -0,0 +1,106 @@ +title: django.views.static was_modified_since Example Code +category: page +slug: django-views-static-was-modified-since-examples +sortorder: 500011543 +toc: False +sidebartitle: django.views.static was_modified_since +meta: Python example code for the was_modified_since callable from the django.views.static module of the Django project. + + +was_modified_since is a callable within the django.views.static module of the Django project. + + +## Example 1 from django-downloadview +[django-downloadview](https://github.com/benoitbryon/django-downloadview) +([project documentation](https://django-downloadview.readthedocs.io/en/1.9/) +and +[PyPI package information](https://pypi.org/project/django-downloadview/)) +is a [Django](/django.html) extension for serving downloads through your +web application. While typically you would use a web server to handle +[static content](/static-content.html), sometimes you need to control +file access, such as requiring a user to register before downloading a +PDF. In that situations, django-downloadview is a handy library to avoid +boilerplate code for common scenarios. + +[**django-downloadview / django_downloadview / views / base.py**](https://github.com/benoitbryon/django-downloadview/blob/master/django_downloadview/views/base.py) + +```python +# base.py +import calendar + +from django.http import Http404, HttpResponseNotModified +from django.views.generic.base import View +~~from django.views.static import was_modified_since + +from django_downloadview import exceptions +from django_downloadview.response import DownloadResponse + + +class DownloadMixin(object): + + response_class = DownloadResponse + + attachment = True + + basename = None + + mimetype = None + + encoding = None + + def get_file(self): + raise NotImplementedError() + + def get_basename(self): + return self.basename + + def get_mimetype(self): + return self.mimetype + + def get_encoding(self): + return self.encoding + +~~ def was_modified_since(self, file_instance, since): + try: + return file_instance.was_modified_since(since) + except (AttributeError, NotImplementedError): + try: + modification_time = calendar.timegm( + file_instance.modified_time.utctimetuple() + ) + size = file_instance.size + except (AttributeError, NotImplementedError) as e: + print("!=======!", e) + return True + else: +~~ return was_modified_since(since, modification_time, size) + + def not_modified_response(self, *response_args, **response_kwargs): + return HttpResponseNotModified(*response_args, **response_kwargs) + + def download_response(self, *response_args, **response_kwargs): + response_kwargs.setdefault("file_instance", self.file_instance) + response_kwargs.setdefault("attachment", self.attachment) + response_kwargs.setdefault("basename", self.get_basename()) + response_kwargs.setdefault("file_mimetype", self.get_mimetype()) + response_kwargs.setdefault("file_encoding", self.get_encoding()) + response = self.response_class(*response_args, **response_kwargs) + return response + + def file_not_found_response(self): + raise Http404() + + def render_to_response(self, *response_args, **response_kwargs): + try: + self.file_instance = self.get_file() + except exceptions.FileNotFound: + return self.file_not_found_response() + since = self.request.META.get("HTTP_IF_MODIFIED_SINCE", None) + if since is not None: + if not self.was_modified_since(self.file_instance, since): + + +## ... source file continues with no further was_modified_since examples... + +``` + diff --git a/content/pages/examples/flask/flask-app-badrequest.markdown b/content/pages/examples/flask/flask-app-badrequest.markdown new file mode 100644 index 000000000..a2c3c3abd --- /dev/null +++ b/content/pages/examples/flask/flask-app-badrequest.markdown @@ -0,0 +1,306 @@ +title: flask.app BadRequest Example Code +category: page +slug: flask-app-badrequest-examples +sortorder: 500021000 +toc: False +sidebartitle: flask.app BadRequest +meta: Example code for understanding how to use the BadRequest class from the flask.app module of the Flask project. + + +[BadRequest](https://github.com/pallets/flask/blob/master/src/flask/app.py) +is an [Exception](https://docs.python.org/3/library/exceptions.html#Exception) +imported into the [Flask](/flask.html) [web framework](/web-frameworks.html) +from the [Werkzeug](https://github.com/pallets/werkzeug) project. It can occur +at runtime when an +[invalid POST request is sent to a URL route](https://stackoverflow.com/questions/14105452/what-is-the-cause-of-the-bad-request-error-when-submitting-form-in-flask-applica) +that accepts POSTs. + +Flask, +Headers, +and ImmutableDict +are several other callables with code examples from the same `flask.app` package. + +These subjects go along with the `BadRequest` code examples: + +* [web development](/web-development.html) and [web design](/web-design.html) +* [Flask](/flask.html) and [web framework](/web-frameworks.html) concepts + + +## Example 1 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / api / __init__.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/api/__init__.py) + +```python +# __init__.py +import functools +import json +import logging +import re +import traceback +from typing import Callable, Dict, List, Optional, Set +import urllib.parse + +from apispec import APISpec, yaml_utils +from apispec.exceptions import DuplicateComponentNameError +from flask import Blueprint, current_app, jsonify, make_response, request, Response +from flask_babel import lazy_gettext as _ +import jsonschema +from marshmallow import Schema, ValidationError +from marshmallow_sqlalchemy.fields import Related, RelatedList +import prison +from sqlalchemy.exc import IntegrityError +~~from werkzeug.exceptions import BadRequest +import yaml + +from .convert import Model2SchemaConverter +from .schemas import get_info_schema, get_item_schema, get_list_schema +from .._compat import as_unicode +from ..const import ( + API_ADD_COLUMNS_RES_KEY, + API_ADD_COLUMNS_RIS_KEY, + API_ADD_TITLE_RES_KEY, + API_ADD_TITLE_RIS_KEY, + API_DESCRIPTION_COLUMNS_RES_KEY, + API_DESCRIPTION_COLUMNS_RIS_KEY, + API_EDIT_COLUMNS_RES_KEY, + API_EDIT_COLUMNS_RIS_KEY, + API_EDIT_TITLE_RES_KEY, + API_EDIT_TITLE_RIS_KEY, + API_FILTERS_RES_KEY, + API_FILTERS_RIS_KEY, + API_LABEL_COLUMNS_RES_KEY, + API_LABEL_COLUMNS_RIS_KEY, + API_LIST_COLUMNS_RES_KEY, + API_LIST_COLUMNS_RIS_KEY, + API_LIST_TITLE_RES_KEY, + API_LIST_TITLE_RIS_KEY, + + +## ... source file abbreviated to get to BadRequest examples ... + + + API_SHOW_COLUMNS_RES_KEY, + API_SHOW_COLUMNS_RIS_KEY, + API_SHOW_TITLE_RES_KEY, + API_SHOW_TITLE_RIS_KEY, + API_URI_RIS_KEY, + PERMISSION_PREFIX, +) +from ..exceptions import FABException, InvalidOrderByColumnFABException +from ..hooks import get_before_request_hooks, wrap_route_handler_with_hooks +from ..security.decorators import permission_name, protect + +log = logging.getLogger(__name__) + + +def get_error_msg(): + if current_app.config.get("FAB_API_SHOW_STACKTRACE"): + return traceback.format_exc() + return "Fatal error" + + +def safe(f): + + def wraps(self, *args, **kwargs): + try: + return f(self, *args, **kwargs) +~~ except BadRequest as e: + return self.response_400(message=str(e)) + except Exception as e: + logging.exception(e) + return self.response_500(message=get_error_msg()) + + return functools.update_wrapper(wraps, f) + + +def rison(schema=None): + + def _rison(f): + def wraps(self, *args, **kwargs): + value = request.args.get(API_URI_RIS_KEY, None) + kwargs["rison"] = dict() + if value: + try: + kwargs["rison"] = prison.loads(value) + except prison.decoder.ParserException: + if current_app.config.get("FAB_API_ALLOW_JSON_QS", True): + try: + kwargs["rison"] = json.loads( + urllib.parse.parse_qs(f"{API_URI_RIS_KEY}={value}").get( + API_URI_RIS_KEY + )[0] + + +## ... source file continues with no further BadRequest examples... + +``` + + +## Example 2 from Flask-WTF +[Flask-WTF](https://github.com/lepture/flask-wtf) +([project documentation](https://flask-wtf.readthedocs.io/) +and +[PyPI page](https://pypi.org/project/Flask-WTF/)) +provides a bridge between [Flask](/flask.html) and the the +[WTForms](https://wtforms.readthedocs.io/en/2.3.x/) form-handling library. +It makes it easier to use WTForms by reducing boilerplate code and +shorter examples for common form operations as well as common security +practices such as [CSRF](/cross-site-request-forgery-csrf.html). + +[**Flask-WTF / flask_wtf / csrf.py**](https://github.com/lepture/flask-wtf/blob/master/flask_wtf/./csrf.py) + +```python +# csrf.py +import hashlib +import logging +import os +import warnings +from urllib.parse import urlparse +from functools import wraps + +from flask import Blueprint, current_app, g, request, session +from itsdangerous import BadData, SignatureExpired, URLSafeTimedSerializer +~~from werkzeug.exceptions import BadRequest +from werkzeug.security import safe_str_cmp +from wtforms import ValidationError +from wtforms.csrf.core import CSRF + +from ._compat import FlaskWTFDeprecationWarning + +__all__ = ('generate_csrf', 'validate_csrf', 'CSRFProtect') +logger = logging.getLogger(__name__) + + +def generate_csrf(secret_key=None, token_key=None): + + secret_key = _get_config( + secret_key, 'WTF_CSRF_SECRET_KEY', current_app.secret_key, + message='A secret key is required to use CSRF.' + ) + field_name = _get_config( + token_key, 'WTF_CSRF_FIELD_NAME', 'csrf_token', + message='A field name is required to use CSRF.' + ) + + if field_name not in g: + s = URLSafeTimedSerializer(secret_key, salt='wtf-csrf-token') + + + +## ... source file abbreviated to get to BadRequest examples ... + + + warnings.warn(FlaskWTFDeprecationWarning( + '"@csrf.error_handler" is deprecated. Use the standard Flask ' + 'error system with "@app.errorhandler(CSRFError)" instead. This ' + 'will be removed in 1.0.' + ), stacklevel=2) + + @wraps(view) + def handler(reason): + response = current_app.make_response(view(reason)) + raise CSRFError(response=response) + + self._error_response = handler + return view + + +class CsrfProtect(CSRFProtect): + + def __init__(self, app=None): + warnings.warn(FlaskWTFDeprecationWarning( + '"flask_wtf.CsrfProtect" has been renamed to "CSRFProtect" ' + 'and will be removed in 1.0.' + ), stacklevel=2) + super().__init__(app=app) + + +~~class CSRFError(BadRequest): + + description = 'CSRF validation failed.' + + +def same_origin(current_uri, compare_uri): + current = urlparse(current_uri) + compare = urlparse(compare_uri) + + return ( + current.scheme == compare.scheme + and current.hostname == compare.hostname + and current.port == compare.port + ) + + + +## ... source file continues with no further BadRequest examples... + +``` + + +## Example 3 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / core / errors.py**](https://github.com/indico/indico/blob/master/indico/core/errors.py) + +```python +# errors.py + + +~~from werkzeug.exceptions import BadRequest, Forbidden, HTTPException, NotFound + +from indico.util.i18n import _ + + +def get_error_description(exception): + try: + description = exception.description + except AttributeError: + return str(exception) + if isinstance(exception, Forbidden) and description == Forbidden.description: + return _('You are not allowed to access this page.') + elif isinstance(exception, NotFound) and description == NotFound.description: + return _("The page you are looking for doesn't exist.") +~~ elif isinstance(exception, BadRequest) and description == BadRequest.description: + return _('The request was invalid or contained invalid arguments.') + else: + return str(description) + + +class IndicoError(Exception): + + +class NoReportError(IndicoError): + + @classmethod + def wrap_exc(cls, exc): + assert isinstance(exc, HTTPException) + exc._disallow_report = True + return exc + + +class UserValueError(NoReportError): + http_status_code = 400 + + + +## ... source file continues with no further BadRequest examples... + +``` + diff --git a/content/pages/examples/flask/flask-app-flask.markdown b/content/pages/examples/flask/flask-app-flask.markdown new file mode 100644 index 000000000..0702a72ad --- /dev/null +++ b/content/pages/examples/flask/flask-app-flask.markdown @@ -0,0 +1,1771 @@ +title: flask.app Flask Example Code +category: page +slug: flask-app-flask-examples +sortorder: 500021001 +toc: False +sidebartitle: flask.app Flask +meta: Example code for understanding how to use the Flask class from the flask.app module of the Flask project. + + +[Flask](https://github.com/pallets/flask/blob/master/src/flask/app.py) is +a class within the `flask.app` module of the [Flask](/flask.html) framework +that implements the [WSGI application specification](/wsgi-servers.html). +This class acts as a central registry for a significant amount of a Flask +application's functionality, including URL rounting, +[template configurations](/template-engines.html), and handling view functions. + +BadRequest, +Headers, +and ImmutableDict +are several other callables with code examples from the same `flask.app` package. + +You should read up on these subjects along with these `Flask` examples: + +* [web development](/web-development.html) and [web design](/web-design.html) +* [Flask](/flask.html) and [web framework](/web-frameworks.html) concepts + + +## Example 1 from Braintree Flask app +[Braintree's Flask example payments app](https://github.com/braintree/braintree_flask_example) +demonstrates how to incorporate this payment provider's +[API](/application-programming-interfaces.html) into your +[Flask](/flask.html) [web application](/web-development.html). +The code is open sourced under the +[MIT license](https://github.com/braintree/braintree_flask_example/blob/master/LICENSE). + +[**Braintree Flask app / app.py**](https://github.com/braintree/braintree_flask_example/blob/master/././app.py) + +```python +# app.py +~~from flask import Flask, redirect, url_for, render_template, request, flash + +import os +from os.path import join, dirname +from dotenv import load_dotenv +import braintree +from gateway import generate_client_token, transact, find_transaction + +load_dotenv() + +~~app = Flask(__name__) +app.secret_key = os.environ.get('APP_SECRET_KEY') + +PORT = int(os.environ.get('PORT', 4567)) + +TRANSACTION_SUCCESS_STATUSES = [ + braintree.Transaction.Status.Authorized, + braintree.Transaction.Status.Authorizing, + braintree.Transaction.Status.Settled, + braintree.Transaction.Status.SettlementConfirmed, + braintree.Transaction.Status.SettlementPending, + braintree.Transaction.Status.Settling, + braintree.Transaction.Status.SubmittedForSettlement +] + +@app.route('/', methods=['GET']) +def index(): + return redirect(url_for('new_checkout')) + +@app.route('/checkouts/new', methods=['GET']) +def new_checkout(): + client_token = generate_client_token() + return render_template('checkouts/new.html', client_token=client_token) + +@app.route('/checkouts/', methods=['GET']) + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 2 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / tests / test_themes.py**](https://github.com/CTFd/CTFd/blob/master/./tests/test_themes.py) + +```python +# test_themes.py + +import os +import shutil + +import pytest +from flask import render_template, render_template_string, request +from jinja2.exceptions import TemplateNotFound +from jinja2.sandbox import SecurityError +from werkzeug.test import Client + +from CTFd.config import TestingConfig +from CTFd.utils import get_config, set_config +from tests.helpers import create_ctfd, destroy_ctfd, gen_user, login_as_user + + +def test_themes_run_in_sandbox(): + app = create_ctfd() + with app.app_context(): + try: + app.jinja_env.from_string( + "{{ ().__class__.__bases__[0].__subclasses__()[40]('./test_utils.py').read() }}" + ).render() + except SecurityError: + pass + except Exception as e: + raise e + destroy_ctfd(app) + + +def test_themes_cant_access_configpy_attributes(): + app = create_ctfd() + with app.app_context(): + assert app.config["SECRET_KEY"] == "AAAAAAAAAAAAAAAAAAAA" + assert ( + app.jinja_env.from_string("{{ get_config('SECRET_KEY') }}").render() + + +## ... source file abbreviated to get to Flask examples ... + + + + r = client.get("/challenges") + assert r.status_code == 200 + assert "Challenges" in r.get_data(as_text=True) + + r = client.get("/scoreboard") + assert r.status_code == 200 + assert "Scoreboard" in r.get_data(as_text=True) + destroy_ctfd(app) + + +def test_that_request_path_hijacking_works_properly(): + app = create_ctfd(setup=False, application_root="/ctf") + assert app.request_class.__name__ == "CTFdRequest" + with app.app_context(): + with app.test_request_context("/challenges"): + assert request.path == "/ctf/challenges" + destroy_ctfd(app) + + app = create_ctfd() + assert app.request_class.__name__ == "CTFdRequest" + with app.app_context(): + with app.test_request_context("/challenges"): + assert request.path == "/challenges" + +~~ from flask import Flask + +~~ test_app = Flask("test") + assert test_app.request_class.__name__ == "Request" + with test_app.test_request_context("/challenges"): + assert request.path == "/challenges" + destroy_ctfd(app) + + +def test_theme_fallback_config(): + + class ThemeFallbackConfig(TestingConfig): + THEME_FALLBACK = False + + app = create_ctfd(config=ThemeFallbackConfig) + try: + os.mkdir(os.path.join(app.root_path, "themes", "foo_fallback")) + except OSError: + pass + + with app.app_context(): + app.config["THEME_FALLBACK"] = False + set_config("ctf_theme", "foo_fallback") + assert app.config["THEME_FALLBACK"] == False + with app.test_client() as client: + try: + r = client.get("/") + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 3 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / tests / test_fab_cli.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/tests/test_fab_cli.py) + +```python +# test_fab_cli.py +import glob +import json +import logging +import os +import tempfile + +from click.testing import CliRunner +~~from flask import Flask +from flask_appbuilder import AppBuilder, SQLA +from flask_appbuilder.cli import ( + create_app, + create_permissions, + create_user, + export_roles, + import_roles, + list_users, + list_views, + reset_password, +) + +from .base import FABTestCase + +logging.basicConfig(format="%(asctime)s:%(levelname)s:%(name)s:%(message)s") +logging.getLogger().setLevel(logging.DEBUG) +log = logging.getLogger(__name__) + +APP_DIR = "myapp" + + +class FlaskTestCase(FABTestCase): + def setUp(self): + pass + + +## ... source file abbreviated to get to Flask examples ... + + + self.assertIn("User bob created.", result.output) + + result = runner.invoke(list_users, []) + self.assertIn("bob", result.output) + + runner.invoke(create_permissions, []) + + runner.invoke(reset_password, ["--username=bob", "--password=bar"]) + + def test_list_views(self): + os.environ["FLASK_APP"] = "app:app" + runner = CliRunner() + with runner.isolated_filesystem(): + result = runner.invoke(list_views, []) + self.assertIn("List of registered views", result.output) + self.assertIn(" Route:/api/v1/security", result.output) + + +class SQLAlchemyImportExportTestCase(FABTestCase): + def setUp(self): + with open("flask_appbuilder/tests/data/roles.json", "r") as fd: + self.expected_roles = json.loads(fd.read()) + + def test_export_roles(self): + with tempfile.TemporaryDirectory() as tmp_dir: +~~ app = Flask("src_app") + app.config.from_object("flask_appbuilder.tests.config_security") + app.config[ + "SQLALCHEMY_DATABASE_URI" + ] = f"sqlite:///{os.path.join(tmp_dir, 'src.db')}" + db = SQLA(app) + app_builder = AppBuilder(app, db.session) # noqa: F841 + cli_runner = app.test_cli_runner() + + path = os.path.join(tmp_dir, "roles.json") + + export_result = cli_runner.invoke(export_roles, [f"--path={path}"]) + + self.assertEqual(export_result.exit_code, 0) + self.assertTrue(os.path.exists(path)) + + with open(path, "r") as fd: + resulting_roles = json.loads(fd.read()) + + for expected_role in self.expected_roles: + match = [ + r for r in resulting_roles if r["name"] == expected_role["name"] + ] + self.assertTrue(match) + resulting_role = match[0] + resulting_role_permission_view_menus = { + (pvm["permission"]["name"], pvm["view_menu"]["name"]) + for pvm in resulting_role["permissions"] + } + expected_role_permission_view_menus = { + (pvm["permission"]["name"], pvm["view_menu"]["name"]) + for pvm in expected_role["permissions"] + } + self.assertEqual( + resulting_role_permission_view_menus, + expected_role_permission_view_menus, + ) + + def test_export_roles_filename(self): + with tempfile.TemporaryDirectory() as tmp_dir: +~~ app = Flask("src_app") + app.config.from_object("flask_appbuilder.tests.config_security") + + app.config[ + "SQLALCHEMY_DATABASE_URI" + ] = f"sqlite:///{os.path.join(tmp_dir, 'src.db')}" + db = SQLA(app) + app_builder = AppBuilder(app, db.session) # noqa: F841 + + owd = os.getcwd() + os.chdir(tmp_dir) + cli_runner = app.test_cli_runner() + export_result = cli_runner.invoke(export_roles) + os.chdir(owd) + + self.assertEqual(export_result.exit_code, 0) + self.assertGreater( + len(glob.glob(os.path.join(tmp_dir, "roles_export_*"))), 0 + ) + + def test_import_roles(self): + with tempfile.TemporaryDirectory() as tmp_dir: +~~ app = Flask("dst_app") + app.config[ + "SQLALCHEMY_DATABASE_URI" + ] = f"sqlite:///{os.path.join(tmp_dir, 'dst.db')}" + db = SQLA(app) + app_builder = AppBuilder(app, db.session) + cli_runner = app.test_cli_runner() + + path = os.path.join(tmp_dir, "roles.json") + + with open(path, "w") as fd: + fd.write(json.dumps(self.expected_roles)) + + self.assertEqual(len(app_builder.sm.get_all_roles()), 2) + + import_result = cli_runner.invoke(import_roles, [f"--path={path}"]) + self.assertEqual(import_result.exit_code, 0) + + resulting_roles = app_builder.sm.get_all_roles() + + for expected_role in self.expected_roles: + match = [r for r in resulting_roles if r.name == expected_role["name"]] + self.assertTrue(match) + resulting_role = match[0] + + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 4 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / app.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/./app.py) + +```python +# app.py +import logging +import logging.config +import os +import sys +import time +import warnings +from datetime import datetime + +~~from flask import Flask, request +from flask_login import current_user +from sqlalchemy import event +from sqlalchemy.engine import Engine +from sqlalchemy.exc import OperationalError, ProgrammingError + +from flaskbb.extensions import (alembic, allows, babel, cache, celery, csrf, + db, debugtoolbar, limiter, login_manager, mail, + redis_store, themes, whooshee) +from flaskbb.plugins import spec +from flaskbb.plugins.manager import FlaskBBPluginManager +from flaskbb.plugins.models import PluginRegistry +from flaskbb.plugins.utils import remove_zombie_plugins_from_db, template_hook +from flaskbb.user.models import Guest, User +from flaskbb.utils.helpers import (app_config_from_env, crop_title, + format_date, format_time, format_datetime, + forum_is_unread, get_alembic_locations, + get_flaskbb_config, is_online, mark_online, + render_template, time_since, time_utcnow, + topic_is_unread) +from flaskbb.utils.requirements import (CanBanUser, CanEditUser, IsAdmin, + IsAtleastModerator, can_delete_topic, + can_edit_post, can_moderate, + can_post_reply, can_post_topic, + has_permission, + permission_with_identity) +from flaskbb.utils.search import (ForumWhoosheer, PostWhoosheer, + TopicWhoosheer, UserWhoosheer) +from flaskbb.utils.settings import flaskbb_config +from flaskbb.utils.translations import FlaskBBDomain + +from . import markup # noqa +from .auth import views as auth_views # noqa +from .deprecation import FlaskBBDeprecation +from .display.navigation import NavigationContentType +from .forum import views as forum_views # noqa +from .management import views as management_views # noqa +from .user import views as user_views # noqa + + +logger = logging.getLogger(__name__) + + +def create_app(config=None, instance_path=None): + +~~ app = Flask( + "flaskbb", instance_path=instance_path, instance_relative_config=True + ) + + if not os.path.exists(app.instance_path): + os.makedirs(app.instance_path) + + configure_app(app, config) + configure_celery_app(app, celery) + configure_extensions(app) + load_plugins(app) + configure_blueprints(app) + configure_template_filters(app) + configure_context_processors(app) + configure_before_handlers(app) + configure_errorhandlers(app) + configure_migrations(app) + configure_translations(app) + app.pluggy.hook.flaskbb_additional_setup(app=app, pluggy=app.pluggy) + + return app + + +def configure_app(app, config): + app.config.from_object("flaskbb.configs.default.DefaultConfig") + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 5 from flask-base +[flask-base](https://github.com/hack4impact/flask-base) +([project documentation](http://hack4impact.github.io/flask-base/)) +provides boilerplate code for new [Flask](/flask.html) web apps. +The purpose of the boilerplate is to stitch together disparate +libraries that are commonly used in Flask projects, such as +[Redis](/redis.html) for fast caching and transient data storage, +[SendGrid](https://www.twilio.com/sendgrid) for transactional email, +[SQLAlchemy](/sqlalchemy.html) for persistent data storage through a +[relational database](/databases.html) backend, +[Flask-WTF](https://flask-wtf.readthedocs.io/) for form +handling and many others. + +flask-base is provided as open source under the +[MIT license](https://github.com/hack4impact/flask-base/blob/master/LICENSE.md). + +[**flask-base / app / __init__.py**](https://github.com/hack4impact/flask-base/blob/master/app/./__init__.py) + +```python +# __init__.py +import os + +~~from flask import Flask +from flask_assets import Environment +from flask_compress import Compress +from flask_login import LoginManager +from flask_mail import Mail +from flask_rq import RQ +from flask_sqlalchemy import SQLAlchemy +from flask_wtf import CSRFProtect + +from app.assets import app_css, app_js, vendor_css, vendor_js +from config import config as Config + +basedir = os.path.abspath(os.path.dirname(__file__)) + +mail = Mail() +db = SQLAlchemy() +csrf = CSRFProtect() +compress = Compress() + +login_manager = LoginManager() +login_manager.session_protection = 'strong' +login_manager.login_view = 'account.login' + + +def create_app(config): +~~ app = Flask(__name__) + config_name = config + + if not isinstance(config, str): + config_name = os.getenv('FLASK_CONFIG', 'default') + + app.config.from_object(Config[config_name]) + app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + + Config[config_name].init_app(app) + + mail.init_app(app) + db.init_app(app) + login_manager.init_app(app) + csrf.init_app(app) + compress.init_app(app) + RQ(app) + + from .utils import register_template_utils + register_template_utils(app) + + assets_env = Environment(app) + dirs = ['assets/styles', 'assets/scripts'] + for path in dirs: + assets_env.append_path(os.path.join(basedir, path)) + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 6 from flask-bones +[flask-bones](https://github.com/cburmeister/flask-bones) +([demo](http://flask-bones.herokuapp.com/)) +is large scale [Flask](/flask.html) example application built +with [Blueprints](https://flask.palletsprojects.com/en/1.1.x/blueprints/) +([example Blueprint code](/flask-blueprints-blueprint-examples.html)). +This project is provided as open source under the +[MIT license](https://github.com/cburmeister/flask-bones/blob/master/LICENSE). + +[**flask-bones / app / __init__.py**](https://github.com/cburmeister/flask-bones/blob/master/app/./__init__.py) + +```python +# __init__.py +import time + +~~from flask import Flask, g, render_template, request +import arrow +import requests + +from app import config +from app.assets import assets +from app.auth import auth +from app.commands import create_db, drop_db, populate_db, recreate_db +from app.database import db +from app.extensions import lm, travis, mail, migrate, bcrypt, babel, rq, limiter +from app.user import user +from app.utils import url_for_other_page + + +def create_app(config=config.base_config): +~~ app = Flask(__name__) + app.config.from_object(config) + + register_extensions(app) + register_blueprints(app) + register_errorhandlers(app) + register_jinja_env(app) + register_commands(app) + + def get_locale(): + return request.accept_languages.best_match(config.SUPPORTED_LOCALES) + + if babel.locale_selector_func is None: + babel.locale_selector_func = get_locale + + @app.before_request + def before_request(): + g.request_start_time = time.time() + g.request_time = lambda: '%.5fs' % (time.time() - g.request_start_time) + g.pjax = 'X-PJAX' in request.headers + + @app.route('/', methods=['GET']) + def index(): + return render_template('index.html') + + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 7 from flask-bookshelf +[flask-bookshelf](https://github.com/damyanbogoev/flask-bookshelf) is the +example [Flask](/flask.html) application that developers create when +going through +[this Flask series of blog posts](https://damyanon.net/tags/flask-series/). + +[**flask-bookshelf / bookshelf / __init__.py**](https://github.com/damyanbogoev/flask-bookshelf/blob/master/bookshelf/./__init__.py) + +```python +# __init__.py +~~from flask import abort, Flask, g, render_template, request, current_app +from flask_babel import Babel +from flask_security import current_user +from bookshelf.utils import get_instance_folder_path +from bookshelf.main.controllers import main +from bookshelf.admin.controllers import admin +from bookshelf.cache import cache +from bookshelf.config import configure_app +from bookshelf.data.models import db + +~~app = Flask( + __name__, + instance_path=get_instance_folder_path(), + instance_relative_config=True, + template_folder="templates", +) + +babel = Babel(app) +configure_app(app) +cache.init_app(app) +db.init_app(app) +app.jinja_env.add_extension("jinja2.ext.loopcontrols") + + +@app.url_defaults +def set_language_code(endpoint, values): + if "lang_code" in values or not g.get("lang_code", None): + return + if app.url_map.is_endpoint_expecting(endpoint, "lang_code"): + values["lang_code"] = g.lang_code + + +@app.url_value_preprocessor +def get_lang_code(endpoint, values): + if values is not None: + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 8 from flaskex +[Flaskex](https://github.com/anfederico/Flaskex) is a working example +[Flask](/flask.html) web application intended as a base to build your +own applications upon. The application comes with pre-built sign up, log in +and related screens, as well as a database backend. Flaskex is provided +as open source under the +[MIT license](https://github.com/anfederico/Flaskex/blob/master/LICENSE.txt). + +[**flaskex / app.py**](https://github.com/anfederico/Flaskex/blob/master/././app.py) + +```python +# app.py + +from scripts import tabledef +from scripts import forms +from scripts import helpers +~~from flask import Flask, redirect, url_for, render_template, request, session +import json +import sys +import os + +~~app = Flask(__name__) +app.secret_key = os.urandom(12) # Generic key for dev purposes only + + +@app.route('/', methods=['GET', 'POST']) +def login(): + if not session.get('logged_in'): + form = forms.LoginForm(request.form) + if request.method == 'POST': + username = request.form['username'].lower() + password = request.form['password'] + if form.validate(): + if helpers.credentials_valid(username, password): + session['logged_in'] = True + session['username'] = username + return json.dumps({'status': 'Login successful'}) + return json.dumps({'status': 'Invalid user/pass'}) + return json.dumps({'status': 'Both fields required'}) + return render_template('login.html', form=form) + user = helpers.get_user() + return render_template('home.html', user=user) + + +@app.route("/logout") +def logout(): + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 9 from Flask-HTTPAuth +[Flask-HTTPAuth](https://github.com/miguelgrinberg/Flask-HTTPAuth) +([documentation](https://flask-httpauth.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/Flask-HTTPAuth/)) +is a [Flask](/flask.html) framework extension that creates +Basic and Digest HTTP authentication for routes. This project +is primarily built and maintained by +[Miguel Grinberg](https://blog.miguelgrinberg.com/). It is provided +as open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/LICENSE). + +[**Flask-HTTPAuth / tests / test_basic_get_password.py**](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/./tests/test_basic_get_password.py) + +```python +# test_basic_get_password.py +import unittest +import base64 +~~from flask import Flask +from flask_httpauth import HTTPBasicAuth + + +class HTTPAuthTestCase(unittest.TestCase): + def setUp(self): +~~ app = Flask(__name__) + app.config['SECRET_KEY'] = 'my secret' + + basic_auth = HTTPBasicAuth() + + @basic_auth.get_password + def get_basic_password(username): + if username == 'john': + return 'hello' + elif username == 'susan': + return 'bye' + else: + return None + + @app.route('/') + def index(): + return 'index' + + @app.route('/basic') + @basic_auth.login_required + def basic_auth_route(): + return 'basic_auth:' + basic_auth.username() + + self.app = app + self.basic_auth = basic_auth + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 10 from flask-phone-input +[flask-phone-input](https://github.com/miguelgrinberg/flask-phone-input) +is an example application that ties together the +[intTellInput.js](https://github.com/jackocnr/intl-tel-input) +JavaScript plugin with the +[Flask-WTF](https://flask-wtf.readthedocs.io/) form-handling +library. flask-phone-input is provided as open source under the +[MIT license](https://github.com/miguelgrinberg/flask-phone-input/blob/1a1c227c044474ce0fe133493d7f8b0fb8312409/LICENSE). + +[**flask-phone-input / app.py**](https://github.com/miguelgrinberg/flask-phone-input/blob/master/././app.py) + +```python +# app.py +~~from flask import Flask, render_template, session, redirect, url_for +from flask_bootstrap import Bootstrap +from flask_wtf import FlaskForm +import phonenumbers +from wtforms import StringField, SubmitField +from wtforms.validators import DataRequired, ValidationError + +~~app = Flask(__name__) +app.config['SECRET_KEY'] = 'top-secret!' +Bootstrap(app) + + +class PhoneForm(FlaskForm): + phone = StringField('Phone', validators=[DataRequired()]) + submit = SubmitField('Submit') + + def validate_phone(self, phone): + try: + p = phonenumbers.parse(phone.data) + if not phonenumbers.is_valid_number(p): + raise ValueError() + except (phonenumbers.phonenumberutil.NumberParseException, ValueError): + raise ValidationError('Invalid phone number') + + +@app.route('/', methods=['GET', 'POST']) +def index(): + form = PhoneForm() + if form.validate_on_submit(): + session['phone'] = form.phone.data + return redirect(url_for('show_phone')) + return render_template('index.html', form=form) + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 11 from flaskSaaS +[flaskSaas](https://github.com/alectrocute/flaskSaaS) is a boilerplate +starter project to build a software-as-a-service (SaaS) web application +in [Flask](/flask.html), with [Stripe](/stripe.html) for billing. The +boilerplate relies on many common Flask extensions such as +[Flask-WTF](https://flask-wtf.readthedocs.io/), +[Flask-Login](https://flask-login.readthedocs.io/en/latest/), +[Flask-Admin](https://flask-admin.readthedocs.io/en/latest/), and +many others. The project is provided as open source under the +[MIT license](https://github.com/alectrocute/flaskSaaS/blob/master/LICENSE). + +[**flaskSaaS / app / __init__.py**](https://github.com/alectrocute/flaskSaaS/blob/master/app/./__init__.py) + +```python +# __init__.py +~~from flask import Flask + +~~app = Flask(__name__) + +app.config.from_object('app.config') + +from app.logger_setup import logger + +from flask.ext.sqlalchemy import SQLAlchemy +db = SQLAlchemy(app) + +from flask.ext.mail import Mail +mail = Mail(app) + +from flask_debugtoolbar import DebugToolbarExtension +app.config['DEBUG_TB_TEMPLATE_EDITOR_ENABLED'] = True +app.config['DEBUG_TB_PROFILER_ENABLED'] = True +toolbar = DebugToolbarExtension(app) + +from flask.ext.bcrypt import Bcrypt +bcrypt = Bcrypt(app) + +from app.views import main, user, error +app.register_blueprint(user.userbp) + +from flask.ext.login import LoginManager +from app.models import User + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 12 from Flask-Security-Too +[Flask-Security-Too](https://github.com/Flask-Middleware/flask-security/) +([PyPi page](https://pypi.org/project/Flask-Security-Too/) and +[project documentation](https://flask-security-too.readthedocs.io/en/stable/)) +is a maintained fork of the original +[Flask-Security](https://github.com/mattupstate/flask-security) project that +makes it easier to add common security features to [Flask](/flask.html) +web applications. A few of the critical goals of the Flask-Security-Too +project are ensuring JavaScript client-based single-page applications (SPAs) +can work securely with Flask-based backends and that guidance by the +[OWASP](https://owasp.org/) organization is followed by default. + +The Flask-Security-Too project is provided as open source under the +[MIT license](https://github.com/Flask-Middleware/flask-security/blob/master/LICENSE). + +[**Flask-Security-Too / flask_security / utils.py**](https://github.com/Flask-Middleware/flask-security/blob/master/flask_security/./utils.py) + +```python +# utils.py + flash, + g, + request, + render_template, + session, + url_for, +) +from flask.json import JSONEncoder +from flask_login import login_user as _login_user +from flask_login import logout_user as _logout_user +from flask_login import current_user +from flask_login import COOKIE_NAME as REMEMBER_COOKIE_NAME +from flask_principal import AnonymousIdentity, Identity, identity_changed, Need +from flask_wtf import csrf +from wtforms import ValidationError +from itsdangerous import BadSignature, SignatureExpired +from werkzeug import __version__ as werkzeug_version +from werkzeug.local import LocalProxy +from werkzeug.datastructures import MultiDict + +from .quart_compat import best, get_quart_status +from .proxies import _security, _datastore, _pwd_context, _hashing_context +from .signals import user_authenticated + +if t.TYPE_CHECKING: # pragma: no cover +~~ from flask import Flask, Response + from .datastore import User + +SB = t.Union[str, bytes] + + +localize_callback = LocalProxy(lambda: _security.i18n_domain.gettext) + +FsPermNeed = partial(Need, "fsperm") +FsPermNeed.__doc__ = """A need with the method preset to `"fsperm"`.""" + + +def _(translate): + return translate + + +def get_request_attr(name: str) -> t.Any: + return getattr(_request_ctx_stack.top, name, None) + + +def set_request_attr(name, value): + return setattr(_request_ctx_stack.top, name, value) + + +if get_quart_status(): # pragma: no cover + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 13 from Flask-SocketIO +[Flask-SocketIO](https://github.com/miguelgrinberg/Flask-SocketIO) +([PyPI package information](https://pypi.org/project/Flask-SocketIO/), +[official tutorial](https://blog.miguelgrinberg.com/post/easy-websockets-with-flask-and-gevent) +and +[project documentation](https://flask-socketio.readthedocs.io/en/latest/)) +is a code library by [Miguel Grinberg](https://blog.miguelgrinberg.com/index) +that provides Socket.IO integration for [Flask](/flask.html) applications. +This extension makes it easier to add bi-directional communications on the +web via the [WebSockets](/websockets.html) protocol. + +The Flask-SocketIO project is open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/LICENSE). + +[**Flask-SocketIO / test_socketio.py**](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/././test_socketio.py) + +```python +# test_socketio.py +import json +import unittest +import coverage + +cov = coverage.coverage(branch=True) +cov.start() + +~~from flask import Flask, session, request, json as flask_json +from flask_socketio import SocketIO, send, emit, join_room, leave_room, \ + Namespace, disconnect + +~~app = Flask(__name__) +app.config['SECRET_KEY'] = 'secret' +socketio = SocketIO(app) +disconnected = None + + +@socketio.on('connect') +def on_connect(): + if request.args.get('fail'): + return False + send('connected') + send(json.dumps(request.args.to_dict(flat=False))) + send(json.dumps({h: request.headers[h] for h in request.headers.keys() + if h not in ['Host', 'Content-Type', 'Content-Length']})) + + +@socketio.on('disconnect') +def on_disconnect(): + global disconnected + disconnected = '/' + + +@socketio.event(namespace='/test') +def connect(): + send('connected-test') + + +## ... source file abbreviated to get to Flask examples ... + + + client.emit('exit', {}, namespace='/ns') + self.assertFalse(client.is_connected('/ns')) + with self.assertRaises(RuntimeError): + client.emit('hello', {}, namespace='/ns') + + def test_emit_class_based(self): + client = socketio.test_client(app, namespace='/ns') + client.get_received('/ns') + client.emit('my_custom_event', {'a': 'b'}, namespace='/ns') + received = client.get_received('/ns') + self.assertEqual(len(received), 1) + self.assertEqual(len(received[0]['args']), 1) + self.assertEqual(received[0]['name'], 'my custom response') + self.assertEqual(received[0]['args'][0]['a'], 'b') + + def test_request_event_data_class_based(self): + client = socketio.test_client(app, namespace='/ns') + client.get_received('/ns') + global request_event_data + request_event_data = None + client.emit('other_custom_event', 'foo', namespace='/ns') + expected_data = {'message': 'other_custom_event', 'args': ('foo',)} + self.assertEqual(request_event_data, expected_data) + + def test_delayed_init(self): +~~ app = Flask(__name__) + socketio = SocketIO(allow_upgrades=False, json=flask_json) + + @socketio.on('connect') + def on_connect(): + send({'connected': 'foo'}, json=True) + + socketio.init_app(app, cookie='foo') + self.assertFalse(socketio.server.eio.allow_upgrades) + self.assertEqual(socketio.server.eio.cookie, 'foo') + + client = socketio.test_client(app) + received = client.get_received() + self.assertEqual(len(received), 1) + self.assertEqual(received[0]['args'], {'connected': 'foo'}) + + def test_encode_decode(self): + client = socketio.test_client(app) + client.get_received() + data = {'foo': 'bar', 'invalid': socketio} + self.assertRaises(TypeError, client.emit, 'my custom event', data, + callback=True) + data = {'foo': 'bar'} + ack = client.emit('my custom event', data, callback=True) + data['foo'] = 'baz' + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 14 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / user_manager.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/./user_manager.py) + +```python +# user_manager.py + + +import datetime + +~~from flask import abort, Blueprint, current_app, Flask, session +from flask_login import LoginManager +from wtforms import ValidationError + +from . import ConfigError +from . import forms +from .db_manager import DBManager +from .email_manager import EmailManager +from .password_manager import PasswordManager +from .token_manager import TokenManager +from .translation_utils import lazy_gettext as _ # map _() to lazy_gettext() +from .user_manager__settings import UserManager__Settings +from .user_manager__utils import UserManager__Utils +from .user_manager__views import UserManager__Views + + +class UserManager(UserManager__Settings, UserManager__Utils, UserManager__Views): + + def __init__(self, app, db, UserClass, **kwargs): + + self.app = app + if app: + self.init_app(app, db, UserClass, **kwargs) + + def init_app( + self, app, db, UserClass, + UserInvitationClass=None, + UserEmailClass=None, + RoleClass=None, # Only used for testing + ): + +~~ if not isinstance(app, Flask): + raise TypeError("flask_user.UserManager.init_app(): Parameter 'app' is an instance of class '%s' " + "instead of a subclass of class 'flask.Flask'." + % app.__class__.__name__) + + app.user_manager = self + + self.db = db + + for attrib_name in dir(self): + if attrib_name[0:5] == 'USER_': + default_value = getattr(UserManager, attrib_name) + setattr(self, attrib_name, app.config.get(attrib_name, default_value)) + + if not self.USER_EMAIL_SENDER_EMAIL: + default_sender = app.config.get('DEFAULT_MAIL_SENDER', None) + default_sender = app.config.get('MAIL_DEFAULT_SENDER', default_sender) + if default_sender: + if default_sender[-1:] == '>': + start = default_sender.rfind('<') + if start >= 1: + self.USER_EMAIL_SENDER_EMAIL = default_sender[start + 1:-1] + if not self.USER_EMAIL_SENDER_NAME: + self.USER_EMAIL_SENDER_NAME = default_sender[0:start].strip(' "') + else: + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 15 from Flask-VueJs-Template +[Flask-VueJs-Template](https://github.com/gtalarico/flask-vuejs-template) +([demo site](https://flask-vuejs-template.herokuapp.com/)) +is a minimal [Flask](/flask.html) boilerplate starter project that +combines Flask, [Vue.js](https://www.fullstackpython.com/vuejs.html), +and [Flask-RESTPlus](https://flask-restplus.readthedocs.io/en/stable/). +The project provides some sensible defaults that are easy to continue +building on, and the source code is open source under the +[MIT license](https://github.com/gtalarico/flask-vuejs-template/blob/master/LICENSE.md). + +[**Flask-VueJs-Template / app / __init__.py**](https://github.com/gtalarico/flask-vuejs-template/blob/master/app/./__init__.py) + +```python +# __init__.py +import os +~~from flask import Flask, current_app, send_file + +from .api import api_bp +from .client import client_bp + +~~app = Flask(__name__, static_folder='../dist/static') +app.register_blueprint(api_bp) + +from .config import Config +app.logger.info('>>> {}'.format(Config.FLASK_ENV)) + +@app.route('/') +def index_client(): + dist_dir = current_app.config['DIST_DIR'] + entry = os.path.join(dist_dir, 'index.html') + return send_file(entry) + + + + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 16 from Flasky +[Flasky](https://github.com/miguelgrinberg/flasky) is a wonderful +example application by +[Miguel Grinberg](https://github.com/miguelgrinberg) that he builds +while teaching developers how to use [Flask](/flask.html) in +[his books and videos](https://courses.miguelgrinberg.com/). Flasky +is [open sourced under the MIT license](https://github.com/miguelgrinberg/flasky/blob/master/LICENSE). + +[**Flasky / app / __init__.py**](https://github.com/miguelgrinberg/flasky/blob/master/./app/__init__.py) + +```python +# __init__.py +~~from flask import Flask +from flask_bootstrap import Bootstrap +from flask_mail import Mail +from flask_moment import Moment +from flask_sqlalchemy import SQLAlchemy +from flask_login import LoginManager +from flask_pagedown import PageDown +from config import config + +bootstrap = Bootstrap() +mail = Mail() +moment = Moment() +db = SQLAlchemy() +pagedown = PageDown() + +login_manager = LoginManager() +login_manager.login_view = 'auth.login' + + +def create_app(config_name): +~~ app = Flask(__name__) + app.config.from_object(config[config_name]) + config[config_name].init_app(app) + + bootstrap.init_app(app) + mail.init_app(app) + moment.init_app(app) + db.init_app(app) + login_manager.init_app(app) + pagedown.init_app(app) + + if app.config['SSL_REDIRECT']: + from flask_sslify import SSLify + sslify = SSLify(app) + + from .main import main as main_blueprint + app.register_blueprint(main_blueprint) + + from .auth import auth as auth_blueprint + app.register_blueprint(auth_blueprint, url_prefix='/auth') + + from .api import api as api_blueprint + app.register_blueprint(api_blueprint, url_prefix='/api/v1') + + return app + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 17 from Datadog Flask Example App +The [Datadog Flask example app](https://github.com/DataDog/trace-examples/tree/master/python/flask) +contains many examples of the [Flask](/flask.html) core functions +available to a developer using the [web framework](/web-frameworks.html). + +[**Datadog Flask Example App / python/flask/app / app.py**](https://github.com/DataDog/trace-examples/blob/master/python/flask/app/./app.py) + +```python +# app.py +from ddtrace import patch_all; patch_all(flask=True, requests=True) # noqa + +from ddtrace import tracer + +~~from flask import Flask, Response +from flask import after_this_request +from flask import abort, jsonify, render_template, url_for +from flask.views import View +from werkzeug.routing import Rule + +from flask_caching import Cache +from flask_cors import CORS + +import requests + +from .blueprint import bp +from .exceptions import AppException +from .limiter import limiter +from .signals import connect_signals + +~~app = Flask(__name__) + +app.register_blueprint(bp) + +connect_signals(app) + +CORS(app) +Cache(app, config=dict(CACHE_TYPE='simple')) +limiter.init_app(app) + + +@app.context_processor +def inject_url_map(): + return dict(url_map=app.url_map) + + +@app.before_first_request +def before_first_request(): + print('Hook: before_first_request') + + +@app.before_request +def before_request(): + print('Hook: before_request') + + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 18 from keras-flask-deploy-webapp +The +[keras-flask-deploy-webapp](https://github.com/mtobeiyf/keras-flask-deploy-webapp) +project combines the [Flask](/flask.html) [web framework](/web-frameworks.html) +with the [Keras deep learning library](https://keras.io/) to provide +an example image classifier that is easy to [deploy](/deployment.html). +The application can be quckly run in a [Docker](/docker.html) container +on your local development environment. The project is licensed under the +[GNU General Public License v3.0](https://github.com/mtobeiyf/keras-flask-deploy-webapp/blob/master/LICENSE). + +[**keras-flask-deploy-webapp / app.py**](https://github.com/mtobeiyf/keras-flask-deploy-webapp/blob/master/././app.py) + +```python +# app.py +import os +import sys + +~~from flask import Flask, redirect, url_for, request, render_template, Response, jsonify, redirect +from werkzeug.utils import secure_filename +from gevent.pywsgi import WSGIServer + +import tensorflow as tf +from tensorflow import keras + +from tensorflow.keras.applications.imagenet_utils import preprocess_input, decode_predictions +from tensorflow.keras.models import load_model +from tensorflow.keras.preprocessing import image + +import numpy as np +from util import base64_to_pil + + +~~app = Flask(__name__) + + + +from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2 +model = MobileNetV2(weights='imagenet') + +print('Model loaded. Check http://127.0.0.1:5000/') + + +MODEL_PATH = 'models/your_model.h5' + + + +def model_predict(img, model): + img = img.resize((224, 224)) + + x = image.img_to_array(img) + x = np.expand_dims(x, axis=0) + + x = preprocess_input(x, mode='tf') + + preds = model.predict(x) + return preds + + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 19 from sandman2 +[sandman2](https://github.com/jeffknupp/sandman2) +([project documentation](https://sandman2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/sandman2/)) +is a code library for automatically generating +[RESTful APIs](/application-programming-interfaces.html) from +existing database schemas. This approach is handy for solving +straightforward situations where you want to put an abstraction +layer between one or more applications and your +[relational database](/databases.html) to prevent or reduce +direct database access. + +The sandman2 project is provided under the +[Apache License 2.0](https://github.com/jeffknupp/sandman2/blob/master/LICENSE). + +[**sandman2 / sandman2 / app.py**](https://github.com/jeffknupp/sandman2/blob/master/sandman2/./app.py) + +```python +# app.py + +~~from flask import Flask, current_app, jsonify +from sqlalchemy.sql import sqltypes + +from sandman2.exception import ( + BadRequestException, + ForbiddenException, + NotFoundException, + NotAcceptableException, + NotImplementedException, + ConflictException, + ServerErrorException, + ServiceUnavailableException, + ) +from sandman2.service import Service +from sandman2.model import db, Model, AutomapModel +from sandman2.admin import CustomAdminView +from flask_admin import Admin +from flask_httpauth import HTTPBasicAuth + +auth = HTTPBasicAuth() + +def get_app( + database_uri, + exclude_tables=None, + user_models=None, + reflect_all=True, + read_only=False, + schema=None): +~~ app = Flask('sandman2') + app.config['SQLALCHEMY_DATABASE_URI'] = database_uri + app.config['SANDMAN2_READ_ONLY'] = read_only + app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + app.classes = [] + db.init_app(app) + admin = Admin(app, base_template='layout.html', template_mode='bootstrap3') + _register_error_handlers(app) + if user_models: + with app.app_context(): + _register_user_models(user_models, admin, schema=schema) + elif reflect_all: + with app.app_context(): + _reflect_all(exclude_tables, admin, read_only, schema=schema) + + @app.route('/') + def index(): + routes = {} + for cls in app.classes: + routes[cls.__model__.__name__] = '{}{{/{}}}'.format( + cls.__model__.__url__, + cls.__model__.primary_key()) + return jsonify(routes) + return app + + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 20 from Science Flask +[Science Flask](https://github.com/danielhomola/science_flask) +is a [Flask](/flask.html)-powered web application for online +scientific research tools. The project was built as a template +for any scientist or groups of scientists to use when working +together without having to really understand how the application +is built. The application includes an academic registration +process (only valid academic email addresses can be used), an +admin panel, logging, and analysis forms. + +[@danielhomola](https://github.com/danielhomola) is the +primary creator of Science Flask and the project is open +source under the +[GNU General Public License](https://github.com/danielhomola/science_flask/blob/master/LICENSE). + +[**Science Flask / frontend / __init__.py**](https://github.com/danielhomola/science_flask/blob/master/./frontend/__init__.py) + +```python +# __init__.py +import os +~~from flask import Flask, url_for, redirect, request, abort +from flask_mail import Mail +from flask_sqlalchemy import SQLAlchemy +from flask_login import LoginManager +from flask_security import Security, SQLAlchemyUserDatastore, signals, \ + current_user +import flask_admin +from flask_admin.contrib import sqla +from flask_admin import helpers as admin_helpers +from flask_wtf.csrf import CSRFProtect +from celery import Celery + + +appdir = os.path.abspath(os.path.dirname(__file__)) +ROOTDIR = os.path.abspath(os.path.join(appdir, os.pardir)) +user_data_folder = os.path.join(ROOTDIR, 'userData') + +~~app = Flask(__name__, instance_path=user_data_folder) + +app.config.from_pyfile('config.py') + +db = SQLAlchemy(app) + +mail = Mail(app) + +csrf = CSRFProtect(app) + +def create_celery_app(): + celery = Celery(__name__, broker=app.config['CELERY_BROKER_URL']) + celery.conf.update(app.config) + TaskBase = celery.Task + + class ContextTask(TaskBase): + abstract = True + + def __call__(self, *args, **kwargs): + with app.app_context(): + return TaskBase.__call__(self, *args, **kwargs) + + celery.Task = ContextTask + celery.app = app + return celery + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 21 from ShortMe +[ShortMe](https://github.com/AcrobaticPanicc/ShortMe-URL-Shortener) +is a [Flask](/flask.html) app that creates a shortened URL +that redirects to another, typically much longer, URL. The +project is provided as open source under the +[MIT license](https://github.com/AcrobaticPanicc/ShortMe-URL-Shortener/blob/main/LICENSE). + +[**ShortMe / app / setup / setup.py**](https://github.com/AcrobaticPanicc/ShortMe-URL-Shortener/blob/main/app/setup/setup.py) + +```python +# setup.py +import os + +~~from flask import Flask +from flask_restful import Api +from dotenv import load_dotenv + +from app.server.db.extensions import db +from app.server.db.models import AuthToken +from app.server.routes.index import index_blueprint +from app.server.routes.internal.redirect_to_url import redirect_to_url_blueprint +from app.server.routes.internal.favicon import app_blueprint +from app.server.routes.internal.send_verification_code import send_otp_blueprint +from app.server.routes.internal.shorten_url import shorten_url_blueprint +from app.server.routes.your_short_url import your_short_url_blueprint +from app.server.routes.total_clicks import total_clicks_blueprint +from app.server.routes.error import error_blueprint +from app.server.routes.page_not_found import page_not_found_blueprint +from app.server.routes.api_doc import api_doc_blueprint +from app.server.routes.get_token import get_token_blueprint +from app.server.routes.your_api_token import your_api_token_blueprint +from app.server.routes.verify_code import verify_code_blueprint + +from app.server.api.api import Shorten, TotalClicks, GetToken + + +def create_app(config_file): + app_path = os.path.dirname(os.path.abspath(__file__)) + project_folder = os.path.expanduser(app_path) + load_dotenv(os.path.join(project_folder, '.env')) + +~~ app = Flask(__name__, template_folder='../client/templates', static_folder='../client/static') + api = Api(app) + app.config.from_pyfile(config_file) + + db.init_app(app) + + with app.app_context(): + db.drop_all() + db.create_all() + + app_auth_token = app.secret_key + auth_token = AuthToken(auth_token=app_auth_token) + db.session.add(auth_token) + db.session.commit() + + api.add_resource(Shorten, '/api/shorten') + api.add_resource(GetToken, '/api/get_token') + api.add_resource(TotalClicks, '/api/total_clicks') + + app.register_blueprint(index_blueprint) + app.register_blueprint(page_not_found_blueprint) + app.register_blueprint(redirect_to_url_blueprint) + app.register_blueprint(your_short_url_blueprint) + app.register_blueprint(total_clicks_blueprint) + app.register_blueprint(error_blueprint) + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 22 from tedivms-flask +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + +[**tedivms-flask / app / __init__.py**](https://github.com/tedivm/tedivms-flask/blob/master/app/./__init__.py) + +```python +# __init__.py +import boto3 +from celery import Celery +from datetime import datetime +import os +import requests +import yaml + +~~from flask import Flask, render_template +from flask import session as current_session +from flask_mail import Mail +from flask_migrate import Migrate, MigrateCommand +from flask.sessions import SessionInterface +from flask_sqlalchemy import SQLAlchemy +from flask_user import user_logged_out +from flask_wtf.csrf import CSRFProtect + +from beaker.cache import CacheManager +from beaker.util import parse_cache_config_options +from beaker.middleware import SessionMiddleware + +db = SQLAlchemy() +csrf_protect = CSRFProtect() +mail = Mail() +migrate = Migrate() + + +def get_config(): +~~ app = Flask(__name__) + + app.config.from_object('app.settings') + if 'APPLICATION_SETTINGS' in os.environ: + app.config.from_envvar(os.environ['APPLICATION_SETTINGS']) + if 'AWS_SECRETS_MANAGER_CONFIG' in os.environ: + secret_config = get_secrets(os.environ['AWS_SECRETS_MANAGER_CONFIG']) + app.config.update(secret_config) + elif 'AWS_SECRETS_MANAGER_CONFIG' in app.config: + secret_config = get_secrets(app.config['AWS_SECRETS_MANAGER_CONFIG']) + app.config.update(secret_config) + for setting in app.config: + if setting in os.environ: + if os.environ[setting].lower() == 'true': + app.config[setting] = True + elif os.environ[setting].lower() == 'false': + app.config[setting] = False + else: + app.config[setting] = os.environ[setting] + if app.config.get('USER_LDAP', False): + app.config['USER_ENABLE_USERNAME'] = True + return app.config + + +def get_secrets(secret_name, region=False): + + +## ... source file abbreviated to get to Flask examples ... + + + + return yaml.safe_load(secret) + + +def get_secret_region(): + if 'AWS_SECRETS_REGION' in os.environ: + return os.environ['AWS_SECRETS_REGION'] + + boto3_session = boto3.session.Session() + if boto3_session.region_name: + return boto3_session.region_name + + r = requests.get('http://169.254.169.254/latest/dynamic/instance-identity/document', timeout=0.2) + r.raise_for_status() + data = r.json() + return data['region'] + + +base_config = get_config() + +celery = Celery(__name__, broker=base_config['CELERY_BROKER']) +cache = None # Initiate below, but define here for scope reasons. + + +def create_app(extra_config_settings={}): +~~ app = Flask(__name__) + + base_config = get_config() + app.config.update(base_config) + app.config.update(extra_config_settings) + + + db.init_app(app) + + migrate.init_app(app, db) + + mail.init_app(app) + + csrf_protect.init_app(app) + + cache = init_cache_manager(app) + + init_session_manager(app) + + init_celery_service(app) + + init_error_handlers(app) + + from app.extensions.jinja import jinja_extensions_blueprint + app.register_blueprint(jinja_extensions_blueprint) + + +## ... source file continues with no further Flask examples... + +``` + + +## Example 23 from trape +[trape](https://github.com/jofpin/trape) is a research tool for tracking +people's activities that are logged digitally. The tool uses +[Flask](/flask.html) to create a web front end to view aggregated data +on an individual the application is set to track. The source code is +provided as open source under the MIT license, according to the +[README](https://github.com/jofpin/trape/blob/master/README.md). + +[**trape / core / user.py**](https://github.com/jofpin/trape/blob/master/./core/user.py) + +```python +# user.py +import time +from core.dependence import urllib2 +~~from flask import Flask, render_template, session, request, json, Response +from core.user_objects import * +import core.stats +from core.utils import utils +from core.db import Database +import os +import sys +import platform +import urllib +import requests +from multiprocessing import Process + +trape = core.stats.trape +app = core.stats.app + +db = Database() + +class victim_server(object): + @app.route("/" + trape.victim_path) + def homeVictim(): + r = requests.get(trape.url_to_clone, headers=victim_headers2(request.user_agent)) + if (trape.type_lure == 'local'): + html = assignScripts(victim_inject_code(render_template("/" + trape.url_to_clone), 'payload', '/', trape.gmaps, trape.ipinfo)) + else: + html = assignScripts(victim_inject_code(r.content, 'payload', trape.url_to_clone, trape.gmaps, trape.ipinfo)) + + +## ... source file continues with no further Flask examples... + +``` + diff --git a/content/pages/examples/flask/flask-app-headers.markdown b/content/pages/examples/flask/flask-app-headers.markdown new file mode 100644 index 000000000..e279fec3c --- /dev/null +++ b/content/pages/examples/flask/flask-app-headers.markdown @@ -0,0 +1,264 @@ +title: flask.app Headers Example Code +category: page +slug: flask-app-headers-examples +sortorder: 500021002 +toc: False +sidebartitle: flask.app Headers +meta: Example code for understanding how to use the Headers class from the flask.app module of the Flask project. + + +[Headers](https://github.com/pallets/flask/blob/master/src/flask/app.py) +is class within the `flask.app` module of the [Flask](/flask.html) +[web framework](/web-frameworks.html) that is imported from the +[datastructures](https://github.com/pallets/werkzeug/blob/master/src/werkzeug/datastructures.py) +module of the [Werkzeug](https://palletsprojects.com/p/werkzeug/) project. +Headers handles the +[HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) +from [requests](/flask-globals-request-examples.html) and responses for +Flask web applications. + +BadRequest, +Flask, +and ImmutableDict +are several other callables with code examples from the same `flask.app` package. + +These topics are also useful while reading the `Headers` examples: + +* [web development](/web-development.html) and [web design](/web-design.html) +* [Flask](/flask.html) and [web framework](/web-frameworks.html) concepts + + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / tests / helpers.py**](https://github.com/CTFd/CTFd/blob/master/./tests/helpers.py) + +```python +# helpers.py +import datetime +import gc +import random +import string +import uuid +from collections import namedtuple +from contextlib import contextmanager +from unittest.mock import Mock, patch + +import requests +from flask.testing import FlaskClient +from freezegun import freeze_time +from sqlalchemy.engine.url import make_url +from sqlalchemy_utils import drop_database +~~from werkzeug.datastructures import Headers + +from CTFd import create_app +from CTFd.cache import cache, clear_standings +from CTFd.config import TestingConfig +from CTFd.models import ( + Awards, + ChallengeComments, + ChallengeFiles, + Challenges, + ChallengeTopics, + Comments, + Fails, + Fields, + Files, + Flags, + Hints, + Notifications, + PageComments, + PageFiles, + Pages, + Solves, + Tags, + TeamComments, + Teams, + Tokens, + Topics, + Tracking, + Unlocks, + UserComments, + Users, +) +from CTFd.utils import set_config +from tests.constants.time import FreezeTimes + +text_type = str +binary_type = bytes + + +FakeRequest = namedtuple("FakeRequest", ["form"]) + + +class CTFdTestClient(FlaskClient): + def open(self, *args, **kwargs): + if kwargs.get("json") is not None: + with self.session_transaction() as sess: +~~ api_key_headers = Headers({"CSRF-Token": sess.get("nonce")}) +~~ headers = kwargs.pop("headers", Headers()) + if isinstance(headers, dict): +~~ headers = Headers(headers) + headers.extend(api_key_headers) + kwargs["headers"] = headers + return super(CTFdTestClient, self).open(*args, **kwargs) + + +class ctftime: + @contextmanager + def init(): + try: + set_config("start", FreezeTimes.START) + set_config("end", FreezeTimes.END) + yield + finally: + set_config("start", None) + set_config("end", None) + + @contextmanager + def not_started(): + try: + freezer = freeze_time(FreezeTimes.NOT_STARTED) + frozen_time = freezer.start() + yield frozen_time + finally: + freezer.stop() + + +## ... source file continues with no further Headers examples... + +``` + + +## Example 2 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / api.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./api.py) + +```python +# api.py +import difflib +import inspect +from itertools import chain +import logging +import operator +import re +import six +import sys +import warnings + +from collections import OrderedDict +from functools import wraps, partial +from types import MethodType + +from flask import url_for, request, current_app +from flask import make_response as original_flask_make_response +try: + from flask.helpers import _endpoint_from_view_func +except ImportError: + from flask.scaffold import _endpoint_from_view_func +from flask.signals import got_request_exception + +from jsonschema import RefResolver + +from werkzeug.utils import cached_property +~~from werkzeug.datastructures import Headers +from werkzeug.exceptions import ( + HTTPException, + MethodNotAllowed, + NotFound, + NotAcceptable, + InternalServerError, +) + +from werkzeug import __version__ as werkzeug_version + +if werkzeug_version.split('.')[0] >= '2': + from werkzeug.wrappers import Response as BaseResponse +else: + from werkzeug.wrappers import BaseResponse + +from . import apidoc +from .mask import ParseError, MaskError +from .namespace import Namespace +from .postman import PostmanCollectionV1 +from .resource import Resource +from .swagger import Swagger +from .utils import default_id, camel_to_dash, unpack +from .representations import output_json +from ._http import HTTPStatus + + +## ... source file abbreviated to get to Headers examples ... + + + if self._has_fr_route(): + try: + return self.handle_error(e) + except Exception as f: + return original_handler(f) + return original_handler(e) + + def handle_error(self, e): + if ( + not isinstance(e, HTTPException) + and current_app.propagate_exceptions + and not isinstance(e, tuple(self._own_and_child_error_handlers.keys())) + ): + + exc_type, exc_value, tb = sys.exc_info() + if exc_value is e: + raise + else: + raise e + + include_message_in_response = current_app.config.get( + "ERROR_INCLUDE_MESSAGE", True + ) + default_data = {} + +~~ headers = Headers() + + for typecheck, handler in six.iteritems(self._own_and_child_error_handlers): + if isinstance(e, typecheck): + result = handler(e) + default_data, code, headers = unpack( + result, HTTPStatus.INTERNAL_SERVER_ERROR + ) + break + else: + got_request_exception.send(current_app._get_current_object(), exception=e) + + if isinstance(e, HTTPException): + code = HTTPStatus(e.code) + if include_message_in_response: + default_data = {"message": getattr(e, "description", code.phrase)} + headers = e.get_response().headers + elif self._default_error_handler: + result = self._default_error_handler(e) + default_data, code, headers = unpack( + result, HTTPStatus.INTERNAL_SERVER_ERROR + ) + else: + code = HTTPStatus.INTERNAL_SERVER_ERROR + if include_message_in_response: + + +## ... source file continues with no further Headers examples... + +``` + diff --git a/content/pages/examples/flask/flask-app-immutabledict.markdown b/content/pages/examples/flask/flask-app-immutabledict.markdown new file mode 100644 index 000000000..d2a334fa8 --- /dev/null +++ b/content/pages/examples/flask/flask-app-immutabledict.markdown @@ -0,0 +1,140 @@ +title: flask.app ImmutableDict Example Code +category: page +slug: flask-app-immutabledict-examples +sortorder: 500021003 +toc: False +sidebartitle: flask.app ImmutableDict +meta: Example code for understanding how to use the ImmutableDict class from the flask.app module of the Flask project. + + +[ImmutableDict](https://github.com/pallets/flask/blob/master/src/flask/app.py) +is a class within the flask.app module of the [Flask](/flask.html) +framework that is actually imported from the Werkzeug +[datastructures module](https://github.com/pallets/werkzeug/blob/master/src/werkzeug/datastructures.py). +The `ImmutableDict` class wraps a +[standard Python dictionary](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) +so that values cannot be modified after initially being set. + +BadRequest, +Flask, +and Headers +are several other callables with code examples from the same `flask.app` package. + +These topics are also useful while reading the `ImmutableDict` examples: + +* [web development](/web-development.html) and [web design](/web-design.html) +* [Flask](/flask.html) and [web framework](/web-frameworks.html) concepts + + +## Example 1 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / core / config.py**](https://github.com/indico/indico/blob/master/indico/core/config.py) + +```python +# config.py + +import ast +import codecs +import os +import re +import socket +import warnings +from datetime import timedelta + +import pytz +from celery.schedules import crontab +from flask import current_app, g +from flask.helpers import get_root_path +~~from werkzeug.datastructures import ImmutableDict +from werkzeug.urls import url_parse + +from indico.util.caching import make_hashable +from indico.util.fs import resolve_link +from indico.util.packaging import package_is_editable +from indico.util.string import crc32, snakify + + +DEFAULTS = { + 'ATTACHMENT_STORAGE': 'default', + 'AUTH_PROVIDERS': {}, + 'BASE_URL': None, + 'CACHE_DIR': '/opt/indico/cache', + 'CATEGORY_CLEANUP': {}, + 'CELERY_BROKER': None, + 'CELERY_CONFIG': {}, + 'CELERY_RESULT_BACKEND': None, + 'COMMUNITY_HUB_URL': 'https://hub.getindico.io', + 'CUSTOMIZATION_DEBUG': False, + 'CUSTOMIZATION_DIR': None, + 'CUSTOM_COUNTRIES': {}, + 'CUSTOM_LANGUAGES': {}, + 'DB_LOG': False, + 'DEBUG': False, + + +## ... source file abbreviated to get to ImmutableDict examples ... + + + allowed |= set(INTERNAL_DEFAULTS) + for key in set(data) - allowed: + warnings.warn(f'Ignoring unknown config key {key}') + return {k: v for k, v in data.items() if k in allowed} + + +def load_config(only_defaults=False, override=None): + data = DEFAULTS | INTERNAL_DEFAULTS + if not only_defaults: + path = get_config_path() + config = _sanitize_data(_parse_config(path)) + data.update(config) + env_override = os.environ.get('INDICO_CONF_OVERRIDE') + if env_override: + data.update(_sanitize_data(ast.literal_eval(env_override))) + resolved_path = resolve_link(path) if os.path.islink(path) else path + resolved_path = None if resolved_path == os.devnull else resolved_path + data['CONFIG_PATH'] = path + data['CONFIG_PATH_RESOLVED'] = resolved_path + if resolved_path is not None: + data['LOGGING_CONFIG_PATH'] = os.path.join(os.path.dirname(resolved_path), data['LOGGING_CONFIG_FILE']) + + if override: + data.update(_sanitize_data(override, allow_internal=True)) + _postprocess_config(data) +~~ return ImmutableDict(data) + + +class IndicoConfig: + + __slots__ = ('_config', '_exc') + + def __init__(self, config=None, exc=AttributeError): + object.__setattr__(self, '_config', config) + object.__setattr__(self, '_exc', exc) + + @property + def data(self): + try: + return self._config or current_app.config['INDICO'] + except KeyError: + raise RuntimeError('config not loaded') + + @property + def hash(self): + return crc32(repr(make_hashable(sorted(self.data.items())))) + + @property + def CONFERENCE_CSS_TEMPLATES_BASE_URL(self): + return self.BASE_URL + '/css/confTemplates' + + +## ... source file continues with no further ImmutableDict examples... + +``` + diff --git a/content/pages/examples/flask/flask-blueprints-blueprint.markdown b/content/pages/examples/flask/flask-blueprints-blueprint.markdown new file mode 100644 index 000000000..16a0bb9c3 --- /dev/null +++ b/content/pages/examples/flask/flask-blueprints-blueprint.markdown @@ -0,0 +1,996 @@ +title: flask.blueprints Blueprint Example Code +category: page +slug: flask-blueprints-blueprint-examples +sortorder: 500021004 +toc: False +sidebartitle: flask.blueprints Blueprint +meta: Example code for understanding how to use the Blueprint class from the flask.blueprints module of the Flask project. + + +A Blueprint in [Flask](/flask.html) is +[a "mold" or template for creating parts of web applications](https://stackoverflow.com/questions/24420857/what-are-flask-blueprints-exactly). +This +[Blueprint](https://github.com/pallets/flask/blob/master/src/flask/blueprints.py) +class within the `flask.blueprints` module implements that functionality +for Flask [web apps](/web-development.html). + + + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / CTFd / auth.py**](https://github.com/CTFd/CTFd/blob/master/./CTFd/auth.py) + +```python +# auth.py +import base64 + +import requests +~~from flask import Blueprint, abort +from flask import current_app as app +from flask import redirect, render_template, request, session, url_for +from itsdangerous.exc import BadSignature, BadTimeSignature, SignatureExpired + +from CTFd.cache import clear_team_session, clear_user_session +from CTFd.models import Teams, UserFieldEntries, UserFields, Users, db +from CTFd.utils import config, email, get_app_config, get_config +from CTFd.utils import user as current_user +from CTFd.utils import validators +from CTFd.utils.config import is_teams_mode +from CTFd.utils.config.integrations import mlc_registration +from CTFd.utils.config.visibility import registration_visible +from CTFd.utils.crypto import verify_password +from CTFd.utils.decorators import ratelimit +from CTFd.utils.decorators.visibility import check_registration_visibility +from CTFd.utils.helpers import error_for, get_errors, markup +from CTFd.utils.logging import log +from CTFd.utils.modes import TEAMS_MODE +from CTFd.utils.security.auth import login_user, logout_user +from CTFd.utils.security.signing import unserialize +from CTFd.utils.validators import ValidationError + +~~auth = Blueprint("auth", __name__) + + +@auth.route("/confirm", methods=["POST", "GET"]) +@auth.route("/confirm/", methods=["POST", "GET"]) +@ratelimit(method="POST", limit=10, interval=60) +def confirm(data=None): + if not get_config("verify_emails"): + return redirect(url_for("challenges.listing")) + + if data and request.method == "GET": + try: + user_email = unserialize(data, max_age=1800) + except (BadTimeSignature, SignatureExpired): + return render_template( + "confirm.html", errors=["Your confirmation link has expired"] + ) + except (BadSignature, TypeError, base64.binascii.Error): + return render_template( + "confirm.html", errors=["Your confirmation token is invalid"] + ) + + user = Users.query.filter_by(email=user_email).first_or_404() + if user.verified: + return redirect(url_for("views.settings")) + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 2 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / base.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/./base.py) + +```python +# base.py +from functools import reduce +import logging +from typing import Dict + +~~from flask import Blueprint, current_app, url_for + +from . import __version__ +from .api.manager import OpenApiManager +from .babel.manager import BabelManager +from .const import ( + LOGMSG_ERR_FAB_ADD_PERMISSION_MENU, + LOGMSG_ERR_FAB_ADD_PERMISSION_VIEW, + LOGMSG_ERR_FAB_ADDON_IMPORT, + LOGMSG_ERR_FAB_ADDON_PROCESS, + LOGMSG_INF_FAB_ADD_VIEW, + LOGMSG_INF_FAB_ADDON_ADDED, + LOGMSG_WAR_FAB_VIEW_EXISTS, +) +from .filters import TemplateFilters +from .menu import Menu, MenuApiManager +from .views import IndexView, UtilView + +log = logging.getLogger(__name__) + + +def dynamic_class_import(class_path): + try: + tmp = class_path.split(".") + module_path = ".".join(tmp[0:-1]) + + +## ... source file abbreviated to get to Blueprint examples ... + + + + @property + def app_name(self): + return self.get_app.config["APP_NAME"] + + @property + def app_theme(self): + return self.get_app.config["APP_THEME"] + + @property + def app_icon(self): + return self.get_app.config["APP_ICON"] + + @property + def languages(self): + return self.get_app.config["LANGUAGES"] + + @property + def version(self): + return __version__ + + def _add_global_filters(self): + self.template_filters = TemplateFilters(self.get_app, self.sm) + + def _add_global_static(self): +~~ bp = Blueprint( + "appbuilder", + __name__, + url_prefix="/static", + template_folder="templates", + static_folder=self.static_folder, + static_url_path=self.static_url_path, + ) + self.get_app.register_blueprint(bp) + + def _add_admin_views(self): + self.indexview = self._check_and_init(self.indexview) + self.add_view_no_menu(self.indexview) + self.add_view_no_menu(UtilView()) + self.bm.register_views() + self.sm.register_views() + self.openapi_manager.register_views() + self.menuapi_manager.register_views() + + def _add_addon_views(self): + for addon in self._addon_managers: + addon_class = dynamic_class_import(addon) + if addon_class: + addon_class = addon_class(self) + try: + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 3 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / auth / views.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/auth/views.py) + +```python +# views.py +import logging +from datetime import datetime + +~~from flask import Blueprint, current_app, flash, g, redirect, request, url_for +from flask.views import MethodView +from flask_babelplus import gettext as _ +from flask_login import ( + confirm_login, + current_user, + login_fresh, + login_required, + login_user, + logout_user, +) + +from flaskbb.auth.forms import ( + AccountActivationForm, + ForgotPasswordForm, + LoginForm, + LoginRecaptchaForm, + ReauthForm, + RegisterForm, + RequestActivationForm, + ResetPasswordForm, +) +from flaskbb.extensions import db, limiter +from flaskbb.utils.helpers import ( + anonymous_required, + + +## ... source file abbreviated to get to Blueprint examples ... + + + else: + try: + db.session.commit() + except Exception: # noqa + logger.exception("Database error while activating account") + db.session.rollback() + flash( + _( + "Could not activate account due to an unrecoverable error" # noqa + ), "danger" + ) + + return redirect(url_for('auth.request_activation_token')) + + flash( + _("Your account has been activated and you can now login."), + "success" + ) + return redirect(url_for("forum.index")) + + return render_template("auth/account_activation.html", form=form) + + +@impl(tryfirst=True) +def flaskbb_load_blueprints(app): +~~ auth = Blueprint("auth", __name__) + + def login_rate_limit(): + return "{count}/{timeout}minutes".format( + count=flaskbb_config["AUTH_REQUESTS"], + timeout=flaskbb_config["AUTH_TIMEOUT"] + ) + + def login_rate_limit_message(): + current_limit = getattr(g, 'view_rate_limit', None) + if current_limit is not None: + window_stats = limiter.limiter.get_window_stats(*current_limit) + reset_time = datetime.utcfromtimestamp(window_stats[0]) + timeout = reset_time - datetime.utcnow() + return "{timeout}".format(timeout=format_timedelta(timeout)) + + @auth.before_request + def check_rate_limiting(): + if not flaskbb_config["AUTH_RATELIMIT_ENABLED"]: + return None + return limiter.check() + + @auth.errorhandler(429) + def login_rate_limit_error(error): + return render_template( + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 4 from flask-base +[flask-base](https://github.com/hack4impact/flask-base) +([project documentation](http://hack4impact.github.io/flask-base/)) +provides boilerplate code for new [Flask](/flask.html) web apps. +The purpose of the boilerplate is to stitch together disparate +libraries that are commonly used in Flask projects, such as +[Redis](/redis.html) for fast caching and transient data storage, +[SendGrid](https://www.twilio.com/sendgrid) for transactional email, +[SQLAlchemy](/sqlalchemy.html) for persistent data storage through a +[relational database](/databases.html) backend, +[Flask-WTF](https://flask-wtf.readthedocs.io/) for form +handling and many others. + +flask-base is provided as open source under the +[MIT license](https://github.com/hack4impact/flask-base/blob/master/LICENSE.md). + +[**flask-base / app / main / views.py**](https://github.com/hack4impact/flask-base/blob/master/app/main/views.py) + +```python +# views.py +~~from flask import Blueprint, render_template + +from app.models import EditableHTML + +~~main = Blueprint('main', __name__) + + +@main.route('/') +def index(): + return render_template('main/index.html') + + +@main.route('/about') +def about(): + editable_html_obj = EditableHTML.get_editable_html('about') + return render_template( + 'main/about.html', editable_html_obj=editable_html_obj) + + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 5 from flask-bones +[flask-bones](https://github.com/cburmeister/flask-bones) +([demo](http://flask-bones.herokuapp.com/)) +is large scale [Flask](/flask.html) example application built +with [Blueprints](https://flask.palletsprojects.com/en/1.1.x/blueprints/) +([example Blueprint code](/flask-blueprints-blueprint-examples.html)). +This project is provided as open source under the +[MIT license](https://github.com/cburmeister/flask-bones/blob/master/LICENSE). + +[**flask-bones / app / auth / __init__.py**](https://github.com/cburmeister/flask-bones/blob/master/app/auth/__init__.py) + +```python +# __init__.py +~~from flask import Blueprint + +~~auth = Blueprint('auth', __name__, template_folder='templates') + +from . import views + + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 6 from flask-bookshelf +[flask-bookshelf](https://github.com/damyanbogoev/flask-bookshelf) is the +example [Flask](/flask.html) application that developers create when +going through +[this Flask series of blog posts](https://damyanon.net/tags/flask-series/). + +[**flask-bookshelf / bookshelf / admin / controllers.py**](https://github.com/damyanbogoev/flask-bookshelf/blob/master/bookshelf/admin/controllers.py) + +```python +# controllers.py +from sqlalchemy import exc +~~from flask import Blueprint, render_template, flash +from flask import current_app, redirect, request, url_for +from flask_security.decorators import roles_required +from bookshelf.admin.forms.author_forms import CreateAuthorForm +from bookshelf.cache import cache +from bookshelf.data.models import Author, db + + +~~admin = Blueprint("admin", __name__, template_folder="templates") + + +@admin.route("/") +@roles_required("admin") +def index(): + return render_template("admin_index.htm") + + +@admin.route("/author/create", methods=["GET", "POST"]) +@roles_required("admin") +def create_author(): + form = CreateAuthorForm(request.form) + if request.method == "POST" and form.validate(): + names = form.names.data + current_app.logger.info("Adding a new author %s.", (names)) + author = Author(names) + + try: + db.session.add(author) + db.session.commit() + cache.clear() + flash("Author successfully created.") + except exc.SQLAlchemyError as e: + flash("Author was not created.") + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 7 from Flask-Bootstrap +[flask-bootstrap](https://github.com/mbr/flask-bootstrap) +([PyPI package information](https://pypi.org/project/Flask-Bootstrap/)) +makes it easier to use the [Bootstrap CSS framework](/bootstrap-css.html) +in your [Flask](/flask.html) applications with less boilerplate +code. The project was primarily created by +[Marc Brinkmann @mbr](https://github.com/mbr) and the source code is +open sourced under the +[Apache 2.0 license](https://github.com/mbr/flask-bootstrap/blob/master/LICENSE). + +[**Flask-Bootstrap / flask_bootstrap / __init__.py**](https://github.com/mbr/flask-bootstrap/blob/master/flask_bootstrap/./__init__.py) + +```python +# __init__.py + +import re + +~~from flask import Blueprint, current_app, url_for + +try: + from wtforms.fields import HiddenField +except ImportError: + + def is_hidden_field_filter(field): + raise RuntimeError('WTForms is not installed.') +else: + + def is_hidden_field_filter(field): + return isinstance(field, HiddenField) + + +from .forms import render_form + +__version__ = '3.3.7.1.dev1' +BOOTSTRAP_VERSION = re.sub(r'^(\d+\.\d+\.\d+).*', r'\1', __version__) +JQUERY_VERSION = '1.12.4' +HTML5SHIV_VERSION = '3.7.3' +RESPONDJS_VERSION = '1.4.2' + + +class CDN(object): + + + +## ... source file abbreviated to get to Blueprint examples ... + + + filename = '%s.min.%s' % tuple(filename.rsplit('.', 1)) + + cdns = current_app.extensions['bootstrap']['cdns'] + resource_url = cdns[cdn].get_resource_url(filename) + + if resource_url.startswith('//') and config['BOOTSTRAP_CDN_FORCE_SSL']: + resource_url = 'https:%s' % resource_url + + return resource_url + + +class Bootstrap(object): + def __init__(self, app=None): + if app is not None: + self.init_app(app) + + def init_app(self, app): + app.config.setdefault('BOOTSTRAP_USE_MINIFIED', True) + app.config.setdefault('BOOTSTRAP_CDN_FORCE_SSL', False) + + app.config.setdefault('BOOTSTRAP_QUERYSTRING_REVVING', True) + app.config.setdefault('BOOTSTRAP_SERVE_LOCAL', False) + + app.config.setdefault('BOOTSTRAP_LOCAL_SUBDOMAIN', None) + +~~ blueprint = Blueprint( + 'bootstrap', + __name__, + template_folder='templates', + static_folder='static', + static_url_path=app.static_url_path + '/bootstrap', + subdomain=app.config['BOOTSTRAP_LOCAL_SUBDOMAIN']) + + blueprint.add_app_template_filter(render_form) + + app.register_blueprint(blueprint) + + app.jinja_env.globals['bootstrap_is_hidden_field'] =\ + is_hidden_field_filter + app.jinja_env.globals['bootstrap_find_resource'] =\ + bootstrap_find_resource + app.jinja_env.add_extension('jinja2.ext.do') + + if not hasattr(app, 'extensions'): + app.extensions = {} + + local = StaticCDN('bootstrap.static', rev=True) + static = StaticCDN() + + def lwrap(cdn, primary=static): + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 8 from flask-debugtoolbar +[Flask Debug-toolbar](https://github.com/flask-debugtoolbar/flask-debugtoolbar) +([documentation](https://flask-debugtoolbar.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/Flask-DebugToolbar/)) +is a [Flask](/flask.html) conversion of the popular +[Django Debug Toolbar](https://github.com/jazzband/django-debug-toolbar) +project. This extension creates a sidebar with useful debugging +information when you are running a Flask application in development +mode. The project is provided as open source under +[this license](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/LICENSE). + +[**flask-debugtoolbar / flask_debugtoolbar / __init__.py**](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/flask_debugtoolbar/./__init__.py) + +```python +# __init__.py +import os +import warnings + +~~from flask import Blueprint, current_app, request, g, send_from_directory, url_for +from flask.globals import _request_ctx_stack +from jinja2 import Environment, PackageLoader +from werkzeug.urls import url_quote_plus + +from flask_debugtoolbar.compat import iteritems +from flask_debugtoolbar.toolbar import DebugToolbar +from flask_debugtoolbar.utils import decode_text, gzip_compress, gzip_decompress + +try: + from importlib.metadata import version + + __version__ = version("Flask-DebugToolbar") +except ImportError: + import pkg_resources + + __version__ = pkg_resources.get_distribution("Flask-DebugToolbar").version + + +~~module = Blueprint('debugtoolbar', __name__) + + +def replace_insensitive(string, target, replacement): + no_case = string.lower() + index = no_case.rfind(target.lower()) + if index >= 0: + return string[:index] + replacement + string[index + len(target):] + else: # no results so return the original string + return string + + +def _printable(value): + try: + return decode_text(repr(value)) + except Exception as e: + return '' % ( + object.__repr__(value), type(e).__name__, e) + + +class DebugToolbarExtension(object): + _static_dir = os.path.realpath( + os.path.join(os.path.dirname(__file__), 'static')) + + _redirect_codes = [301, 302, 303, 304] + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 9 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / apidoc.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./apidoc.py) + +```python +# apidoc.py +from __future__ import unicode_literals + +~~from flask import url_for, Blueprint, render_template + + +~~class Apidoc(Blueprint): + + def __init__(self, *args, **kwargs): + self.registered = False + super(Apidoc, self).__init__(*args, **kwargs) + + def register(self, *args, **kwargs): + super(Apidoc, self).register(*args, **kwargs) + self.registered = True + + +apidoc = Apidoc( + "restx_doc", + __name__, + template_folder="templates", + static_folder="static", + static_url_path="/swaggerui", +) + + +@apidoc.add_app_template_global +def swagger_static(filename): + return url_for("restx_doc.static", filename=filename) + + + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 10 from Flask-WTF +[Flask-WTF](https://github.com/lepture/flask-wtf) +([project documentation](https://flask-wtf.readthedocs.io/) +and +[PyPI page](https://pypi.org/project/Flask-WTF/)) +provides a bridge between [Flask](/flask.html) and the the +[WTForms](https://wtforms.readthedocs.io/en/2.3.x/) form-handling library. +It makes it easier to use WTForms by reducing boilerplate code and +shorter examples for common form operations as well as common security +practices such as [CSRF](/cross-site-request-forgery-csrf.html). + +[**Flask-WTF / flask_wtf / csrf.py**](https://github.com/lepture/flask-wtf/blob/master/flask_wtf/./csrf.py) + +```python +# csrf.py +import hashlib +import logging +import os +import warnings +from urllib.parse import urlparse +from functools import wraps + +~~from flask import Blueprint, current_app, g, request, session +from itsdangerous import BadData, SignatureExpired, URLSafeTimedSerializer +from werkzeug.exceptions import BadRequest +from werkzeug.security import safe_str_cmp +from wtforms import ValidationError +from wtforms.csrf.core import CSRF + +from ._compat import FlaskWTFDeprecationWarning + +__all__ = ('generate_csrf', 'validate_csrf', 'CSRFProtect') +logger = logging.getLogger(__name__) + + +def generate_csrf(secret_key=None, token_key=None): + + secret_key = _get_config( + secret_key, 'WTF_CSRF_SECRET_KEY', current_app.secret_key, + message='A secret key is required to use CSRF.' + ) + field_name = _get_config( + token_key, 'WTF_CSRF_FIELD_NAME', 'csrf_token', + message='A field name is required to use CSRF.' + ) + + if field_name not in g: + + +## ... source file abbreviated to get to Blueprint examples ... + + + return None + + def protect(self): + if request.method not in current_app.config['WTF_CSRF_METHODS']: + return + + try: + validate_csrf(self._get_csrf_token()) + except ValidationError as e: + logger.info(e.args[0]) + self._error_response(e.args[0]) + + if request.is_secure and current_app.config['WTF_CSRF_SSL_STRICT']: + if not request.referrer: + self._error_response('The referrer header is missing.') + + good_referrer = f'https://{request.host}/' + + if not same_origin(request.referrer, good_referrer): + self._error_response('The referrer does not match the host.') + + g.csrf_valid = True # mark this request as CSRF valid + + def exempt(self, view): + +~~ if isinstance(view, Blueprint): + self._exempt_blueprints.add(view.name) + return view + + if isinstance(view, str): + view_location = view + else: + view_location = '.'.join((view.__module__, view.__name__)) + + self._exempt_views.add(view_location) + return view + + def _error_response(self, reason): + raise CSRFError(reason) + + def error_handler(self, view): + + warnings.warn(FlaskWTFDeprecationWarning( + '"@csrf.error_handler" is deprecated. Use the standard Flask ' + 'error system with "@app.errorhandler(CSRFError)" instead. This ' + 'will be removed in 1.0.' + ), stacklevel=2) + + @wraps(view) + def handler(reason): + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 11 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / user_manager.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/./user_manager.py) + +```python +# user_manager.py + + +import datetime + +~~from flask import abort, Blueprint, current_app, Flask, session +from flask_login import LoginManager +from wtforms import ValidationError + +from . import ConfigError +from . import forms +from .db_manager import DBManager +from .email_manager import EmailManager +from .password_manager import PasswordManager +from .token_manager import TokenManager +from .translation_utils import lazy_gettext as _ # map _() to lazy_gettext() +from .user_manager__settings import UserManager__Settings +from .user_manager__utils import UserManager__Utils +from .user_manager__views import UserManager__Views + + +class UserManager(UserManager__Settings, UserManager__Utils, UserManager__Views): + + def __init__(self, app, db, UserClass, **kwargs): + + self.app = app + if app: + self.init_app(app, db, UserClass, **kwargs) + + def init_app( + + +## ... source file abbreviated to get to Blueprint examples ... + + + + @self.login_manager.user_loader + def load_user_by_user_token(user_token): + user = self.db_manager.UserClass.get_user_by_token(user_token) + return user + + self.babel = app.extensions.get('babel', None) + from .translation_utils import init_translations + init_translations(self.babel) + + if not hasattr(app.jinja_env, 'install_gettext_callables'): + app.jinja_env.add_extension('jinja2.ext.i18n') + app.jinja_env.install_null_translations() + + def flask_user_context_processor(): + def call_or_get(function_or_property): + return function_or_property() if callable(function_or_property) else function_or_property + + return dict( + user_manager=current_app.user_manager, + call_or_get=call_or_get, + ) + + app.context_processor(flask_user_context_processor) + +~~ blueprint = Blueprint('flask_user', __name__, template_folder='templates') + app.register_blueprint(blueprint) + + self.AddEmailFormClass = forms.AddEmailForm + self.ChangePasswordFormClass = forms.ChangePasswordForm + self.ChangeUsernameFormClass = forms.ChangeUsernameForm + self.EditUserProfileFormClass = forms.EditUserProfileForm + self.ForgotPasswordFormClass = forms.ForgotPasswordForm + self.InviteUserFormClass = forms.InviteUserForm + self.LoginFormClass = forms.LoginForm + self.RegisterFormClass = forms.RegisterForm + self.ResendEmailConfirmationFormClass = forms.ResendEmailConfirmationForm + self.ResetPasswordFormClass = forms.ResetPasswordForm + + self.db_manager = DBManager(app, db, UserClass, UserEmailClass, UserInvitationClass, RoleClass) + + self.password_manager = PasswordManager(app) + + if self.USER_ENABLE_EMAIL: + from .email_adapters.smtp_email_adapter import SMTPEmailAdapter + self.email_adapter = SMTPEmailAdapter(app) + + if self.USER_ENABLE_EMAIL: + self.email_manager = EmailManager(app) + + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 12 from Flask-VueJs-Template +[Flask-VueJs-Template](https://github.com/gtalarico/flask-vuejs-template) +([demo site](https://flask-vuejs-template.herokuapp.com/)) +is a minimal [Flask](/flask.html) boilerplate starter project that +combines Flask, [Vue.js](https://www.fullstackpython.com/vuejs.html), +and [Flask-RESTPlus](https://flask-restplus.readthedocs.io/en/stable/). +The project provides some sensible defaults that are easy to continue +building on, and the source code is open source under the +[MIT license](https://github.com/gtalarico/flask-vuejs-template/blob/master/LICENSE.md). + +[**Flask-VueJs-Template / app / client.py**](https://github.com/gtalarico/flask-vuejs-template/blob/master/app/./client.py) + +```python +# client.py + +import os +~~from flask import Blueprint, render_template + +~~client_bp = Blueprint('client_app', __name__, + url_prefix='', + static_url_path='', + static_folder='./dist/static/', + template_folder='./dist/', + ) + + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 13 from Datadog Flask Example App +The [Datadog Flask example app](https://github.com/DataDog/trace-examples/tree/master/python/flask) +contains many examples of the [Flask](/flask.html) core functions +available to a developer using the [web framework](/web-frameworks.html). + +[**Datadog Flask Example App / python/flask/app / blueprint.py**](https://github.com/DataDog/trace-examples/blob/master/python/flask/app/./blueprint.py) + +```python +# blueprint.py +from ddtrace import Pin +~~from flask import abort, Blueprint, render_template_string + +from .limiter import limiter + + +~~bp = Blueprint('bp', __name__, url_prefix='/bp/') + +Pin.override(bp, service='flask-bp', app='flask', app_type='web') + + +@bp.before_request +def bp_before_request(): + print('Hook: bp_before_request') + + +@bp.before_app_request +def bp_before_app_request(): + print('Hook: bp_before_app_request') + + +@bp.before_app_first_request +def bp_before_app_first_request(): + print('Hook: bp_before_app_first_request') + + +@bp.after_request +def bp_after_request(response): + print('Hook: bp_after_request') + return response + + + +## ... source file continues with no further Blueprint examples... + +``` + + +## Example 14 from tedivms-flask +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + +[**tedivms-flask / app / extensions / jinja.py**](https://github.com/tedivm/tedivms-flask/blob/master/app/extensions/jinja.py) + +```python +# jinja.py +~~from flask import Blueprint +from wtforms.fields import HiddenField +from jinja2 import evalcontextfilter, Markup +import re + +~~jinja_extensions_blueprint = Blueprint('jinja_extensions_blueprint', __name__, template_folder='templates') + + +@jinja_extensions_blueprint.app_template_filter() +def filesize_format(num): + magnitude = 0 + while abs(num) >= 1000: + magnitude += 1 + num /= 1000.0 + return '%.0f%s' % (num, ['', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][magnitude]) + + +@jinja_extensions_blueprint.app_template_global +def is_hidden_field_filter(field): + return isinstance(field, HiddenField) + + +@jinja_extensions_blueprint.app_template_filter() +@evalcontextfilter +def nl2br(eval_ctx, value): + normalized_value = re.sub(r'\r\n|\r|\n', '\n', value) # normalize newlines + html_value = normalized_value.replace('\n', '\n
    \n') + if eval_ctx.autoescape: + return Markup(html_value) + return html_value + + +## ... source file continues with no further Blueprint examples... + +``` + diff --git a/content/pages/examples/flask/flask-cli-appgroup.markdown b/content/pages/examples/flask/flask-cli-appgroup.markdown new file mode 100644 index 000000000..0e496e286 --- /dev/null +++ b/content/pages/examples/flask/flask-cli-appgroup.markdown @@ -0,0 +1,121 @@ +title: flask.cli AppGroup Example Code +category: page +slug: flask-cli-appgroup-examples +sortorder: 500021005 +toc: False +sidebartitle: flask.cli AppGroup +meta: Example code for understanding how to use the AppGroup class from the flask.cli module of the Flask project. + + +[AppGroup](https://github.com/pallets/flask/blob/master/src/flask/cli.py) +is a class within the `flask.cli` module of the Flask project. It +works like the +[Click Group](https://click.palletsprojects.com/en/7.x/commands/) +class and automatically wraps the functions using +[with_appcontext](/flask-cli-with-appcontext-examples.html). + +DispatchingApp, +FlaskGroup, +ScriptInfo, +pass_script_info, +and with_appcontext +are several other callables with code examples from the same `flask.cli` package. + +## Example 1 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / cli / util.py**](https://github.com/indico/indico/blob/master/indico/cli/util.py) + +```python +# util.py + +import traceback +from importlib import import_module + +import click +~~from flask.cli import AppGroup, FlaskGroup, ScriptInfo +from flask_pluginengine import wrap_in_plugin_context +from werkzeug.utils import cached_property + + + + +def _create_app(info): + from indico.web.flask.app import make_app + return make_app() + + +class IndicoFlaskGroup(FlaskGroup): + + def __init__(self, **extra): + super().__init__(create_app=_create_app, add_default_commands=False, add_version_option=False, + set_debug_flag=False, **extra) + self._indico_plugin_commands = None + + def _load_plugin_commands(self): + assert False + + def _wrap_in_plugin_context(self, plugin, cmd): + cmd.callback = wrap_in_plugin_context(plugin, cmd.callback) + for subcmd in getattr(cmd, 'commands', {}).values(): + self._wrap_in_plugin_context(plugin, subcmd) + + def _get_indico_plugin_commands(self, ctx): + if self._indico_plugin_commands is not None: + return self._indico_plugin_commands + try: + from indico.core import signals + from indico.util.signals import named_objects_from_signal + ctx.ensure_object(ScriptInfo).load_app() + cmds = named_objects_from_signal(signals.plugin.cli.send(), plugin_attr='_indico_plugin') + rv = {} + for name, cmd in cmds.items(): + if cmd._indico_plugin: + self._wrap_in_plugin_context(cmd._indico_plugin, cmd) + rv[name] = cmd + except Exception as exc: + if 'No indico config found' not in str(exc): + click.echo(click.style('Loading plugin commands failed:', fg='red', bold=True)) + click.echo(click.style(traceback.format_exc(), fg='red')) + rv = {} + self._indico_plugin_commands = rv + return rv + + def get_command(self, ctx, name): +~~ rv = AppGroup.get_command(self, ctx, name) + if rv is not None: + return rv + return self._get_indico_plugin_commands(ctx).get(name) + + def list_commands(self, ctx): + rv = set(click.Group.list_commands(self, ctx)) + rv.update(self._get_indico_plugin_commands(ctx)) + return sorted(rv) + + +class LazyGroup(click.Group): + + def __init__(self, import_name, **kwargs): + self._import_name = import_name + super().__init__(**kwargs) + + @cached_property + def _impl(self): + module, name = self._import_name.split(':', 1) + return getattr(import_module(module), name) + + def get_command(self, ctx, cmd_name): + return self._impl.get_command(ctx, cmd_name) + + + +## ... source file continues with no further AppGroup examples... + +``` + diff --git a/content/pages/examples/flask/flask-cli-dispatchingapp.markdown b/content/pages/examples/flask/flask-cli-dispatchingapp.markdown new file mode 100644 index 000000000..aa8140dd9 --- /dev/null +++ b/content/pages/examples/flask/flask-cli-dispatchingapp.markdown @@ -0,0 +1,123 @@ +title: flask.cli DispatchingApp Example Code +category: page +slug: flask-cli-dispatchingapp-examples +sortorder: 500021006 +toc: False +sidebartitle: flask.cli DispatchingApp +meta: Example code for understanding how to use the DispatchingApp class from the flask.cli module of the Flask project. + + +[DispatchingApp](https://github.com/pallets/flask/blob/master/src/flask/cli.py) +is a class within the `flask.cli` module of the [Flask](/flask.html) project. +DispatchingApp is a special application that dispatches to a Flask app +if it is imported by name in a background thread. + +AppGroup, +FlaskGroup, +ScriptInfo, +pass_script_info, +and with_appcontext +are several other callables with code examples from the same `flask.cli` package. + +## Example 1 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / cli / devserver.py**](https://github.com/indico/indico/blob/master/indico/cli/devserver.py) + +```python +# devserver.py + +import os + +~~from flask.cli import DispatchingApp +from werkzeug.debug import DebuggedApplication +from werkzeug.exceptions import NotFound +from werkzeug.middleware.dispatcher import DispatcherMiddleware +from werkzeug.middleware.proxy_fix import ProxyFix +from werkzeug.serving import WSGIRequestHandler, run_simple +from werkzeug.urls import url_parse + + +try: + import pywatchman +except ImportError: + pywatchman = None + + +def run_cmd(info, **kwargs): + if kwargs['reloader_type'] == 'watchman': + if pywatchman is None: + print('watchman is not available - you need to `pip install pywatchman`') + return + run_watchman() + return + run_server(info, **kwargs) + + + + +## ... source file abbreviated to get to DispatchingApp examples ... + + + + import logging + werkzeug_logger = logging.getLogger('werkzeug') + werkzeug_logger.propagate = False + werkzeug_logger.setLevel(logging.INFO) + werkzeug_logger.addHandler(logging.StreamHandler()) + + app = _make_wsgi_app(info, url, evalex_whitelist, proxy) + run_simple(host, port, app, + reloader_type=reloader_type, use_reloader=(reloader_type != 'none'), + use_debugger=False, use_evalex=False, threaded=True, ssl_context=ssl_ctx, + extra_files=extra_files, request_handler=QuietWSGIRequestHandler if quiet else None) + + +def _reset_state(): + from indico.core.celery import celery + celery.flask_app = None + + +def _make_wsgi_app(info, url, evalex_whitelist, proxy): + def _load_app(): + _reset_state() + return info.load_app() + + url_data = url_parse(url) +~~ app = DispatchingApp(_load_app, use_eager_loading=False) + app = DebuggedIndico(app, evalex_whitelist) + app = _make_indico_dispatcher(app, url_data.path) + if proxy: + app = ProxyFix(app, x_for=1, x_proto=1, x_host=1) + QuietWSGIRequestHandler.INDICO_URL_PREFIX = url_data.path.rstrip('/') + return app + + +def _make_indico_dispatcher(wsgi_app, path): + path = path.rstrip('/') + if not path: + return wsgi_app + else: + return DispatcherMiddleware(NotFound(), { + path: wsgi_app + }) + + +class DebuggedIndico(DebuggedApplication): + def __init__(self, *args, **kwargs): + self._evalex_whitelist = None + self._request_ip = None + super().__init__(*args, **kwargs) + + + +## ... source file continues with no further DispatchingApp examples... + +``` + diff --git a/content/pages/examples/flask/flask-cli-flaskgroup.markdown b/content/pages/examples/flask/flask-cli-flaskgroup.markdown new file mode 100644 index 000000000..1b39ccb93 --- /dev/null +++ b/content/pages/examples/flask/flask-cli-flaskgroup.markdown @@ -0,0 +1,171 @@ +title: flask.cli FlaskGroup Example Code +category: page +slug: flask-cli-flaskgroup-examples +sortorder: 500021007 +toc: False +sidebartitle: flask.cli FlaskGroup +meta: Example code for understanding how to use the FlaskGroup class from the flask.cli module of the Flask project. + + +[FlaskGroup](https://github.com/pallets/flask/blob/master/src/flask/cli.py) +is a class within the `flask.cli` module of the [Flask project](/flask.html). +FlaskGroup is a subclass of [AppGroup](/flask-cli-appgroup-examples.html) +that provides for loading more commands from a configured Flask app. +Generally, only advanced use cases will need to use this class. + +AppGroup, +DispatchingApp, +ScriptInfo, +pass_script_info, +and with_appcontext +are several other callables with code examples from the same `flask.cli` package. + +## Example 1 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / cli / main.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/cli/main.py) + +```python +# main.py +import binascii +import logging +import os +import sys +import time +import traceback +from datetime import datetime + +import click +from flask import current_app +~~from flask.cli import FlaskGroup, ScriptInfo, with_appcontext +from flask_alembic import alembic_click +from jinja2 import Environment, FileSystemLoader +from sqlalchemy_utils.functions import database_exists +from werkzeug.utils import import_string + +from flaskbb import create_app +from flaskbb.cli.utils import ( + EmailType, + FlaskBBCLIError, + get_version, + prompt_config_path, + prompt_save_user, + write_config, +) +from flaskbb.extensions import alembic, celery, db, whooshee +from flaskbb.utils.populate import ( + create_default_groups, + create_default_settings, + create_latest_db, + create_test_data, + create_welcome_forum, + insert_bulk_data, + run_plugin_migrations, + update_settings_from_fixture, +) +from flaskbb.utils.translations import compile_translations + + +logger = logging.getLogger(__name__) + + +~~class FlaskBBGroup(FlaskGroup): + def __init__(self, *args, **kwargs): + super(FlaskBBGroup, self).__init__(*args, **kwargs) + self._loaded_flaskbb_plugins = False + + def _load_flaskbb_plugins(self, ctx): + if self._loaded_flaskbb_plugins: + return + + try: + app = ctx.ensure_object(ScriptInfo).load_app() + app.pluggy.hook.flaskbb_cli(cli=self, app=app) + self._loaded_flaskbb_plugins = True + except Exception: + logger.error( + "Error while loading CLI Plugins", exc_info=traceback.format_exc() + ) + else: + shell_context_processors = app.pluggy.hook.flaskbb_shell_context() + for p in shell_context_processors: + app.shell_context_processor(p) + + def get_command(self, ctx, name): + self._load_flaskbb_plugins(ctx) + return super(FlaskBBGroup, self).get_command(ctx, name) + + +## ... source file continues with no further FlaskGroup examples... + +``` + + +## Example 2 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / cli / util.py**](https://github.com/indico/indico/blob/master/indico/cli/util.py) + +```python +# util.py + +import traceback +from importlib import import_module + +import click +~~from flask.cli import AppGroup, FlaskGroup, ScriptInfo +from flask_pluginengine import wrap_in_plugin_context +from werkzeug.utils import cached_property + + + + +def _create_app(info): + from indico.web.flask.app import make_app + return make_app() + + +~~class IndicoFlaskGroup(FlaskGroup): + + def __init__(self, **extra): + super().__init__(create_app=_create_app, add_default_commands=False, add_version_option=False, + set_debug_flag=False, **extra) + self._indico_plugin_commands = None + + def _load_plugin_commands(self): + assert False + + def _wrap_in_plugin_context(self, plugin, cmd): + cmd.callback = wrap_in_plugin_context(plugin, cmd.callback) + for subcmd in getattr(cmd, 'commands', {}).values(): + self._wrap_in_plugin_context(plugin, subcmd) + + def _get_indico_plugin_commands(self, ctx): + if self._indico_plugin_commands is not None: + return self._indico_plugin_commands + try: + from indico.core import signals + from indico.util.signals import named_objects_from_signal + ctx.ensure_object(ScriptInfo).load_app() + cmds = named_objects_from_signal(signals.plugin.cli.send(), plugin_attr='_indico_plugin') + rv = {} + for name, cmd in cmds.items(): + + +## ... source file continues with no further FlaskGroup examples... + +``` + diff --git a/content/pages/examples/flask/flask-cli-pass-script-info.markdown b/content/pages/examples/flask/flask-cli-pass-script-info.markdown new file mode 100644 index 000000000..2467707c5 --- /dev/null +++ b/content/pages/examples/flask/flask-cli-pass-script-info.markdown @@ -0,0 +1,111 @@ +title: flask.cli pass_script_info Example Code +category: page +slug: flask-cli-pass-script-info-examples +sortorder: 500021009 +toc: False +sidebartitle: flask.cli pass_script_info +meta: Python example code that shows how to use the pass_script_info callable from the flask.cli module of the Flask project. + + +[pass_script_info](https://github.com/pallets/flask/blob/master/src/flask/cli.py) +is simply a decorator around the [ScriptInfo](/flask-cli-scriptinfo-examples.html) +class within this same `flask.cli` module. + +AppGroup, +DispatchingApp, +FlaskGroup, +ScriptInfo, +and with_appcontext +are several other callables with code examples from the same `flask.cli` package. + +## Example 1 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / cli / core.py**](https://github.com/indico/indico/blob/master/indico/cli/core.py) + +```python +# core.py + +import click +~~from flask.cli import AppGroup, pass_script_info + +from indico.cli.util import IndicoFlaskGroup, LazyGroup + + +__all__ = ('cli_command', 'cli_group') + + +_cli = AppGroup() +cli_command = _cli.command +cli_group = _cli.group +del _cli + + +def _get_indico_version(ctx, param, value): + if not value or ctx.resilient_parsing: + return + import indico + message = f'Indico v{indico.__version__}' + click.echo(message, ctx.color) + ctx.exit() + + +@click.group(cls=IndicoFlaskGroup) +@click.option('--version', '-v', expose_value=False, callback=_get_indico_version, is_flag=True, is_eager=True, + + +## ... source file abbreviated to get to pass_script_info examples ... + + +@click.option('--min-age', type=click.IntRange(1), default=1, metavar='N', + help='Delete files at least N days old (default: 1)') +def cleanup(temp, cache, verbose, dry_run, min_age): + from .cleanup import cleanup_cmd + if not temp and not cache: + raise click.UsageError('You need to specify what to delete') + cleanup_cmd(temp, cache, min_age=min_age, dry_run=dry_run, verbose=(verbose or dry_run)) + + +@cli.command(with_appcontext=False) +@click.option('--host', '-h', default='127.0.0.1', metavar='HOST', help='The ip/host to bind to.') +@click.option('--port', '-p', default=None, type=int, metavar='PORT', help='The port to bind to.') +@click.option('--url', '-u', default=None, metavar='URL', + help='The URL used to access indico. Defaults to `http(s)://host:port`') +@click.option('--ssl', '-s', is_flag=True, help='Use SSL.') +@click.option('--ssl-key', '-K', type=click.Path(exists=True, dir_okay=False), help='The SSL private key to use.') +@click.option('--ssl-cert', '-C', type=click.Path(exists=True, dir_okay=False), help='The SSL cert key to use.') +@click.option('--quiet', '-q', is_flag=True, help='Disable logging of requests for most static files.') +@click.option('--enable-evalex', is_flag=True, + help="Enable the werkzeug debugger's python shell in tracebacks and via /console") +@click.option('--evalex-from', multiple=True, + help='Restrict the debugger shell to the given ips (can be used multiple times)') +@click.option('--proxy', is_flag=True, help='Use the ip and protocol provided by the proxy.') +@click.option('--reloader', 'reloader_type', type=click.Choice(['auto', 'none', 'stat', 'watchdog', 'watchman']), + default='auto', help='The type of auto-reloader to use.') +~~@pass_script_info +def run(info, **kwargs): + from indico.cli.devserver import run_cmd + if bool(kwargs['ssl_key']) != bool(kwargs['ssl_cert']): + raise click.BadParameter('ssl-key and ssl-cert must be used together') + run_cmd(info, **kwargs) + + +@cli.command(short_help='Run a shell in the app context.') +@click.option('-v', '--verbose', is_flag=True, help='Show verbose information on the available objects') +@click.option('-r', '--request-context', is_flag=True, help='Run the shell inside a Flask request context') +def shell(verbose, request_context): + from .shell import shell_cmd + shell_cmd(verbose, request_context) + + + +## ... source file continues with no further pass_script_info examples... + +``` + diff --git a/content/pages/examples/flask/flask-cli-scriptinfo.markdown b/content/pages/examples/flask/flask-cli-scriptinfo.markdown new file mode 100644 index 000000000..469bcd7b5 --- /dev/null +++ b/content/pages/examples/flask/flask-cli-scriptinfo.markdown @@ -0,0 +1,239 @@ +title: flask.cli ScriptInfo Example Code +category: page +slug: flask-cli-scriptinfo-examples +sortorder: 500021008 +toc: False +sidebartitle: flask.cli ScriptInfo +meta: Example code for understanding how to use the ScriptInfo class from the flask.cli module of the Flask project. + + +[ScriptInfo](https://github.com/pallets/flask/blob/master/src/flask/cli.py) +is a class within the `flask.cli` module of the [Flask](/flask.html) +framework. It is a helper object for Flask application and not usually +dealt with directly by developers, instead it is created automatically +by the [FlaskGroup](/flask-cli-flaskgroup-examples.html) object. + +AppGroup, +DispatchingApp, +FlaskGroup, +pass_script_info, +and with_appcontext +are several other callables with code examples from the same `flask.cli` package. + +## Example 1 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / cli / main.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/cli/main.py) + +```python +# main.py +import binascii +import logging +import os +import sys +import time +import traceback +from datetime import datetime + +import click +from flask import current_app +~~from flask.cli import FlaskGroup, ScriptInfo, with_appcontext +from flask_alembic import alembic_click +from jinja2 import Environment, FileSystemLoader +from sqlalchemy_utils.functions import database_exists +from werkzeug.utils import import_string + +from flaskbb import create_app +from flaskbb.cli.utils import ( + EmailType, + FlaskBBCLIError, + get_version, + prompt_config_path, + prompt_save_user, + write_config, +) +from flaskbb.extensions import alembic, celery, db, whooshee +from flaskbb.utils.populate import ( + create_default_groups, + create_default_settings, + create_latest_db, + create_test_data, + create_welcome_forum, + insert_bulk_data, + run_plugin_migrations, + update_settings_from_fixture, +) +from flaskbb.utils.translations import compile_translations + + +logger = logging.getLogger(__name__) + + +class FlaskBBGroup(FlaskGroup): + def __init__(self, *args, **kwargs): + super(FlaskBBGroup, self).__init__(*args, **kwargs) + self._loaded_flaskbb_plugins = False + + def _load_flaskbb_plugins(self, ctx): + if self._loaded_flaskbb_plugins: + return + + try: +~~ app = ctx.ensure_object(ScriptInfo).load_app() + app.pluggy.hook.flaskbb_cli(cli=self, app=app) + self._loaded_flaskbb_plugins = True + except Exception: + logger.error( + "Error while loading CLI Plugins", exc_info=traceback.format_exc() + ) + else: + shell_context_processors = app.pluggy.hook.flaskbb_shell_context() + for p in shell_context_processors: + app.shell_context_processor(p) + + def get_command(self, ctx, name): + self._load_flaskbb_plugins(ctx) + return super(FlaskBBGroup, self).get_command(ctx, name) + + def list_commands(self, ctx): + self._load_flaskbb_plugins(ctx) + return super(FlaskBBGroup, self).list_commands(ctx) + + +def make_app(): + ctx = click.get_current_context(silent=True) + script_info = None + if ctx is not None: + script_info = ctx.obj + + config_file = getattr(script_info, "config_file", None) + instance_path = getattr(script_info, "instance_path", None) + return create_app(config_file, instance_path) + + +def set_config(ctx, param, value): +~~ ctx.ensure_object(ScriptInfo).config_file = value + + +def set_instance(ctx, param, value): +~~ ctx.ensure_object(ScriptInfo).instance_path = value + + +@click.group( + cls=FlaskBBGroup, + create_app=make_app, + add_version_option=False, + invoke_without_command=True, +) +@click.option( + "--config", + expose_value=False, + callback=set_config, + required=False, + is_flag=False, + is_eager=True, + metavar="CONFIG", + help="Specify the config to use either in dotted module " + "notation e.g. 'flaskbb.configs.default.DefaultConfig' " + "or by using a path like '/path/to/flaskbb.cfg'", +) +@click.option( + "--instance", + expose_value=False, + callback=set_instance, + + +## ... source file continues with no further ScriptInfo examples... + +``` + + +## Example 2 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / cli / util.py**](https://github.com/indico/indico/blob/master/indico/cli/util.py) + +```python +# util.py + +import traceback +from importlib import import_module + +import click +~~from flask.cli import AppGroup, FlaskGroup, ScriptInfo +from flask_pluginengine import wrap_in_plugin_context +from werkzeug.utils import cached_property + + + + +def _create_app(info): + from indico.web.flask.app import make_app + return make_app() + + +class IndicoFlaskGroup(FlaskGroup): + + def __init__(self, **extra): + super().__init__(create_app=_create_app, add_default_commands=False, add_version_option=False, + set_debug_flag=False, **extra) + self._indico_plugin_commands = None + + def _load_plugin_commands(self): + assert False + + def _wrap_in_plugin_context(self, plugin, cmd): + cmd.callback = wrap_in_plugin_context(plugin, cmd.callback) + for subcmd in getattr(cmd, 'commands', {}).values(): + self._wrap_in_plugin_context(plugin, subcmd) + + def _get_indico_plugin_commands(self, ctx): + if self._indico_plugin_commands is not None: + return self._indico_plugin_commands + try: + from indico.core import signals + from indico.util.signals import named_objects_from_signal +~~ ctx.ensure_object(ScriptInfo).load_app() + cmds = named_objects_from_signal(signals.plugin.cli.send(), plugin_attr='_indico_plugin') + rv = {} + for name, cmd in cmds.items(): + if cmd._indico_plugin: + self._wrap_in_plugin_context(cmd._indico_plugin, cmd) + rv[name] = cmd + except Exception as exc: + if 'No indico config found' not in str(exc): + click.echo(click.style('Loading plugin commands failed:', fg='red', bold=True)) + click.echo(click.style(traceback.format_exc(), fg='red')) + rv = {} + self._indico_plugin_commands = rv + return rv + + def get_command(self, ctx, name): + rv = AppGroup.get_command(self, ctx, name) + if rv is not None: + return rv + return self._get_indico_plugin_commands(ctx).get(name) + + def list_commands(self, ctx): + rv = set(click.Group.list_commands(self, ctx)) + rv.update(self._get_indico_plugin_commands(ctx)) + return sorted(rv) + + +## ... source file continues with no further ScriptInfo examples... + +``` + diff --git a/content/pages/examples/flask/flask-cli-with-appcontext.markdown b/content/pages/examples/flask/flask-cli-with-appcontext.markdown new file mode 100644 index 000000000..e2d1ab675 --- /dev/null +++ b/content/pages/examples/flask/flask-cli-with-appcontext.markdown @@ -0,0 +1,232 @@ +title: flask.cli with_appcontext Example Code +category: page +slug: flask-cli-with-appcontext-examples +sortorder: 500021010 +toc: False +sidebartitle: flask.cli with_appcontext +meta: Python example code that shows how to use the with_appcontext callable from the flask.cli module of the Flask project. + + +[with_appcontext](https://github.com/pallets/flask/blob/master/src/flask/cli.py) +is a [Flask](/flask.html) decorator in the `flask.cli` module that +wraps a callback to guarantee it will be called with a script's +application context. Any callbacks registered with `app.cli` are +wrapped with this function by default. + +AppGroup, +DispatchingApp, +FlaskGroup, +ScriptInfo, +and pass_script_info +are several other callables with code examples from the same `flask.cli` package. + +## Example 1 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / cli / main.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/cli/main.py) + +```python +# main.py +import binascii +import logging +import os +import sys +import time +import traceback +from datetime import datetime + +import click +from flask import current_app +~~from flask.cli import FlaskGroup, ScriptInfo, with_appcontext +from flask_alembic import alembic_click +from jinja2 import Environment, FileSystemLoader +from sqlalchemy_utils.functions import database_exists +from werkzeug.utils import import_string + +from flaskbb import create_app +from flaskbb.cli.utils import ( + EmailType, + FlaskBBCLIError, + get_version, + prompt_config_path, + prompt_save_user, + write_config, +) +from flaskbb.extensions import alembic, celery, db, whooshee +from flaskbb.utils.populate import ( + create_default_groups, + create_default_settings, + create_latest_db, + create_test_data, + create_welcome_forum, + insert_bulk_data, + run_plugin_migrations, + update_settings_from_fixture, + + +## ... source file abbreviated to get to with_appcontext examples ... + + +def flaskbb(ctx): + if ctx.invoked_subcommand is None: + click.echo(ctx.get_help()) + + +flaskbb.add_command(alembic_click, "db") + + +@flaskbb.command() +@click.option( + "--welcome", "-w", default=True, is_flag=True, help="Disable the welcome forum." +) +@click.option( + "--force", "-f", default=False, is_flag=True, help="Doesn't ask for confirmation." +) +@click.option("--username", "-u", help="The username of the user.") +@click.option("--email", "-e", type=EmailType(), help="The email address of the user.") +@click.option("--password", "-p", help="The password of the user.") +@click.option( + "--no-plugins", + "-n", + default=False, + is_flag=True, + help="Don't run the migrations for the default plugins.", +) +~~@with_appcontext +def install(welcome, force, username, email, password, no_plugins): + if not current_app.config["CONFIG_PATH"]: + click.secho( + "[!] No 'flaskbb.cfg' config found. " + "You can generate a configuration file with 'flaskbb makeconfig'.", + fg="red", + ) + sys.exit(1) + + click.secho("[+] Installing FlaskBB...", fg="cyan") + if database_exists(db.engine.url): + if force or click.confirm( + click.style( + "Existing database found. Do you want to delete the old one and " + "create a new one?", + fg="magenta", + ) + ): + db.drop_all() + else: + sys.exit(0) + + create_latest_db() + + + +## ... source file abbreviated to get to with_appcontext examples ... + + + except ImportError: + raise FlaskBBCLIError( + "{} fixture is not available".format(fixture), fg="red" + ) + + click.secho("[+] Updating fixtures...", fg="cyan") + count = update_settings_from_fixture( + fixture=settings, overwrite_group=force, overwrite_setting=force + ) + click.secho( + "[+] {settings} settings in {groups} setting groups " + "updated.".format( + groups=len(count), + settings=sum(len(settings) for settings in count.values()), + ), + fg="green", + ) + + +@flaskbb.command( + "celery", + add_help_option=False, + context_settings={"ignore_unknown_options": True, "allow_extra_args": True}, +) +@click.pass_context +~~@with_appcontext +def start_celery(ctx): + celery.start(ctx.args) + + +@flaskbb.command("shell", short_help="Runs a shell in the app context.") +~~@with_appcontext +def shell_command(): + import code + + banner = "Python %s on %s\nInstance Path: %s" % ( + sys.version, + sys.platform, + current_app.instance_path, + ) + ctx = {"db": db} + + startup = os.environ.get("PYTHONSTARTUP") + if startup and os.path.isfile(startup): + with open(startup, "r") as f: + eval(compile(f.read(), startup, "exec"), ctx) + + ctx.update(current_app.make_shell_context()) + + try: + import IPython + from traitlets.config import get_config + + c = get_config() + c.InteractiveShellEmbed.colors = "Linux" + IPython.embed(config=c, banner1=banner, user_ns=ctx) + except ImportError: + code.interact(banner=banner, local=ctx) + + +@flaskbb.command("urls", short_help="Show routes for the app.") +@click.option( + "--route", "-r", "order_by", flag_value="rule", default=True, help="Order by route" +) +@click.option( + "--endpoint", "-e", "order_by", flag_value="endpoint", help="Order by endpoint" +) +@click.option( + "--methods", "-m", "order_by", flag_value="methods", help="Order by methods" +) +~~@with_appcontext +def list_urls(order_by): + from flask import current_app + + rules = sorted( + current_app.url_map.iter_rules(), key=lambda rule: getattr(rule, order_by) + ) + + max_rule_len = max(len(rule.rule) for rule in rules) + max_rule_len = max(max_rule_len, len("Route")) + + max_endpoint_len = max(len(rule.endpoint) for rule in rules) + max_endpoint_len = max(max_endpoint_len, len("Endpoint")) + + max_method_len = max(len(", ".join(rule.methods)) for rule in rules) + max_method_len = max(max_method_len, len("Methods")) + + column_header_len = max_rule_len + max_endpoint_len + max_method_len + 4 + column_template = "{:<%s} {:<%s} {:<%s}" % ( + max_rule_len, + max_endpoint_len, + max_method_len, + ) + + click.secho( + + +## ... source file continues with no further with_appcontext examples... + +``` + diff --git a/content/pages/examples/flask/flask-code-examples.markdown b/content/pages/examples/flask/flask-code-examples.markdown deleted file mode 100644 index 468e988b5..000000000 --- a/content/pages/examples/flask/flask-code-examples.markdown +++ /dev/null @@ -1,79 +0,0 @@ -title: Flask Core and Extensions Code Examples -category: page -slug: flask-core-extensions-code-examples -sortorder: 500020000 -toc: False -sidebartitle: Flask Core and Extensions Code Examples -meta: Learn how to create Flask applications with easy to copy and paste Python code examples for the Flask web framework. - - -[Flask](/flask.html) is a Python [web framework](/web-frameworks.html). - -Official Flask logo. Flask Artwork License. - - -## Flask Example Projects -Flask's large ecosystem of extensions make it easier for developers to -build common web app features such as authentication, -[database](/databases.html) operations and -[APIs](/application-programming-interfaces.html) even though support -is not built into the core Flask [web framework](/web-frameworks.html). -This design is by choice in contrast to [Django](/django.html)'s -"batteries-included" approach. Either framework's design decision -is a viable approach depending on the needs and requirements of the -application you are building. - -The extensive collection of Flask libraries is a great source for -learning the framework through reading code examples. - -This alphabetically-ordered list of projects provide helpful example -code for building your own web apps. - - -### flask-base -[flask-base](https://github.com/hack4impact/flask-base) -([project documentation](http://hack4impact.github.io/flask-base/)) -is a boilerplate starter application that is pre-configured with -[SQLAlchemy](/sqlalchemy.html), [Redis](/redis.html), user -authentication and other features. - -flask-base's code is open sourced -[under the MIT license](https://github.com/hack4impact/flask-base/blob/master/LICENSE.md). - - -### FlaskBB -[FlaskBB](https://github.com/flaskbb/flaskbb) -([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based -forum web application. The web app allows users to chat in an open -message board or send private messages in plain text or -[Markdown](/markdown.html). - -FlaskBB is provided as open source -[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). - -FlaskBB's code examples can be found on: - -* [flask redirect](/flask-redirect-examples.html) -* [flask request](/flask-request-examples.html) - - -### Flasky -[Flasky](https://github.com/miguelgrinberg/flasky) is the wonderful -example application by -[Miguel Grinberg](https://github.com/miguelgrinberg) that he builds -while teaching developers how to use [Flask](/flask.html) in -[his books and videos](https://courses.miguelgrinberg.com/). Flasky -is [open sourced under the MIT license](https://github.com/miguelgrinberg/flasky/blob/master/LICENSE). - -Code examples from Flasky are shown on the following pages: - -* [flask_sqlalchemy SQLAlchemy Model](/flask-sqlalchemy-model-examples.html) - - -### newspie -[NewsPie](https://github.com/skamieniarz/newspie) is a minimalistic news -aggregator created with [Flask](/flask.html) and the -[News API](https://newsapi.org/). - -NewsPie is provided as open source under the -[MIT license](https://github.com/skamieniarz/newspie/blob/master/LICENSE). diff --git a/content/pages/examples/flask/flask-ctx-after-this-request.markdown b/content/pages/examples/flask/flask-ctx-after-this-request.markdown new file mode 100644 index 000000000..f18d7b9b7 --- /dev/null +++ b/content/pages/examples/flask/flask-ctx-after-this-request.markdown @@ -0,0 +1,296 @@ +title: flask.ctx after_this_request Example Code +category: page +slug: flask-ctx-after-this-request-examples +sortorder: 500021011 +toc: False +sidebartitle: flask.ctx after_this_request +meta: Python example code that shows how to use the after_this_request callable from the flask.ctx module of the Flask project. + + +[after_this_request](https://github.com/pallets/flask/blob/master/src/flask/ctx.py) +is a function in the `flask.ctx` module of the [Flask](/flask.html) +[web framework](/web-frameworks.html). The function's name is strongly +descriptive of what it does and it particularly useful for modifying +response objects, especially when you want a function other than the +view function to modify a response. + +has_app_context +and +has_request_context +are a couple of other callables within the `flask.ctx` package that also have code examples. + +## Example 1 from Flask-Security-Too +[Flask-Security-Too](https://github.com/Flask-Middleware/flask-security/) +([PyPi page](https://pypi.org/project/Flask-Security-Too/) and +[project documentation](https://flask-security-too.readthedocs.io/en/stable/)) +is a maintained fork of the original +[Flask-Security](https://github.com/mattupstate/flask-security) project that +makes it easier to add common security features to [Flask](/flask.html) +web applications. A few of the critical goals of the Flask-Security-Too +project are ensuring JavaScript client-based single-page applications (SPAs) +can work securely with Flask-based backends and that guidance by the +[OWASP](https://owasp.org/) organization is followed by default. + +The Flask-Security-Too project is provided as open source under the +[MIT license](https://github.com/Flask-Middleware/flask-security/blob/master/LICENSE). + +[**Flask-Security-Too / flask_security / unified_signin.py**](https://github.com/Flask-Middleware/flask-security/blob/master/flask_security/./unified_signin.py) + +```python +# unified_signin.py + +import time +import typing as t + +from flask import current_app as app +~~from flask import after_this_request, request, session +from flask_login import current_user +from werkzeug.datastructures import MultiDict +from wtforms import BooleanField, RadioField, StringField, SubmitField, validators + +from .confirmable import requires_confirmation +from .decorators import anonymous_user_required, auth_required, unauth_csrf +from .forms import Form, Required, get_form_field_label +from .proxies import _security, _datastore +from .quart_compat import get_quart_status +from .signals import us_profile_changed, us_security_token_sent +from .twofactor import ( + is_tf_setup, + tf_login, + tf_verify_validility_token, +) +from .utils import ( + _, + SmsSenderFactory, + base_render_json, + check_and_get_token_status, + config_value as cv, + do_flash, + find_user, + get_identity_attributes, + + +## ... source file abbreviated to get to after_this_request examples ... + + + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def validate(self): + if not super().validate(): + return False + + if not _security._totp_factory.verify_totp( + token=self.passcode.data, + totp_secret=self.totp_secret, + user=self.user, + window=cv("US_TOKEN_VALIDITY"), + ): + self.passcode.errors.append(get_message("INVALID_PASSWORD_CODE")[0]) + return False + + return True + + +def _send_code_helper(form): + user = form.user + method = form.chosen_method.data + totp_secrets = _datastore.us_get_totp_secrets(user) + if method == "email" and method not in totp_secrets: +~~ after_this_request(view_commit) + totp_secrets[method] = _security._totp_factory.generate_totp_secret() + _datastore.us_put_totp_secrets(user, totp_secrets) + + msg = user.us_send_security_token( + method, + totp_secret=totp_secrets[method], + phone_number=getattr(user, "us_phone_number", None), + send_magic_link=True, + ) + code_sent = True + if msg: + code_sent = False + form.chosen_method.errors.append(msg) + return code_sent, msg + + +@anonymous_user_required +@unauth_csrf(fall_through=True) +def us_signin_send_code(): + form_class = _security.us_signin_form + + if request.is_json: + if request.content_length: + form = form_class(MultiDict(request.get_json()), meta=suppress_form_csrf()) + + +## ... source file abbreviated to get to after_this_request examples ... + + + form.submit.data = True + + if form.validate_on_submit(): + + remember_me = form.remember.data if "remember" in form else None + if cv("TWO_FACTOR") and form.authn_via in cv("US_MFA_REQUIRED"): + if request.is_json and request.content_length: + tf_validity_token = request.get_json().get( # type: ignore + "tf_validity_token", None + ) + else: + tf_validity_token = request.cookies.get("tf_validity", default=None) + + tf_validity_token_is_valid = tf_verify_validility_token( + tf_validity_token, form.user.fs_uniquifier + ) + if cv("TWO_FACTOR_REQUIRED") or is_tf_setup(form.user): + if cv("TWO_FACTOR_ALWAYS_VALIDATE") or (not tf_validity_token_is_valid): + + return tf_login( + form.user, + remember=remember_me, + primary_authn_via=form.authn_via, + ) + +~~ after_this_request(view_commit) + login_user(form.user, remember=remember_me, authn_via=[form.authn_via]) + + if _security._want_json(request): + return base_render_json(form, include_auth_token=True) + + return redirect(get_post_login_redirect()) + + code_methods = _compute_code_methods() + if _security._want_json(request): + payload = { + "available_methods": cv("US_ENABLED_METHODS"), + "code_methods": code_methods, + "identity_attributes": get_identity_attributes(), + } + return base_render_json(form, include_user=False, additional=payload) + + if current_user.is_authenticated: + return redirect(get_post_login_redirect()) + + form.passcode.data = None + + if form.requires_confirmation and cv("REQUIRES_CONFIRMATION_ERROR_VIEW"): + do_flash(*get_message("CONFIRMATION_REQUIRED")) + return redirect(get_url(cv("REQUIRES_CONFIRMATION_ERROR_VIEW"))) + + +## ... source file abbreviated to get to after_this_request examples ... + + + if _security.redirect_behavior == "spa": + return redirect( + get_url( + cv("LOGIN_ERROR_VIEW"), + qparams=user.get_redirect_qparams({c: m}), + ) + ) + do_flash(m, c) + return redirect(url_for_security("us_signin")) + + if ( + cv("TWO_FACTOR") + and "email" in cv("US_MFA_REQUIRED") + and (cv("TWO_FACTOR_REQUIRED") or is_tf_setup(user)) + ): + if _security.redirect_behavior == "spa": + return redirect( + get_url( + cv("LOGIN_ERROR_VIEW"), + qparams=user.get_redirect_qparams({"tf_required": 1}), + ) + ) + return tf_login(user, primary_authn_via="email") + + login_user(user, authn_via=["email"]) +~~ after_this_request(view_commit) + if _security.redirect_behavior == "spa": + return redirect( + get_url(cv("POST_LOGIN_VIEW"), qparams=user.get_redirect_qparams()) + ) + + do_flash(*get_message("PASSWORDLESS_LOGIN_SUCCESSFUL")) + return redirect(get_post_login_redirect()) + + +@auth_required( + lambda: cv("API_ENABLED_METHODS"), + within=lambda: cv("FRESHNESS"), + grace=lambda: cv("FRESHNESS_GRACE_PERIOD"), +) +def us_setup() -> "ResponseValue": + form_class = _security.us_setup_form + + if request.is_json: + if request.content_length: + form = form_class(MultiDict(request.get_json()), meta=suppress_form_csrf()) + else: + form = form_class(formdata=None, meta=suppress_form_csrf()) + else: + form = form_class(meta=suppress_form_csrf()) + + +## ... source file abbreviated to get to after_this_request examples ... + + + form_class = _security.us_setup_validate_form + + if request.is_json: + form = form_class(MultiDict(request.get_json()), meta=suppress_form_csrf()) + else: + form = form_class(meta=suppress_form_csrf()) + + expired, invalid, state = check_and_get_token_status( + token, "us_setup", get_within_delta("US_SETUP_WITHIN") + ) + if invalid: + m, c = get_message("API_ERROR") + if expired: + m, c = get_message("US_SETUP_EXPIRED", within=cv("US_SETUP_WITHIN")) + if invalid or expired: + if _security._want_json(request): + payload = json_error_response(errors=m) + return _security._render_json(payload, 400, None, None) + do_flash(m, c) + return redirect(url_for_security("us_setup")) + + form.totp_secret = state["totp_secret"] + form.user = current_user + + if form.validate_on_submit(): +~~ after_this_request(view_commit) + method = state["chosen_method"] + phone = state["phone_number"] if method == "sms" else None + _datastore.us_set(current_user, method, state["totp_secret"], phone) + + us_profile_changed.send( + app._get_current_object(), user=current_user, method=method # type: ignore + ) + if _security._want_json(request): + return base_render_json( + form, + include_user=False, + additional=dict( + chosen_method=method, phone=current_user.us_phone_number + ), + ) + else: + do_flash(*get_message("US_SETUP_SUCCESSFUL")) + return redirect( + get_url(cv("US_POST_SETUP_VIEW")) or get_url(cv("POST_LOGIN_VIEW")) + ) + + if _security._want_json(request): + return base_render_json(form, include_user=False) + m, c = get_message("INVALID_PASSWORD_CODE") + + +## ... source file continues with no further after_this_request examples... + +``` + diff --git a/content/pages/examples/flask/flask-ctx-has-app-context.markdown b/content/pages/examples/flask/flask-ctx-has-app-context.markdown new file mode 100644 index 000000000..d4a03d102 --- /dev/null +++ b/content/pages/examples/flask/flask-ctx-has-app-context.markdown @@ -0,0 +1,205 @@ +title: flask.ctx has_app_context Example Code +category: page +slug: flask-ctx-has-app-context-examples +sortorder: 500021012 +toc: False +sidebartitle: flask.ctx has_app_context +meta: Python example code that shows how to use the has_app_context callable from the flask.ctx module of the Flask project. + + +[has_app_context](https://github.com/pallets/flask/blob/master/src/flask/ctx.py) +is a function in the `flask.ctx` module that is similar to +[has_request_context](/flask-ctx-has-request-context-examples.html) +but for the +[application context](https://flask.palletsprojects.com/en/1.1.x/appcontext/) +rather than the request. + +after_this_request +and +has_request_context +are a couple of other callables within the `flask.ctx` package that also have code examples. + +## Example 1 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / marshalling.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./marshalling.py) + +```python +# marshalling.py +from __future__ import unicode_literals + +from collections import OrderedDict +from functools import wraps +from six import iteritems + +~~from flask import request, current_app, has_app_context + +from .mask import Mask, apply as apply_mask +from .utils import unpack + + +def make(cls): + if isinstance(cls, type): + return cls() + return cls + + +def marshal(data, fields, envelope=None, skip_none=False, mask=None, ordered=False): + out, has_wildcards = _marshal(data, fields, envelope, skip_none, mask, ordered) + + if has_wildcards: + from .fields import Wildcard + + items = [] + keys = [] + for dkey, val in fields.items(): + key = dkey + if isinstance(val, dict): + value = marshal(data, val, skip_none=skip_none, ordered=ordered) + else: + + +## ... source file abbreviated to get to has_app_context examples ... + + + + out = OrderedDict(items) if ordered else dict(items) + + if envelope: + out = OrderedDict([(envelope, out)]) if ordered else {envelope: out} + + return out, has_wildcards["present"] + + +class marshal_with(object): + + def __init__( + self, fields, envelope=None, skip_none=False, mask=None, ordered=False + ): + self.fields = fields + self.envelope = envelope + self.skip_none = skip_none + self.ordered = ordered + self.mask = Mask(mask, skip=True) + + def __call__(self, f): + @wraps(f) + def wrapper(*args, **kwargs): + resp = f(*args, **kwargs) + mask = self.mask +~~ if has_app_context(): + mask_header = current_app.config["RESTX_MASK_HEADER"] + mask = request.headers.get(mask_header) or mask + if isinstance(resp, tuple): + data, code, headers = unpack(resp) + return ( + marshal( + data, + self.fields, + self.envelope, + self.skip_none, + mask, + self.ordered, + ), + code, + headers, + ) + else: + return marshal( + resp, self.fields, self.envelope, self.skip_none, mask, self.ordered + ) + + return wrapper + + + + +## ... source file continues with no further has_app_context examples... + +``` + + +## Example 2 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / util / i18n.py**](https://github.com/indico/indico/blob/master/indico/util/i18n.py) + +```python +# i18n.py + +import ast +import re +from collections import Counter +from contextlib import contextmanager + +from babel import negotiate_locale +from babel.core import LOCALE_ALIASES, Locale +from babel.messages.pofile import read_po +from babel.support import NullTranslations +~~from flask import current_app, g, has_app_context, has_request_context, request, session +from flask_babel import Babel, Domain, get_domain +from flask_pluginengine import current_plugin +from speaklater import is_lazy_string, make_lazy_string +from werkzeug.utils import cached_property + +from indico.core.config import config +from indico.util.caching import memoize_request + + +LOCALE_ALIASES = dict(LOCALE_ALIASES, en='en_GB') +RE_TR_FUNCTION = re.compile(r'''_\("([^"]*)"\)|_\('([^']*)'\)''', re.DOTALL | re.MULTILINE) + +babel = Babel() +_use_context = object() + + +def get_translation_domain(plugin_name=_use_context): + if plugin_name is None: + return get_domain() + else: + plugin = None +~~ if has_app_context(): + from indico.core.plugins import plugin_engine + plugin = plugin_engine.get_plugin(plugin_name) if plugin_name is not _use_context else current_plugin + if plugin: + return plugin.translation_domain + else: + return get_domain() + + +def _indico_gettext(*args, **kwargs): + func_name = kwargs.pop('func_name', 'gettext') + plugin_name = kwargs.pop('plugin_name', None) + + translations = get_translation_domain(plugin_name).get_translations() + return getattr(translations, func_name)(*args, **kwargs) + + +def lazy_gettext(string, plugin_name=None): + if is_lazy_string(string): + return string + return make_lazy_string(_indico_gettext, string, plugin_name=plugin_name) + + +def orig_string(lazy_string): + return lazy_string._args[0] if is_lazy_string(lazy_string) else lazy_string + + +## ... source file continues with no further has_app_context examples... + +``` + diff --git a/content/pages/examples/flask/flask-ctx-has-request-context.markdown b/content/pages/examples/flask/flask-ctx-has-request-context.markdown new file mode 100644 index 000000000..9fe1163e0 --- /dev/null +++ b/content/pages/examples/flask/flask-ctx-has-request-context.markdown @@ -0,0 +1,369 @@ +title: flask.ctx has_request_context Example Code +category: page +slug: flask-ctx-has-request-context-examples +sortorder: 500021013 +toc: False +sidebartitle: flask.ctx has_request_context +meta: Python example code that shows how to use the has_request_context callable from the flask.ctx module of the Flask project. + + +[has_request_context](https://github.com/pallets/flask/blob/master/src/flask/ctx.py) +is a function within the `flask.ctx` module that is useful for +determining if a +[request context](https://flask.palletsprojects.com/en/1.1.x/reqcontext/) +is available or not. There is a similar +[has_app_context](/flask-ctx-has-app-context-examples.html) +function as well that works for the +[application context](https://flask.palletsprojects.com/en/1.1.x/appcontext/). + + +after_this_request +and +has_app_context +are a couple of other callables within the `flask.ctx` package that also have code examples. + +## Example 1 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / babel / manager.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/babel/manager.py) + +```python +# manager.py +import os + +~~from flask import has_request_context, request, session +from flask_babel import Babel + +from .views import LocaleView +from ..basemanager import BaseManager + + +class BabelManager(BaseManager): + + babel = None + locale_view = None + + def __init__(self, appbuilder): + super(BabelManager, self).__init__(appbuilder) + app = appbuilder.get_app + app.config.setdefault("BABEL_DEFAULT_LOCALE", "en") + if not app.config.get("LANGUAGES"): + app.config["LANGUAGES"] = {"en": {"flag": "us", "name": "English"}} + appbuilder_parent_dir = os.path.join( + os.path.dirname(os.path.abspath(__file__)), os.pardir + ) + appbuilder_translations_path = os.path.join( + appbuilder_parent_dir, "translations" + ) + if "BABEL_TRANSLATION_DIRECTORIES" in app.config: + current_translation_directories = app.config.get( + "BABEL_TRANSLATION_DIRECTORIES" + ) + translations_path = ( + appbuilder_translations_path + ";" + current_translation_directories + ) + else: + translations_path = appbuilder_translations_path + ";translations" + app.config["BABEL_TRANSLATION_DIRECTORIES"] = translations_path + self.babel = Babel(app) + self.babel.locale_selector_func = self.get_locale + + def register_views(self): + self.locale_view = LocaleView() + self.appbuilder.add_view_no_menu(self.locale_view) + + @property + def babel_default_locale(self): + return self.appbuilder.get_app.config["BABEL_DEFAULT_LOCALE"] + + @property + def languages(self): + return self.appbuilder.get_app.config["LANGUAGES"] + + def get_locale(self): +~~ if has_request_context(): + for arg, value in request.args.items(): + if arg == "_l_": + if value in self.languages: + return value + else: + return self.babel_default_locale + locale = session.get("locale") + if locale: + return locale + session["locale"] = self.babel_default_locale + return session["locale"] + + + +## ... source file continues with no further has_request_context examples... + +``` + + +## Example 2 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / forum / locals.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/forum/locals.py) + +```python +# locals.py + +~~from flask import _request_ctx_stack, has_request_context, request +from werkzeug.local import LocalProxy + +from .models import Category, Forum, Post, Topic + + +@LocalProxy +def current_post(): + return _get_item(Post, 'post_id', 'post') + + +@LocalProxy +def current_topic(): + if current_post: + return current_post.topic + return _get_item(Topic, 'topic_id', 'topic') + + +@LocalProxy +def current_forum(): + if current_topic: + return current_topic.forum + return _get_item(Forum, 'forum_id', 'forum') + + +@LocalProxy +def current_category(): + if current_forum: + return current_forum.category + return _get_item(Category, 'category_id', 'category') + + +def _get_item(model, view_arg, name): + if ( +~~ has_request_context() and + not getattr(_request_ctx_stack.top, name, None) and + view_arg in request.view_args + ): + setattr( + _request_ctx_stack.top, + name, + model.query.filter_by(id=request.view_args[view_arg]).first() + ) + + return getattr(_request_ctx_stack.top, name, None) + + + +## ... source file continues with no further has_request_context examples... + +``` + + +## Example 3 from Flask-SocketIO +[Flask-SocketIO](https://github.com/miguelgrinberg/Flask-SocketIO) +([PyPI package information](https://pypi.org/project/Flask-SocketIO/), +[official tutorial](https://blog.miguelgrinberg.com/post/easy-websockets-with-flask-and-gevent) +and +[project documentation](https://flask-socketio.readthedocs.io/en/latest/)) +is a code library by [Miguel Grinberg](https://blog.miguelgrinberg.com/index) +that provides Socket.IO integration for [Flask](/flask.html) applications. +This extension makes it easier to add bi-directional communications on the +web via the [WebSockets](/websockets.html) protocol. + +The Flask-SocketIO project is open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/LICENSE). + +[**Flask-SocketIO / flask_socketio / __init__.py**](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/./flask_socketio/__init__.py) + +```python +# __init__.py +from functools import wraps +import os +import sys + +gevent_socketio_found = True +try: + from socketio import socketio_manage # noqa: F401 +except ImportError: + gevent_socketio_found = False +if gevent_socketio_found: + print('The gevent-socketio package is incompatible with this version of ' + 'the Flask-SocketIO extension. Please uninstall it, and then ' + 'install the latest version of python-socketio in its place.') + sys.exit(1) + +import flask +~~from flask import _request_ctx_stack, has_request_context, json as flask_json +from flask.sessions import SessionMixin +import socketio +from socketio.exceptions import ConnectionRefusedError # noqa: F401 +from werkzeug.debug import DebuggedApplication +from werkzeug.serving import run_with_reloader + +from .namespace import Namespace +from .test_client import SocketIOTestClient + +__version__ = '5.0.2dev' + + +class _SocketIOMiddleware(socketio.WSGIApp): + def __init__(self, socketio_app, flask_app, socketio_path='socket.io'): + self.flask_app = flask_app + super(_SocketIOMiddleware, self).__init__(socketio_app, + flask_app.wsgi_app, + socketio_path=socketio_path) + + def __call__(self, environ, start_response): + environ = environ.copy() + environ['flask.app'] = self.flask_app + return super(_SocketIOMiddleware, self).__call__(environ, + start_response) + + +## ... source file abbreviated to get to has_request_context examples ... + + + else: + def set_handler(handler): + return self.on(handler.__name__, *args, **kwargs)(handler) + + return set_handler + + def on_namespace(self, namespace_handler): + if not isinstance(namespace_handler, Namespace): + raise ValueError('Not a namespace instance.') + namespace_handler._set_socketio(self) + if self.server: + self.server.register_namespace(namespace_handler) + else: + self.namespace_handlers.append(namespace_handler) + + def emit(self, event, *args, **kwargs): + namespace = kwargs.pop('namespace', '/') + to = kwargs.pop('to', kwargs.pop('room', None)) + include_self = kwargs.pop('include_self', True) + skip_sid = kwargs.pop('skip_sid', None) + if not include_self and not skip_sid: + skip_sid = flask.request.sid + callback = kwargs.pop('callback', None) + if callback: + sid = None +~~ if has_request_context(): + sid = getattr(flask.request, 'sid', None) + original_callback = callback + + def _callback_wrapper(*args): + return self._handle_event(original_callback, None, namespace, + sid, *args) + + if sid: + callback = _callback_wrapper + self.server.emit(event, *args, namespace=namespace, to=to, + skip_sid=skip_sid, callback=callback, **kwargs) + + def send(self, data, json=False, namespace=None, to=None, + callback=None, include_self=True, skip_sid=None, **kwargs): + skip_sid = flask.request.sid if not include_self else skip_sid + if json: + self.emit('json', data, namespace=namespace, to=to, + skip_sid=skip_sid, callback=callback, **kwargs) + else: + self.emit('message', data, namespace=namespace, to=to, + skip_sid=skip_sid, callback=callback, **kwargs) + + def close_room(self, room, namespace=None): + self.server.close_room(room, namespace) + + +## ... source file continues with no further has_request_context examples... + +``` + + +## Example 4 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / core / logger.py**](https://github.com/indico/indico/blob/master/indico/core/logger.py) + +```python +# logger.py + +import logging +import logging.config +import logging.handlers +import os +import warnings +from pprint import pformat + +import yaml +~~from flask import has_request_context, request, session + +from indico.core.config import config +from indico.web.util import get_request_info, get_request_user + + +class AddRequestIDFilter: + def filter(self, record): +~~ record.request_id = request.id if has_request_context() else '0' * 16 + return True + + +class AddUserIDFilter: + def filter(self, record): +~~ user = get_request_user()[0] if has_request_context() else None + record.user_id = str(session.user.id) if user else '-' + return True + + +class RequestInfoFormatter(logging.Formatter): + def format(self, record): + rv = super().format(record) + info = get_request_info() + if info: + rv += '\n\n' + pformat(info) + return rv + + +class FormattedSubjectSMTPHandler(logging.handlers.SMTPHandler): + def getSubject(self, record): + return self.subject % record.__dict__ + + +class BlacklistFilter(logging.Filter): + def __init__(self, names): + self.filters = [logging.Filter(name) for name in names] + + def filter(self, record): + return not any(x.filter(record) for x in self.filters) + + +## ... source file continues with no further has_request_context examples... + +``` + diff --git a/content/pages/examples/flask/flask-example-projects-code.markdown b/content/pages/examples/flask/flask-example-projects-code.markdown new file mode 100644 index 000000000..e8a469a5d --- /dev/null +++ b/content/pages/examples/flask/flask-example-projects-code.markdown @@ -0,0 +1,189 @@ +title: Flask Example Projects and Code +category: page +slug: flask-code-examples +sortorder: 500020001 +toc: False +sidebartitle: Flask Example Code +meta: Python example projects and code that show how to use the Flask web microframework. + + +## Example Projects with Great Example Code +The following active projects use the [Flask](/flask.html) framework +in various ways. The code within the projects can show you how to build +your own applications. + + +### Braintree Flask example +[Braintree's Flask example payments app](https://github.com/braintree/braintree_flask_example) +demonstrates how to incorporate this payment provider's +[API](/application-programming-interfaces.html) into your +[Flask](/flask.html) [web application](/web-development.html). +The code is open sourced under the +[MIT license](https://github.com/braintree/braintree_flask_example/blob/master/LICENSE). + + +### CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + + +### Datadog Flask example +The [Datadog Flask app](https://github.com/DataDog/trace-examples/tree/master/python/flask) +contains many examples of the [Flask](/flask.html) core functions +available to a developer using the [web framework](/web-frameworks.html). + + +### Deploy Keras Model with Flask as Web App in 10 Minutes +The +[keras-flask-deploy-webapp](https://github.com/mtobeiyf/keras-flask-deploy-webapp) +project combines the [Flask](/flask.html) [web framework](/web-frameworks.html) +with the [Keras deep learning library](https://keras.io/) to provide +an example image classifier that is easy to [deploy](/deployment.html). +The application can be quckly run in a [Docker](/docker.html) container +on your local development environment. The project is licensed under the +[GNU General Public License v3.0](https://github.com/mtobeiyf/keras-flask-deploy-webapp/blob/master/LICENSE). + + +### FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + + +### flask-bones +[flask-bones](https://github.com/cburmeister/flask-bones) +([demo](http://flask-bones.herokuapp.com/)) +is large scale [Flask](/flask.html) example application built +with [Blueprints](https://flask.palletsprojects.com/en/1.1.x/blueprints/) +([example Blueprint code](/flask-blueprints-blueprint-examples.html)). +This project is provided as open source under the +[MIT license](https://github.com/cburmeister/flask-bones/blob/master/LICENSE). + + +### Flaskex +[Flaskex](https://github.com/anfederico/Flaskex) is a working example +[Flask](/flask.html) web application intended as a base to build your +own applications upon. The application comes with pre-built sign up, log in +and related screens, as well as a database backend. Flaskex is provided +as open source under the +[MIT license](https://github.com/anfederico/Flaskex/blob/master/LICENSE.txt). + + +### Flask Bookshelf +[flask-bookshelf](https://github.com/damyanbogoev/flask-bookshelf) is the +example [Flask](/flask.html) application that developers create when +going through +[this Flask series of blog posts](https://damyanon.net/tags/flask-series/). + + +### Flask JSONDash +[Flask JSONDash](https://github.com/christabor/flask_jsondash) is a +configurable web application built in Flask that creates charts and +dashboards from arbitrary API endpoints. Everything for the web app +is configured in JSON. The code is provided as open source under the +[MIT license](https://github.com/christabor/flask_jsondash/blob/master/LICENSE). + + +### flask-phone-input +[flask-phone-input](https://github.com/miguelgrinberg/flask-phone-input) +is an example application that ties together the +[intTellInput.js](https://github.com/jackocnr/intl-tel-input) +JavaScript plugin with the +[Flask-WTF](https://flask-wtf.readthedocs.io/) form-handling +library. flask-phone-input is provided as open source under the +[MIT license](https://github.com/miguelgrinberg/flask-phone-input/blob/1a1c227c044474ce0fe133493d7f8b0fb8312409/LICENSE). + + +### flaskSaaS +[flaskSaas](https://github.com/alectrocute/flaskSaaS) is a boilerplate +starter project to build a software-as-a-service (SaaS) web application +in [Flask](/flask.html), with [Stripe](/stripe.html) for billing. The +boilerplate relies on many common Flask extensions such as +[Flask-WTF](https://flask-wtf.readthedocs.io/en/latest/), +[Flask-Login](https://flask-login.readthedocs.io/en/latest/), +[Flask-Admin](https://flask-admin.readthedocs.io/en/latest/), and +many others. The project is provided as open source under the +[MIT license](https://github.com/alectrocute/flaskSaaS/blob/master/LICENSE). + + +### Flasky +[Flasky](https://github.com/miguelgrinberg/flasky) is a wonderful +example application by +[Miguel Grinberg](https://github.com/miguelgrinberg) that he builds +while teaching developers how to use [Flask](/flask.html) in +[his books and videos](https://courses.miguelgrinberg.com/). Flasky +is [open sourced under the MIT license](https://github.com/miguelgrinberg/flasky/blob/master/LICENSE). + + +### indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + + +### newspie +[NewsPie](https://github.com/skamieniarz/newspie) is a minimalistic news +aggregator created with [Flask](/flask.html) and the +[News API](https://newsapi.org/). NewsPie is provided as open source under +the [MIT license](https://github.com/skamieniarz/newspie/blob/master/LICENSE). + + +### Science Flask +[Science Flask](https://github.com/danielhomola/science_flask) +is a [Flask](/flask.html)-powered web application for online +scientific research tools. The project was built as a template +for any scientist or groups of scientists to use when working +together without having to really understand how the application +is built. The application includes an academic registration +process (only valid academic email addresses can be used), an +admin panel, logging, and analysis forms. + +[@danielhomola](https://github.com/danielhomola) is the +primary creator of Science Flask and the project is open +source under the +[GNU General Public License](https://github.com/danielhomola/science_flask/blob/master/LICENSE). + + +### ShortMe-URL-Shortener +[ShortMe](https://github.com/AcrobaticPanicc/ShortMe-URL-Shortener) +is a [Flask](/flask.html) app that creates a shortened URL +that redirects to another, typically much longer, URL. The +project is provided as open source under the +[MIT license](https://github.com/AcrobaticPanicc/ShortMe-URL-Shortener/blob/main/LICENSE). + + +### tedivm's flask starter app +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + + +### trape +[trape](https://github.com/jofpin/trape) is a research tool for tracking +people's activities that are logged digitally. The tool uses +[Flask](/flask.html) to create a web front end to view aggregated data +on an individual the application is set to track. The source code is +provided as open source under the MIT license, according to the +[README](https://github.com/jofpin/trape/blob/master/README.md). + diff --git a/content/pages/examples/flask/flask-extensions-plug-ins.markdown b/content/pages/examples/flask/flask-extensions-plug-ins.markdown new file mode 100644 index 000000000..de0d41668 --- /dev/null +++ b/content/pages/examples/flask/flask-extensions-plug-ins.markdown @@ -0,0 +1,230 @@ +title: Flask Extensions, Plug-ins and Related Libraries +category: page +slug: flask-extensions-plug-ins-related-libraries +sortorder: 500020000 +toc: False +sidebartitle: Flask Extensions +meta: Python code extensions and plug-in projects that show how to use the Flask web app framework. + + +[Flask](/flask.html) is a Python [web framework](/web-frameworks.html). + +Official Flask logo. Flask Artwork License. + +Flask has a wide range of code libraries and extensions that make the +[web framework](/web-frameworks.html) go from a *micro*framework into +a full-featured web application creation tool. + +Flask's large ecosystem of extensions make it easier for developers to +build common web app features such as authentication, +[database](/databases.html) operations and +[APIs](/application-programming-interfaces.html) even though support +is not built into the core Flask [web framework](/web-frameworks.html). +This design is by choice in contrast to [Django](/django.html)'s +"batteries-included" approach. Either framework's design decision +is a viable approach depending on the needs and requirements of the +application you are building. + +The following projects, ordered alphabetically, can be helpful both +as extensions added to your code base as well as example code for +building your own applications. + + +### Flask App Builder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + + +### Flask-Ask +[Flask-Ask](https://github.com/johnwheeler/flask-ask) is an extension +for building Amazon Alexa skills using a familiar [Flask](/flask.html) +functions style of organization. There is a +[starter tutorial](https://developer.amazon.com/blogs/post/Tx14R0IYYGH3SKT/Flask-Ask-A-New-Python-Framework-for-Rapid-Alexa-Skills-Kit-Development) +that shows how to use the framework and the code +is provided as open source under the +[Apache 2.0 license](https://github.com/johnwheeler/flask-ask/blob/master/LICENSE.txt). + + +### Flask-Authorize +[Flask-Authorize](https://github.com/bprinty/Flask-Authorize) +([documentation](https://flask-authorize.readthedocs.io/en/latest/) +and +[PyPI package](https://pypi.org/project/Flask-Authorize/)) +is a [Flask](/flask.html) extension to make it easier to implement +Access Control Lists (ACLs) and Role-Based Access Control (RBAC) into +web applications. The project is open sourced under the +[MIT license](https://github.com/bprinty/Flask-Authorize/blob/master/LICENSE). + + +### flask-base +[flask-base](https://github.com/hack4impact/flask-base) +([project documentation](http://hack4impact.github.io/flask-base/)) +is a boilerplate starter application that is pre-configured with +[SQLAlchemy](/sqlalchemy.html), [Redis](/redis.html), user +authentication and other features. + +flask-base's code is open sourced +[under the MIT license](https://github.com/hack4impact/flask-base/blob/master/LICENSE.md). + + +### flask-bootstrap +[flask-bootstrap](https://github.com/mbr/flask-bootstrap) +([PyPI package information](https://pypi.org/project/Flask-Bootstrap/)) +makes it easier to use the [Bootstrap CSS framework](/bootstrap-css.html) +in your [Flask](/flask.html) applications with less boilerplate +code. The project was primarily created by +[Marc Brinkmann @mbr](https://github.com/mbr) and the source code is +open sourced under the +[Apache 2.0 license](https://github.com/mbr/flask-bootstrap/blob/master/LICENSE). + + +### Flask Debug-toolbar +[Flask Debug-toolbar](https://github.com/flask-debugtoolbar/flask-debugtoolbar) +([documentation](https://flask-debugtoolbar.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/Flask-DebugToolbar/)) +is a [Flask](/flask.html) conversion of the popular +[Django Debug Toolbar](https://github.com/jazzband/django-debug-toolbar) +project. This extension creates a sidebar with useful debugging +information when you are running a Flask application in development +mode. The project is provided as open source under +[this license](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/LICENSE). + + +### Flask-HTTPAuth +[Flask-HTTPAuth](https://github.com/miguelgrinberg/Flask-HTTPAuth) +([documentation](https://flask-httpauth.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/Flask-HTTPAuth/)) +is a [Flask](/flask.html) framework extension that creates +Basic and Digest HTTP authentication for routes. This project +is primarily built and maintained by +[Miguel Grinberg](https://blog.miguelgrinberg.com/). It is provided +as open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/LICENSE). + + +### Flask-Login +[Flask-Login](https://github.com/maxcountryman/flask-login) +([project documentation](https://flask-login.readthedocs.io/en/latest/) +and [PyPI package](https://pypi.org/project/Flask-Login/)) +is a [Flask](/flask.html) extension that provides user session +management, which handles common tasks such as logging in +and out of a [web application](/web-development.html) and +managing associated user session data. Flask-Login is +open sourced under the +[MIT license](https://github.com/maxcountryman/flask-login/blob/master/LICENSE). + + +### Flask-Meld +[Flask-Meld](https://github.com/mikeabrahamsen/Flask-Meld) +([PyPI package information](https://pypi.org/project/Flask-Meld/)) +allows you to write your front end web code in your back end +Python code. It does this by adding a `{% meld_scripts %}` tag to +the Flask template engine and then inserting components written +in Python scripts created by a developer. + + +### flask-praetorian +[flask-praetorian](https://github.com/dusktreader/flask-praetorian) +([project documentation](https://flask-praetorian.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/flask-praetorian/)) +extends the [Flask](/flask.html) framework security model with JWT tokens, +which is particularly useful when using a front end +[JavaScript](/javascript.html) framework such as [React](/react.html) +or [Angular](/angular.html). [PyJWT](https://pyjwt.readthedocs.io/en/latest/) +is used under the hood to ensure a solid JWT implementation. +This extension makes it much easier to add functionality that checks +user roles on URLs before allowing access to a resource. flask-praetorian +is open sourced under the +[MIT license](https://github.com/dusktreader/flask-praetorian/blob/master/LICENSE.rst). + + +### Flask RESTX +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + + +### Flask-Security-Too +[Flask-Security-Too](https://github.com/Flask-Middleware/flask-security/) +([PyPi page](https://pypi.org/project/Flask-Security-Too/) and +[project documentation](https://flask-security-too.readthedocs.io/en/stable/)) +is a maintained fork of the original +[Flask-Security](https://github.com/mattupstate/flask-security) project that +makes it easier to add common security features to [Flask](/flask.html) +web applications. A few of the critical goals of the Flask-Security-Too +project are ensuring JavaScript client-based single-page applications (SPAs) +can work securely with Flask-based backends and that guidance by the +[OWASP](https://owasp.org/) organization is followed by default. + +The Flask-Security-Too project is provided as open source under the +[MIT license](https://github.com/Flask-Middleware/flask-security/blob/master/LICENSE). + + +### Flask-SocketIO +[Flask-SocketIO](https://github.com/miguelgrinberg/Flask-SocketIO) +([PyPI package information](https://pypi.org/project/Flask-SocketIO/), +[official tutorial](https://blog.miguelgrinberg.com/post/easy-websockets-with-flask-and-gevent) +and +[project documentation](https://flask-socketio.readthedocs.io/en/latest/)) +is a code library by [Miguel Grinberg](https://blog.miguelgrinberg.com/index) +that provides Socket.IO integration for [Flask](/flask.html) applications. +This extension makes it easier to add bi-directional communications on the +web via the [WebSockets](/websockets.html) protocol. + +The Flask-SocketIO project is open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/LICENSE). + + +### Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + + +### Flask-VueJs-Template +[Flask-VueJs-Template](https://github.com/gtalarico/flask-vuejs-template) +([demo site](https://flask-vuejs-template.herokuapp.com/)) +is a minimal [Flask](/flask.html) boilerplate starter project that +combines Flask, [Vue.js](https://www.fullstackpython.com/vuejs.html), +and [Flask-RESTPlus](https://flask-restplus.readthedocs.io/en/stable/). +The project provides some sensible defaults that are easy to continue +building on, and the source code is open source under the +[MIT license](https://github.com/gtalarico/flask-vuejs-template/blob/master/LICENSE.md). + + +### Flask-WTF +[Flask-WTF](https://github.com/lepture/flask-wtf) +([project documentation](https://flask-wtf.readthedocs.io/) +and +[PyPI page](https://pypi.org/project/Flask-WTF/)) +provides a bridge between [Flask](/flask.html) and the the +[WTForms](https://wtforms.readthedocs.io/en/2.3.x/) form-handling library. +It makes it easier to use WTForms by reducing boilerplate code and +shorter examples for common form operations as well as common security +practices such as [CSRF](/cross-site-request-forgery-csrf.html). + diff --git a/content/pages/examples/flask/flask-globals-current-app.markdown b/content/pages/examples/flask/flask-globals-current-app.markdown new file mode 100644 index 000000000..450633b87 --- /dev/null +++ b/content/pages/examples/flask/flask-globals-current-app.markdown @@ -0,0 +1,2773 @@ +title: flask.globals current_app Example Code +category: page +slug: flask-globals-current-app-examples +sortorder: 500021014 +toc: False +sidebartitle: flask.globals current_app +meta: Python example code that shows how to use the current_app callable from the flask.globals module of the Flask project. + + +[current_app](https://github.com/pallets/flask/blob/master/src/flask/globals.py) +is function in [Flask](/flask.html)'s `flask.globals` module and is an +instance of +[LocalProxy](https://github.com/pallets/werkzeug/blob/master/src/werkzeug/local.py) +from the Werkzeug framework. `current_app` can be used to access data about the +running application, including the configuration. This is useful for both +developers using the framework and ones building extensions for Flask. + +You will often see `current_app` imported directly from `flask` instead +of `flask.globals`. These imports are equivalent because `flask` is simply +importing `current_app` from `flask.globals`. + +g, +request, +and session +are several other callables with code examples from the same `flask.globals` package. + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / migrations / env.py**](https://github.com/CTFd/CTFd/blob/master/./migrations/env.py) + +```python +# env.py +from __future__ import with_statement + +import logging +from logging.config import fileConfig + +from sqlalchemy import engine_from_config +from sqlalchemy import pool + +from alembic import context + +config = context.config + +fileConfig(config.config_file_name, disable_existing_loggers=False) +logger = logging.getLogger("alembic.env") + +~~from flask import current_app + +config.set_main_option( + "sqlalchemy.url", + str(current_app.extensions["migrate"].db.engine.url).replace("%", "%%"), +) +~~target_metadata = current_app.extensions["migrate"].db.metadata + + + +def run_migrations_offline(): + url = config.get_main_option("sqlalchemy.url") + context.configure(url=url, target_metadata=target_metadata, literal_binds=True) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + + def process_revision_directives(context, revision, directives): + if getattr(config.cmd_opts, "autogenerate", False): + script = directives[0] + if script.upgrade_ops.is_empty(): + directives[:] = [] + logger.info("No changes in schema detected.") + + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix="sqlalchemy.", + poolclass=pool.NullPool, + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 2 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / validators.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/./validators.py) + +```python +# validators.py +import re +from typing import Optional + +~~from flask import current_app +from flask_appbuilder.exceptions import PasswordComplexityValidationError +from flask_appbuilder.models.base import BaseInterface +from flask_babel import gettext +from wtforms import Field, Form, ValidationError + +password_complexity_regex = re.compile( + r"""( + ^(?=.*[A-Z].*[A-Z]) # at least two capital letters + (?=.*[^0-9a-zA-Z]) # at least one of these special characters + (?=.*[0-9].*[0-9]) # at least two numeric digits + (?=.*[a-z].*[a-z].*[a-z]) # at least three lower case letters + .{10,} # at least 10 total characters + $ + )""", + re.VERBOSE, +) + + +class Unique: + + field_flags = ("unique",) + + def __init__( + self, datamodel: BaseInterface, col_name: str, message: Optional[str] = None + ) -> None: + self.datamodel = datamodel + self.col_name = col_name + self.message = message + + def __call__(self, form: Form, field: Field) -> None: + filters = self.datamodel.get_filters().add_filter( + self.col_name, self.datamodel.FilterEqual, field.data + ) + count, obj = self.datamodel.query(filters) + if count > 0: + if not hasattr(form, "_id") or form._id != self.datamodel.get_keys(obj)[0]: + if self.message is None: + self.message = field.gettext(u"Already exists.") + raise ValidationError(self.message) + + +class PasswordComplexityValidator: + + def __call__(self, form: Form, field: Field) -> None: +~~ if current_app.config.get("FAB_PASSWORD_COMPLEXITY_ENABLED", False): +~~ password_complexity_validator = current_app.config.get( + "FAB_PASSWORD_COMPLEXITY_VALIDATOR", None + ) + if password_complexity_validator is not None: + try: + password_complexity_validator(field.data) + except PasswordComplexityValidationError as exc: + raise ValidationError(str(exc)) + else: + try: + default_password_complexity(field.data) + except PasswordComplexityValidationError as exc: + raise ValidationError(str(exc)) + + +def default_password_complexity(password: str) -> None: + match = re.search(password_complexity_regex, password) + if not match: + raise PasswordComplexityValidationError( + gettext( + "Must have at least two capital letters," + " one special character, two digits, three lower case letters and" + " a minimal length of 10." + ) + ) + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 3 from Flask-Authorize +[Flask-Authorize](https://github.com/bprinty/Flask-Authorize) +([documentation](https://flask-authorize.readthedocs.io/en/latest/) +and +[PyPI package](https://pypi.org/project/Flask-Authorize/)) +is a [Flask](/flask.html) extension to make it easier to implement +Access Control Lists (ACLs) and Role-Based Access Control (RBAC) into +web applications. The project is open sourced under the +[MIT license](https://github.com/bprinty/Flask-Authorize/blob/master/LICENSE). + +[**Flask-Authorize / flask_authorize / mixins.py**](https://github.com/bprinty/Flask-Authorize/blob/master/flask_authorize/./mixins.py) + +```python +# mixins.py + + +import six +import re +import json +~~from flask import current_app +from werkzeug.exceptions import Unauthorized +from sqlalchemy import Column, ForeignKey +from sqlalchemy.types import Integer, Text +from sqlalchemy.orm import relationship +from sqlalchemy.sql import operators +from sqlalchemy.ext.declarative import declared_attr +from sqlalchemy import TypeDecorator, inspect, and_, or_ + + +class JSON(TypeDecorator): + impl = Text + + @property + def python_type(self): + return object + + def process_bind_param(self, value, dialect): + return json.dumps(value) + + def process_result_value(self, value, dialect): + try: + return json.loads(value) + except (ValueError, TypeError): + return None + + +## ... source file abbreviated to get to current_app examples ... + + + operators.contains_op): + return Text() + else: + return self + + def process_bind_param(self, value, dialect): + if not value: + return None + return '|'.join(value) + + def process_result_value(self, value, dialect): + try: + if not value: + return [] + return value.split('|') + except (ValueError, TypeError): + return None + + +MODELS = dict() + + +def gather_models(): + global MODELS + +~~ from flask import current_app +~~ if 'sqlalchemy' not in current_app.extensions: + return +~~ check = current_app.config['AUTHORIZE_IGNORE_PROPERTY'] + +~~ db = current_app.extensions['sqlalchemy'].db + for cls in db.Model._decl_class_registry.values(): + if isinstance(cls, type) and issubclass(cls, db.Model): + if hasattr(cls, check) and not getattr(cls, check): + continue + MODELS[table_key(cls)] = cls + return + + +def table_key(cls): +~~ if current_app.config['AUTHORIZE_MODEL_PARSER'] == 'class': + return cls.__name__ + +~~ elif current_app.config['AUTHORIZE_MODEL_PARSER'] == 'lower': + return cls.__name__.lower() + +~~ elif current_app.config['AUTHORIZE_MODEL_PARSER'] == 'snake': + words = re.findall(r'([A-Z][0-9a-z]+)', cls.__name__) + if len(words) > 1: + return '_'.join(map(lambda x: x.lower(), words)) + +~~ elif current_app.config['AUTHORIZE_MODEL_PARSER'] == 'table': + mapper = inspect(cls) + return mapper.tables[0].name + + +def default_permissions_factory(name): + def _(cls=None): + perms = default_permissions(cls) + return perms.get(name, []) + return _ + + +def default_permissions(cls=None): + if cls is None or cls.__permissions__ is None: +~~ return current_app.config['AUTHORIZE_DEFAULT_PERMISSIONS'] + elif isinstance(cls.__permissions__, int): + return parse_permission_set(cls.__permissions__) + elif isinstance(cls.__permissions__, dict): + return cls.__permissions__ + + +def default_allowances(cls=None): + global MODELS + if not MODELS: + gather_models() + + default = { +~~ key: current_app.config['AUTHORIZE_DEFAULT_ALLOWANCES'] + for key in MODELS + } + + if cls is None: + return default + + if isinstance(cls.__allowances__, dict): + return cls.__allowances__ + + return default + + +def default_restrictions(cls=None): + global MODELS + if not MODELS: + gather_models() + + default = { +~~ key: current_app.config['AUTHORIZE_DEFAULT_RESTRICTIONS'] + for key in MODELS + } + + if cls is None: + return default + + if cls.__restrictions__ == '*' or cls.__restrictions__ is True: + return { +~~ key: current_app.config['AUTHORIZE_DEFAULT_ACTIONS'] + for key in MODELS + } + + if isinstance(cls.__restrictions__, dict): + default.update(cls.__restrictions__) + return default + + +def permission_list(number): + if isinstance(number, six.string_types) and len(number) == 1: + number = int(number) + if not isinstance(number, int): + return number + + ret = [] + for mask, name in zip([1, 2, 4], ['delete', 'read', 'update']): + if number & mask: + ret.append(name) + return ret + + +def parse_permission_set(number): + if isinstance(number, six.string_types) and len(number) == 3: + number = int(number) + + +## ... source file abbreviated to get to current_app examples ... + + + cls.group_id.in_([x.id for x in current_user.groups]), + cls.group_permissions.contains(check) + )) + return or_(*clauses) + + @property + def permissions(self): + result = {} + for name in ['owner', 'group', 'other']: + prop = name + '_permissions' + if hasattr(self, prop): + result[name] = getattr(self, prop) + return result + + @permissions.setter + def permissions(self, value): + for name in ['owner', 'group', 'other']: + if name not in value: + continue + prop = name + '_permissions' + if hasattr(self, prop): + setattr(self, prop, value[name]) + return + + def set_permissions(self, *args, **kwargs): +~~ if 'authorize' in current_app.extensions: +~~ authorize = current_app.extensions['authorize'] + if not authorize.update(self): + raise Unauthorized + + if len(args): + perms = parse_permission_set(args[0]) + kwargs.update(perms) + + permissions = self.permissions.copy() + permissions.update(kwargs) + self.permissions = permissions + return self + + +class OwnerMixin(object): + __user_model__ = 'User' + + @classmethod + def get_user_default(cls): + from .plugin import CURRENT_USER + return CURRENT_USER().id + + @classmethod + def get_user_tablename(cls): + if isinstance(cls.__user_model__, str): + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 4 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / auth / views.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/auth/views.py) + +```python +# views.py +import logging +from datetime import datetime + +~~from flask import Blueprint, current_app, flash, g, redirect, request, url_for +from flask.views import MethodView +from flask_babelplus import gettext as _ +from flask_login import ( + confirm_login, + current_user, + login_fresh, + login_required, + login_user, + logout_user, +) + +from flaskbb.auth.forms import ( + AccountActivationForm, + ForgotPasswordForm, + LoginForm, + LoginRecaptchaForm, + ReauthForm, + RegisterForm, + RequestActivationForm, + ResetPasswordForm, +) +from flaskbb.extensions import db, limiter +from flaskbb.utils.helpers import ( + anonymous_required, + + +## ... source file abbreviated to get to current_app examples ... + + + + reauth_manager = self.reauthentication_factory() + try: + reauth_manager.reauthenticate( + user=current_user, secret=form.password.data + ) + confirm_login() + flash(_("Reauthenticated."), "success") + return redirect_or_next(current_user.url) + except StopAuthentication as e: + flash(e.reason, "danger") + except Exception: + flash(_("Unrecoverable error while handling reauthentication")) + raise + + return render_template("auth/reauth.html", form=form) + + +class Register(MethodView): + decorators = [anonymous_required, registration_enabled] + + def __init__(self, registration_service_factory): + self.registration_service_factory = registration_service_factory + + def form(self): +~~ current_app.pluggy.hook.flaskbb_form_registration(form=RegisterForm) + form = RegisterForm() + + form.language.choices = get_available_languages() + form.language.default = flaskbb_config['DEFAULT_LANGUAGE'] + form.process(request.form) # needed because a default is overriden + return form + + def get(self): + return render_template("auth/register.html", form=self.form()) + + def post(self): + form = self.form() + if form.validate_on_submit(): + registration_info = UserRegistrationInfo( + username=form.username.data, + password=form.password.data, + group=4, + email=form.email.data, + language=form.language.data + ) + + service = self.registration_service_factory() + try: + service.register(registration_info) + except StopValidation as e: + form.populate_errors(e.reasons) + return render_template("auth/register.html", form=form) + except PersistenceError: + logger.exception("Database error while persisting user") + flash( + _( + "Could not process registration due" + "to an unrecoverable error" + ), "danger" + ) + + return render_template("auth/register.html", form=form) + +~~ current_app.pluggy.hook.flaskbb_event_user_registered( + username=registration_info.username + ) + return redirect_or_next(url_for('forum.index')) + + return render_template("auth/register.html", form=form) + + +class ForgotPassword(MethodView): + decorators = [anonymous_required] + form = ForgotPasswordForm + + def __init__(self, password_reset_service_factory): + self.password_reset_service_factory = password_reset_service_factory + + def get(self): + return render_template("auth/forgot_password.html", form=self.form()) + + def post(self): + form = self.form() + if form.validate_on_submit(): + + try: + service = self.password_reset_service_factory() + service.initiate_password_reset(form.email.data) + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 5 from flask-base +[flask-base](https://github.com/hack4impact/flask-base) +([project documentation](http://hack4impact.github.io/flask-base/)) +provides boilerplate code for new [Flask](/flask.html) web apps. +The purpose of the boilerplate is to stitch together disparate +libraries that are commonly used in Flask projects, such as +[Redis](/redis.html) for fast caching and transient data storage, +[SendGrid](https://www.twilio.com/sendgrid) for transactional email, +[SQLAlchemy](/sqlalchemy.html) for persistent data storage through a +[relational database](/databases.html) backend, +[Flask-WTF](https://flask-wtf.readthedocs.io/) for form +handling and many others. + +flask-base is provided as open source under the +[MIT license](https://github.com/hack4impact/flask-base/blob/master/LICENSE.md). + +[**flask-base / app / models / user.py**](https://github.com/hack4impact/flask-base/blob/master/app/models/user.py) + +```python +# user.py +~~from flask import current_app +from flask_login import AnonymousUserMixin, UserMixin +from itsdangerous import TimedJSONWebSignatureSerializer as Serializer +from itsdangerous import BadSignature, SignatureExpired +from werkzeug.security import check_password_hash, generate_password_hash + +from .. import db, login_manager + + +class Permission: + GENERAL = 0x01 + ADMINISTER = 0xff + + +class Role(db.Model): + __tablename__ = 'roles' + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(64), unique=True) + index = db.Column(db.String(64)) + default = db.Column(db.Boolean, default=False, index=True) + permissions = db.Column(db.Integer) + users = db.relationship('User', backref='role', lazy='dynamic') + + @staticmethod + def insert_roles(): + + +## ... source file abbreviated to get to current_app examples ... + + + if role is None: + role = Role(name=r) + role.permissions = roles[r][0] + role.index = roles[r][1] + role.default = roles[r][2] + db.session.add(role) + db.session.commit() + + def __repr__(self): + return '' % self.name + + +class User(UserMixin, db.Model): + __tablename__ = 'users' + id = db.Column(db.Integer, primary_key=True) + confirmed = db.Column(db.Boolean, default=False) + first_name = db.Column(db.String(64), index=True) + last_name = db.Column(db.String(64), index=True) + email = db.Column(db.String(64), unique=True, index=True) + password_hash = db.Column(db.String(128)) + role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) + + def __init__(self, **kwargs): + super(User, self).__init__(**kwargs) + if self.role is None: +~~ if self.email == current_app.config['ADMIN_EMAIL']: + self.role = Role.query.filter_by( + permissions=Permission.ADMINISTER).first() + if self.role is None: + self.role = Role.query.filter_by(default=True).first() + + def full_name(self): + return '%s %s' % (self.first_name, self.last_name) + + def can(self, permissions): + return self.role is not None and \ + (self.role.permissions & permissions) == permissions + + def is_admin(self): + return self.can(Permission.ADMINISTER) + + @property + def password(self): + raise AttributeError('`password` is not a readable attribute') + + @password.setter + def password(self, password): + self.password_hash = generate_password_hash(password) + + def verify_password(self, password): + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 6 from flask-bookshelf +[flask-bookshelf](https://github.com/damyanbogoev/flask-bookshelf) is the +example [Flask](/flask.html) application that developers create when +going through +[this Flask series of blog posts](https://damyanon.net/tags/flask-series/). + +[**flask-bookshelf / bookshelf / __init__.py**](https://github.com/damyanbogoev/flask-bookshelf/blob/master/bookshelf/./__init__.py) + +```python +# __init__.py +~~from flask import abort, Flask, g, render_template, request, current_app +from flask_babel import Babel +from flask_security import current_user +from bookshelf.utils import get_instance_folder_path +from bookshelf.main.controllers import main +from bookshelf.admin.controllers import admin +from bookshelf.cache import cache +from bookshelf.config import configure_app +from bookshelf.data.models import db + +app = Flask( + __name__, + instance_path=get_instance_folder_path(), + instance_relative_config=True, + template_folder="templates", +) + +babel = Babel(app) +configure_app(app) +cache.init_app(app) +db.init_app(app) +app.jinja_env.add_extension("jinja2.ext.loopcontrols") + + +@app.url_defaults + + +## ... source file abbreviated to get to current_app examples ... + + + g.lang_code = values.pop("lang_code", None) + + +@app.before_request +def ensure_lang_support(): + lang_code = g.get("lang_code", None) + if lang_code and lang_code not in app.config["SUPPORTED_LANGUAGES"].keys(): + abort(404) + + +@babel.localeselector +def get_locale(): + return g.get("lang_code", app.config["BABEL_DEFAULT_LOCALE"]) + + +@babel.timezoneselector +def get_timezone(): + user = g.get("user", None) + if user is not None: + return user.timezone + return "UTC" + + +@app.errorhandler(404) +def page_not_found(error): +~~ current_app.logger.error("Page not found: %s", (request.path, error)) + return render_template("404.htm"), 404 + + +@app.errorhandler(500) +def internal_server_error(error): +~~ current_app.logger.error("Server Error: %s", (error)) + return render_template("500.htm"), 500 + + +@app.errorhandler(Exception) +def unhandled_exception(error): +~~ current_app.logger.error("Unhandled Exception: %s", (error)) + return render_template("500.htm"), 500 + + +@app.context_processor +def inject_data(): + return dict(user=current_user, lang_code=g.get("lang_code", None)) + + +@app.route("/") +@app.route("//") +@cache.cached(300) +def home(lang_code=None): + return render_template("index.htm") + + +app.register_blueprint(main, url_prefix="/main") +app.register_blueprint(main, url_prefix="//main") +app.register_blueprint(admin, url_prefix="/admin") +app.register_blueprint(admin, url_prefix="//admin") + + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 7 from Flask-Bootstrap +[flask-bootstrap](https://github.com/mbr/flask-bootstrap) +([PyPI package information](https://pypi.org/project/Flask-Bootstrap/)) +makes it easier to use the [Bootstrap CSS framework](/bootstrap-css.html) +in your [Flask](/flask.html) applications with less boilerplate +code. The project was primarily created by +[Marc Brinkmann @mbr](https://github.com/mbr) and the source code is +open sourced under the +[Apache 2.0 license](https://github.com/mbr/flask-bootstrap/blob/master/LICENSE). + +[**Flask-Bootstrap / flask_bootstrap / __init__.py**](https://github.com/mbr/flask-bootstrap/blob/master/flask_bootstrap/./__init__.py) + +```python +# __init__.py + +import re + +~~from flask import Blueprint, current_app, url_for + +try: + from wtforms.fields import HiddenField +except ImportError: + + def is_hidden_field_filter(field): + raise RuntimeError('WTForms is not installed.') +else: + + def is_hidden_field_filter(field): + return isinstance(field, HiddenField) + + +from .forms import render_form + +__version__ = '3.3.7.1.dev1' +BOOTSTRAP_VERSION = re.sub(r'^(\d+\.\d+\.\d+).*', r'\1', __version__) +JQUERY_VERSION = '1.12.4' +HTML5SHIV_VERSION = '3.7.3' +RESPONDJS_VERSION = '1.4.2' + + +class CDN(object): + + def get_resource_url(self, filename): + raise NotImplementedError + + +class StaticCDN(object): + + def __init__(self, static_endpoint='static', rev=False): + self.static_endpoint = static_endpoint + self.rev = rev + + def get_resource_url(self, filename): + extra_args = {} + +~~ if self.rev and current_app.config['BOOTSTRAP_QUERYSTRING_REVVING']: + extra_args['bootstrap'] = __version__ + + return url_for(self.static_endpoint, filename=filename, **extra_args) + + +class WebCDN(object): + + def __init__(self, baseurl): + self.baseurl = baseurl + + def get_resource_url(self, filename): + return self.baseurl + filename + + +class ConditionalCDN(object): + + def __init__(self, confvar, primary, fallback): + self.confvar = confvar + self.primary = primary + self.fallback = fallback + + def get_resource_url(self, filename): +~~ if current_app.config[self.confvar]: + return self.primary.get_resource_url(filename) + return self.fallback.get_resource_url(filename) + + +def bootstrap_find_resource(filename, cdn, use_minified=None, local=True): +~~ config = current_app.config + + if None == use_minified: + use_minified = config['BOOTSTRAP_USE_MINIFIED'] + + if use_minified: + filename = '%s.min.%s' % tuple(filename.rsplit('.', 1)) + +~~ cdns = current_app.extensions['bootstrap']['cdns'] + resource_url = cdns[cdn].get_resource_url(filename) + + if resource_url.startswith('//') and config['BOOTSTRAP_CDN_FORCE_SSL']: + resource_url = 'https:%s' % resource_url + + return resource_url + + +class Bootstrap(object): + def __init__(self, app=None): + if app is not None: + self.init_app(app) + + def init_app(self, app): + app.config.setdefault('BOOTSTRAP_USE_MINIFIED', True) + app.config.setdefault('BOOTSTRAP_CDN_FORCE_SSL', False) + + app.config.setdefault('BOOTSTRAP_QUERYSTRING_REVVING', True) + app.config.setdefault('BOOTSTRAP_SERVE_LOCAL', False) + + app.config.setdefault('BOOTSTRAP_LOCAL_SUBDOMAIN', None) + + blueprint = Blueprint( + 'bootstrap', + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 8 from flask-debugtoolbar +[Flask Debug-toolbar](https://github.com/flask-debugtoolbar/flask-debugtoolbar) +([documentation](https://flask-debugtoolbar.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/Flask-DebugToolbar/)) +is a [Flask](/flask.html) conversion of the popular +[Django Debug Toolbar](https://github.com/jazzband/django-debug-toolbar) +project. This extension creates a sidebar with useful debugging +information when you are running a Flask application in development +mode. The project is provided as open source under +[this license](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/LICENSE). + +[**flask-debugtoolbar / flask_debugtoolbar / __init__.py**](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/flask_debugtoolbar/./__init__.py) + +```python +# __init__.py +import os +import warnings + +~~from flask import Blueprint, current_app, request, g, send_from_directory, url_for +from flask.globals import _request_ctx_stack +from jinja2 import Environment, PackageLoader +from werkzeug.urls import url_quote_plus + +from flask_debugtoolbar.compat import iteritems +from flask_debugtoolbar.toolbar import DebugToolbar +from flask_debugtoolbar.utils import decode_text, gzip_compress, gzip_decompress + +try: + from importlib.metadata import version + + __version__ = version("Flask-DebugToolbar") +except ImportError: + import pkg_resources + + __version__ = pkg_resources.get_distribution("Flask-DebugToolbar").version + + +module = Blueprint('debugtoolbar', __name__) + + +def replace_insensitive(string, target, replacement): + no_case = string.lower() + index = no_case.rfind(target.lower()) + + +## ... source file abbreviated to get to current_app examples ... + + + ), + } + + def dispatch_request(self): + req = _request_ctx_stack.top.request + app = current_app + + if req.routing_exception is not None: + app.raise_routing_exception(req) + + rule = req.url_rule + + if getattr(rule, 'provide_automatic_options', False) \ + and req.method == 'OPTIONS': + return app.make_default_options_response() + + view_func = app.view_functions[rule.endpoint] + view_func = self.process_view(app, view_func, req.view_args) + + return view_func(**req.view_args) + + def _show_toolbar(self): + if request.blueprint == 'debugtoolbar': + return False + +~~ hosts = current_app.config['DEBUG_TB_HOSTS'] + if hosts and request.remote_addr not in hosts: + return False + + return True + + def send_static_file(self, filename): + return send_from_directory(self._static_dir, filename) + + def process_request(self): + g.debug_toolbar = self + + if not self._show_toolbar(): + return + + real_request = request._get_current_object() + + self.debug_toolbars[real_request] = ( + DebugToolbar(real_request, self.jinja_env)) + + for panel in self.debug_toolbars[real_request].panels: + panel.process_request(real_request) + + def process_view(self, app, view_func, view_kwargs): + real_request = request._get_current_object() + try: + toolbar = self.debug_toolbars[real_request] + except KeyError: + return view_func + + for panel in toolbar.panels: + new_view = panel.process_view(real_request, view_func, view_kwargs) + if new_view: + view_func = new_view + + return view_func + + def process_response(self, response): + real_request = request._get_current_object() + if real_request not in self.debug_toolbars: + return response + +~~ if current_app.config['DEBUG_TB_INTERCEPT_REDIRECTS']: + if response.status_code in self._redirect_codes: + redirect_to = response.location + redirect_code = response.status_code + if redirect_to: + content = self.render('redirect.html', { + 'redirect_to': redirect_to, + 'redirect_code': redirect_code + }) + response.content_length = len(content) + response.location = None + response.response = [content] + response.status_code = 200 + + if not (response.status_code == 200 and + response.is_sequence and + response.headers['content-type'].startswith('text/html')): + return response + + if 'gzip' in response.headers.get('Content-Encoding', ''): + response_html = gzip_decompress(response.data).decode(response.charset) + else: + response_html = response.data.decode(response.charset) + + no_case = response_html.lower() + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 9 from flask_jsondash +[Flask JSONDash](https://github.com/christabor/flask_jsondash) is a +configurable web application built in Flask that creates charts and +dashboards from arbitrary API endpoints. Everything for the web app +is configured in JSON. The code is provided as open source under the +[MIT license](https://github.com/christabor/flask_jsondash/blob/master/LICENSE). + +[**flask_jsondash / flask_jsondash / charts_builder.py**](https://github.com/christabor/flask_jsondash/blob/master/flask_jsondash/./charts_builder.py) + +```python +# charts_builder.py + + +import json +import os +import uuid +from datetime import datetime as dt + +import jinja2 +~~from flask import (Blueprint, current_app, flash, redirect, render_template, + request, send_from_directory, url_for) + +from flask_jsondash import static, templates + +from flask_jsondash import db +from flask_jsondash import settings +from flask_jsondash.utils import setting +from flask_jsondash.utils import adapter +from flask_jsondash import utils +from flask_jsondash.schema import ( + validate_raw_json, InvalidSchemaError, +) + +TEMPLATE_DIR = os.path.dirname(templates.__file__) +STATIC_DIR = os.path.dirname(static.__file__) + +REQUIRED_STATIC_FAMILES = ['D3'] + +charts = Blueprint( + 'jsondash', + __name__, + template_folder=TEMPLATE_DIR, + static_url_path=STATIC_DIR, + static_folder=STATIC_DIR, +) + + +def auth(**kwargs): +~~ if 'JSONDASH' not in current_app.config: + return True +~~ if 'auth' not in current_app.config['JSONDASH']: + return True + authtype = kwargs.pop('authtype') +~~ auth_conf = current_app.config.get('JSONDASH').get('auth') + if authtype not in auth_conf: + return True + return auth_conf[authtype](**kwargs) + + +def metadata(key=None, exclude=[]): + _metadata = dict() +~~ conf = current_app.config + conf_metadata = conf.get('JSONDASH', {}).get('metadata') + if key is not None: + if key in conf_metadata: + return conf_metadata[key]() + else: + return None + for k, func in conf_metadata.items(): + if k in exclude: + continue + _metadata[k] = conf_metadata[k]() + return _metadata + + +def local_static(chart_config, static_config): + js_path = static_config.get('js_path') + css_path = static_config.get('css_path') + for family, config in chart_config.items(): + if config['js_url']: + for i, url in enumerate(config['js_url']): + url = '{}{}'.format(js_path, url.split('/')[-1]) + config['js_url'][i] = url_for('static', filename=url) + if config['css_url']: + for i, url in enumerate(config['css_url']): + url = '{}{}'.format(css_path, url.split('/')[-1]) + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 10 from flask-login +[Flask-Login](https://github.com/maxcountryman/flask-login) +([project documentation](https://flask-login.readthedocs.io/en/latest/) +and [PyPI package](https://pypi.org/project/Flask-Login/)) +is a [Flask](/flask.html) extension that provides user session +management, which handles common tasks such as logging in +and out of a [web application](/web-development.html) and +managing associated user session data. Flask-Login is +open sourced under the +[MIT license](https://github.com/maxcountryman/flask-login/blob/master/LICENSE). + +[**flask-login / flask_login / utils.py**](https://github.com/maxcountryman/flask-login/blob/master/flask_login/./utils.py) + +```python +# utils.py + + +import hmac +from hashlib import sha512 +from functools import wraps +from werkzeug.local import LocalProxy +from werkzeug.security import safe_str_cmp +from werkzeug.urls import url_decode, url_encode + +~~from flask import (_request_ctx_stack, current_app, request, session, url_for, + has_request_context) + +from ._compat import text_type, urlparse, urlunparse +from .config import COOKIE_NAME, EXEMPT_METHODS +from .signals import user_logged_in, user_logged_out, user_login_confirmed + + +current_user = LocalProxy(lambda: _get_user()) + + +def encode_cookie(payload, key=None): + return u'{0}|{1}'.format(payload, _cookie_digest(payload, key=key)) + + +def decode_cookie(cookie, key=None): + try: + payload, digest = cookie.rsplit(u'|', 1) + if hasattr(digest, 'decode'): + digest = digest.decode('ascii') # pragma: no cover + except ValueError: + return + + if safe_str_cmp(_cookie_digest(payload, key=key), digest): + return payload + + +## ... source file abbreviated to get to current_app examples ... + + + if (not l_url.scheme or l_url.scheme == c_url.scheme) and \ + (not l_url.netloc or l_url.netloc == c_url.netloc): + return urlunparse(('', '', c_url.path, c_url.params, c_url.query, '')) + return current_url + + +def expand_login_view(login_view): + if login_view.startswith(('https://', 'http://', '/')): + return login_view + else: + if request.view_args is None: + return url_for(login_view) + else: + return url_for(login_view, **request.view_args) + + +def login_url(login_view, next_url=None, next_field='next'): + base = expand_login_view(login_view) + + if next_url is None: + return base + + parsed_result = urlparse(base) + md = url_decode(parsed_result.query) + md[next_field] = make_next_param(base, next_url) +~~ netloc = current_app.config.get('FORCE_HOST_FOR_REDIRECTS') or \ + parsed_result.netloc + parsed_result = parsed_result._replace(netloc=netloc, + query=url_encode(md, sort=True)) + return urlunparse(parsed_result) + + +def login_fresh(): + return session.get('_fresh', False) + + +def login_user(user, remember=False, duration=None, force=False, fresh=True): + if not force and not user.is_active: + return False + +~~ user_id = getattr(user, current_app.login_manager.id_attribute)() + session['_user_id'] = user_id + session['_fresh'] = fresh +~~ session['_id'] = current_app.login_manager._session_identifier_generator() + + if remember: + session['_remember'] = 'set' + if duration is not None: + try: + session['_remember_seconds'] = (duration.microseconds + + (duration.seconds + + duration.days * 24 * 3600) * + 10**6) / 10.0**6 + except AttributeError: + raise Exception('duration must be a datetime.timedelta, ' + 'instead got: {0}'.format(duration)) + +~~ current_app.login_manager._update_request_context_with_user(user) + user_logged_in.send(current_app._get_current_object(), user=_get_user()) + return True + + +def logout_user(): + + user = _get_user() + + if '_user_id' in session: + session.pop('_user_id') + + if '_fresh' in session: + session.pop('_fresh') + + if '_id' in session: + session.pop('_id') + +~~ cookie_name = current_app.config.get('REMEMBER_COOKIE_NAME', COOKIE_NAME) + if cookie_name in request.cookies: + session['_remember'] = 'clear' + if '_remember_seconds' in session: + session.pop('_remember_seconds') + + user_logged_out.send(current_app._get_current_object(), user=user) + +~~ current_app.login_manager._update_request_context_with_user() + return True + + +def confirm_login(): + session['_fresh'] = True +~~ session['_id'] = current_app.login_manager._session_identifier_generator() + user_login_confirmed.send(current_app._get_current_object()) + + +def login_required(func): + @wraps(func) + def decorated_view(*args, **kwargs): + if request.method in EXEMPT_METHODS: + return func(*args, **kwargs) +~~ elif current_app.config.get('LOGIN_DISABLED'): + return func(*args, **kwargs) + elif not current_user.is_authenticated: +~~ return current_app.login_manager.unauthorized() + return func(*args, **kwargs) + return decorated_view + + +def fresh_login_required(func): + @wraps(func) + def decorated_view(*args, **kwargs): + if request.method in EXEMPT_METHODS: + return func(*args, **kwargs) +~~ elif current_app.config.get('LOGIN_DISABLED'): + return func(*args, **kwargs) + elif not current_user.is_authenticated: +~~ return current_app.login_manager.unauthorized() + elif not login_fresh(): +~~ return current_app.login_manager.needs_refresh() + return func(*args, **kwargs) + return decorated_view + + +def set_login_view(login_view, blueprint=None): + + num_login_views = len(current_app.login_manager.blueprint_login_views) + if blueprint is not None or num_login_views != 0: + + (current_app.login_manager + .blueprint_login_views[blueprint.name]) = login_view + + if (current_app.login_manager.login_view is not None and +~~ None not in current_app.login_manager.blueprint_login_views): + + (current_app.login_manager + .blueprint_login_views[None]) = (current_app.login_manager + .login_view) + +~~ current_app.login_manager.login_view = None + else: +~~ current_app.login_manager.login_view = login_view + + +def _get_user(): + if has_request_context() and not hasattr(_request_ctx_stack.top, 'user'): +~~ current_app.login_manager._load_user() + + return getattr(_request_ctx_stack.top, 'user', None) + + +def _cookie_digest(payload, key=None): + key = _secret_key(key) + + return hmac.new(key, payload.encode('utf-8'), sha512).hexdigest() + + +def _get_remote_addr(): + address = request.headers.get('X-Forwarded-For', request.remote_addr) + if address is not None: + address = address.encode('utf-8').split(b',')[0].strip() + return address + + +def _create_identifier(): + user_agent = request.headers.get('User-Agent') + if user_agent is not None: + user_agent = user_agent.encode('utf-8') + base = '{0}|{1}'.format(_get_remote_addr(), user_agent) + if str is bytes: + base = text_type(base, 'utf-8', errors='replace') # pragma: no cover + h = sha512() + h.update(base.encode('utf8')) + return h.hexdigest() + + +def _user_context_processor(): + return dict(current_user=_get_user()) + + +def _secret_key(key=None): + if key is None: +~~ key = current_app.config['SECRET_KEY'] + + if isinstance(key, text_type): # pragma: no cover + key = key.encode('latin1') # ensure bytes + + return key + + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 11 from Flask-Meld +[Flask-Meld](https://github.com/mikeabrahamsen/Flask-Meld) +([PyPI package information](https://pypi.org/project/Flask-Meld/)) +allows you to write your front end web code in your back end +Python code. It does this by adding a `{% meld_scripts %}` tag to +the Flask template engine and then inserting components written +in Python scripts created by a developer. + +[**Flask-Meld / flask_meld / message.py**](https://github.com/mikeabrahamsen/Flask-Meld/blob/main/flask_meld/./message.py) + +```python +# message.py +import ast +from werkzeug.wrappers.response import Response +import functools + +from .component import get_component_class +~~from flask import jsonify, current_app +import orjson + + +def process_message(message): + meld_id = message["id"] + component_name = message["componentName"] + action_queue = message["actionQueue"] + + data = message["data"] + Component = get_component_class(component_name) + component = Component(meld_id, **data) + return_data = None + + for action in action_queue: + payload = action.get("payload", None) + if "syncInput" in action["type"]: + if hasattr(component, payload["name"]): + setattr(component, payload["name"], payload["value"]) + if component._form: + field_name = payload.get("name") + if field_name in component._form._fields: + field = getattr(component._form, field_name) + component._set_field_data(field_name, payload["value"]) + component.updated(field) + + +## ... source file abbreviated to get to current_app examples ... + + + + if "(" in call_method_name and call_method_name.endswith(")"): + param_idx = call_method_name.index("(") + params_str = call_method_name[param_idx:] + + method_name = call_method_name.replace(params_str, "") + + params_str = params_str[1:-1] + if params_str != "": + try: + params = ast.literal_eval("[" + params_str + "]") + except (ValueError, SyntaxError): + params = list(map(str.strip, params_str.split(","))) + + return method_name, params + + +def listen(*event_names: str): + def dec(func): + func._meld_event_names = event_names + return func + return dec + + +def emit(event_name: str, **kwargs): +~~ current_app.socketio.emit("meld-event", {"event": event_name, "message": kwargs}) + + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 12 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / swagger.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./swagger.py) + +```python +# swagger.py +from __future__ import unicode_literals, absolute_import + +import itertools +import re + +from inspect import isclass, getdoc +from collections import OrderedDict + +try: + from collections.abc import Hashable +except ImportError: + from collections import Hashable +from six import string_types, itervalues, iteritems, iterkeys + +~~from flask import current_app +from werkzeug.routing import parse_rule + +from . import fields +from .model import Model, ModelBase, OrderedModel +from .reqparse import RequestParser +from .utils import merge, not_none, not_none_sorted +from ._http import HTTPStatus + +try: + from urllib.parse import quote +except ImportError: + from urllib import quote + +PATH_TYPES = { + "int": "integer", + "float": "number", + "string": "string", + "default": "string", +} + + +PY_TYPES = { + int: "integer", + float: "number", + + +## ... source file abbreviated to get to current_app examples ... + + +) + + +def ref(model): + name = model.name if isinstance(model, ModelBase) else model + return {"$ref": "#/definitions/{0}".format(quote(name, safe=""))} + + +def _v(value): + return value() if callable(value) else value + + +def extract_path(path): + return RE_URL.sub(r"{\1}", path) + + +def extract_path_params(path): + params = OrderedDict() + for converter, arguments, variable in parse_rule(path): + if not converter: + continue + param = {"name": variable, "in": "path", "required": True} + + if converter in PATH_TYPES: + param["type"] = PATH_TYPES[converter] +~~ elif converter in current_app.url_map.converters: + param["type"] = "string" + else: + raise ValueError("Unsupported type converter: %s" % converter) + params[variable] = param + return params + + +def _param_to_header(param): + param.pop("in", None) + param.pop("name", None) + return _clean_header(param) + + +def _clean_header(header): + if isinstance(header, string_types): + header = {"description": header} + typedef = header.get("type", "string") + if isinstance(typedef, Hashable) and typedef in PY_TYPES: + header["type"] = PY_TYPES[typedef] + elif ( + isinstance(typedef, (list, tuple)) + and len(typedef) == 1 + and typedef[0] in PY_TYPES + ): + + +## ... source file abbreviated to get to current_app examples ... + + + if self.api.contact and (self.api.contact_email or self.api.contact_url): + infos["contact"] = { + "name": _v(self.api.contact), + "email": _v(self.api.contact_email), + "url": _v(self.api.contact_url), + } + if self.api.license: + infos["license"] = {"name": _v(self.api.license)} + if self.api.license_url: + infos["license"]["url"] = _v(self.api.license_url) + + paths = {} + tags = self.extract_tags(self.api) + + responses = self.register_errors() + + for ns in self.api.namespaces: + for resource, urls, route_doc, kwargs in ns.resources: + for url in self.api.ns_urls(ns, urls): + path = extract_path(url) + serialized = self.serialize_resource( + ns, resource, url, route_doc=route_doc, **kwargs + ) + paths[path] = serialized + +~~ if current_app.config["RESTX_INCLUDE_ALL_MODELS"]: + for m in self.api.models: + self.register_model(m) + + for ns in self.api.namespaces: + if ns.authorizations: + if self.api.authorizations is None: + self.api.authorizations = {} + self.api.authorizations = merge( + self.api.authorizations, ns.authorizations + ) + + specs = { + "swagger": "2.0", + "basePath": basepath, + "paths": not_none_sorted(paths), + "info": infos, + "produces": list(iterkeys(self.api.representations)), + "consumes": ["application/json"], + "securityDefinitions": self.api.authorizations or None, + "security": self.security_requirements(self.api.security) or None, + "tags": tags, + "definitions": self.serialize_definitions() or None, + "responses": responses or None, + "host": self.get_host(), + } + return not_none(specs) + + def get_host(self): +~~ hostname = current_app.config.get("SERVER_NAME", None) or None + if hostname and self.api.blueprint and self.api.blueprint.subdomain: + hostname = ".".join((self.api.blueprint.subdomain, hostname)) + return hostname + + def extract_tags(self, api): + tags = [] + by_name = {} + for tag in api.tags: + if isinstance(tag, string_types): + tag = {"name": tag} + elif isinstance(tag, (list, tuple)): + tag = {"name": tag[0], "description": tag[1]} + elif isinstance(tag, dict) and "name" in tag: + pass + else: + raise ValueError("Unsupported tag format for {0}".format(tag)) + tags.append(tag) + by_name[tag["name"]] = tag + for ns in api.namespaces: + if not ns.resources: + continue + if all(is_hidden(r.resource, route_doc=r.route_doc) for r in ns.resources): + continue + if ns.name not in by_name: + + +## ... source file abbreviated to get to current_app examples ... + + + else self.api.default_id(doc["name"], method) + ) + + def parameters_for(self, doc): + params = [] + for name, param in iteritems(doc["params"]): + param["name"] = name + if "type" not in param and "schema" not in param: + param["type"] = "string" + if "in" not in param: + param["in"] = "query" + + if "type" in param and "schema" not in param: + ptype = param.get("type", None) + if isinstance(ptype, (list, tuple)): + typ = ptype[0] + param["type"] = "array" + param["items"] = {"type": PY_TYPES.get(typ, typ)} + + elif isinstance(ptype, (type, type(None))) and ptype in PY_TYPES: + param["type"] = PY_TYPES[ptype] + + params.append(param) + + mask = doc.get("__mask__") +~~ if mask and current_app.config["RESTX_MASK_SWAGGER"]: + param = { +~~ "name": current_app.config["RESTX_MASK_HEADER"], + "in": "header", + "type": "string", + "format": "mask", + "description": "An optional fields mask", + } + if isinstance(mask, string_types): + param["default"] = mask + params.append(param) + + return params + + def responses_for(self, doc, method): + responses = {} + + for d in doc, doc[method]: + if "responses" in d: + for code, response in iteritems(d["responses"]): + code = str(code) + if isinstance(response, string_types): + description = response + model = None + kwargs = {} + elif len(response) == 3: + description, model, kwargs = response + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 13 from flask-sqlalchemy +[flask-sqlalchemy](https://github.com/pallets/flask-sqlalchemy) +([project documentation](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) +and +[PyPI information](https://pypi.org/project/Flask-SQLAlchemy/)) is a +[Flask](/flask.html) extension that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) when building Flask apps. flask-sqlalchemy +provides helper functions that reduce the amount of common boilerplate +code that you have to frequently write yourself if you did not use this +library when combining Flask with SQLAlchemy. + +flask-sqlalchemy is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/pallets/flask-sqlalchemy/blob/master/LICENSE.rst). + +[**flask-sqlalchemy / src/flask_sqlalchemy / __init__.py**](https://github.com/pallets/flask-sqlalchemy/blob/master/src/flask_sqlalchemy/./__init__.py) + +```python +# __init__.py +import functools +import os +import sys +import warnings +from math import ceil +from operator import itemgetter +from threading import Lock +from time import perf_counter + +import sqlalchemy +from flask import _app_ctx_stack +from flask import abort +~~from flask import current_app +from flask import request +from flask.signals import Namespace +from sqlalchemy import event +from sqlalchemy import inspect +from sqlalchemy import orm +from sqlalchemy.engine.url import make_url +from sqlalchemy.orm.exc import UnmappedClassError +from sqlalchemy.orm.session import Session as SessionBase + +from .model import DefaultMeta +from .model import Model + +try: + from sqlalchemy.orm import declarative_base + from sqlalchemy.orm import DeclarativeMeta +except ImportError: + from sqlalchemy.ext.declarative import declarative_base + from sqlalchemy.ext.declarative import DeclarativeMeta + +try: + from greenlet import getcurrent as _ident_func +except ImportError: + from threading import get_ident as _ident_func + + + +## ... source file abbreviated to get to current_app examples ... + + + return _EngineConnector(self, self.get_app(app), bind) + + def get_engine(self, app=None, bind=None): + + app = self.get_app(app) + state = get_state(app) + + with self._engine_lock: + connector = state.connectors.get(bind) + + if connector is None: + connector = self.make_connector(app, bind) + state.connectors[bind] = connector + + return connector.get_engine() + + def create_engine(self, sa_url, engine_opts): + return sqlalchemy.create_engine(sa_url, **engine_opts) + + def get_app(self, reference_app=None): + + if reference_app is not None: + return reference_app + + if current_app: +~~ return current_app._get_current_object() + + if self.app is not None: + return self.app + + raise RuntimeError( + "No application found. Either work inside a view function or push" + " an application context. See" + " https://flask-sqlalchemy.palletsprojects.com/contexts/." + ) + + def get_tables_for_bind(self, bind=None): + result = [] + for table in self.Model.metadata.tables.values(): + if table.info.get("bind_key") == bind: + result.append(table) + return result + + def get_binds(self, app=None): + app = self.get_app(app) + binds = [None] + list(app.config.get("SQLALCHEMY_BINDS") or ()) + retval = {} + for bind in binds: + engine = self.get_engine(app, bind) + tables = self.get_tables_for_bind(bind) + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 14 from Flask-WTF +[Flask-WTF](https://github.com/lepture/flask-wtf) +([project documentation](https://flask-wtf.readthedocs.io/) +and +[PyPI page](https://pypi.org/project/Flask-WTF/)) +provides a bridge between [Flask](/flask.html) and the the +[WTForms](https://wtforms.readthedocs.io/en/2.3.x/) form-handling library. +It makes it easier to use WTForms by reducing boilerplate code and +shorter examples for common form operations as well as common security +practices such as [CSRF](/cross-site-request-forgery-csrf.html). + +[**Flask-WTF / flask_wtf / csrf.py**](https://github.com/lepture/flask-wtf/blob/master/flask_wtf/./csrf.py) + +```python +# csrf.py +import hashlib +import logging +import os +import warnings +from urllib.parse import urlparse +from functools import wraps + +~~from flask import Blueprint, current_app, g, request, session +from itsdangerous import BadData, SignatureExpired, URLSafeTimedSerializer +from werkzeug.exceptions import BadRequest +from werkzeug.security import safe_str_cmp +from wtforms import ValidationError +from wtforms.csrf.core import CSRF + +from ._compat import FlaskWTFDeprecationWarning + +__all__ = ('generate_csrf', 'validate_csrf', 'CSRFProtect') +logger = logging.getLogger(__name__) + + +def generate_csrf(secret_key=None, token_key=None): + +~~ secret_key = _get_config( +~~ secret_key, 'WTF_CSRF_SECRET_KEY', current_app.secret_key, + message='A secret key is required to use CSRF.' + ) + field_name = _get_config( + token_key, 'WTF_CSRF_FIELD_NAME', 'csrf_token', + message='A field name is required to use CSRF.' + ) + + if field_name not in g: + s = URLSafeTimedSerializer(secret_key, salt='wtf-csrf-token') + + if field_name not in session: + session[field_name] = hashlib.sha1(os.urandom(64)).hexdigest() + + try: + token = s.dumps(session[field_name]) + except TypeError: + session[field_name] = hashlib.sha1(os.urandom(64)).hexdigest() + token = s.dumps(session[field_name]) + + setattr(g, field_name, token) + + return g.get(field_name) + + +def validate_csrf(data, secret_key=None, time_limit=None, token_key=None): + +~~ secret_key = _get_config( +~~ secret_key, 'WTF_CSRF_SECRET_KEY', current_app.secret_key, + message='A secret key is required to use CSRF.' + ) + field_name = _get_config( + token_key, 'WTF_CSRF_FIELD_NAME', 'csrf_token', + message='A field name is required to use CSRF.' + ) + time_limit = _get_config( + time_limit, 'WTF_CSRF_TIME_LIMIT', 3600, required=False + ) + + if not data: + raise ValidationError('The CSRF token is missing.') + + if field_name not in session: + raise ValidationError('The CSRF session token is missing.') + + s = URLSafeTimedSerializer(secret_key, salt='wtf-csrf-token') + + try: + token = s.loads(data, max_age=time_limit) + except SignatureExpired: + raise ValidationError('The CSRF token has expired.') + except BadData: + raise ValidationError('The CSRF token is invalid.') + + if not safe_str_cmp(session[field_name], token): + raise ValidationError('The CSRF tokens do not match.') + + +def _get_config( + value, config_name, default=None, + required=True, message='CSRF is not configured.' +): + + if value is None: +~~ value = current_app.config.get(config_name, default) + + if required and value is None: + raise RuntimeError(message) + + return value + + +class _FlaskFormCSRF(CSRF): + def setup_form(self, form): + self.meta = form.meta + return super().setup_form(form) + + def generate_csrf_token(self, csrf_token_field): + return generate_csrf( + secret_key=self.meta.csrf_secret, + token_key=self.meta.csrf_field_name + ) + + def validate_csrf_token(self, form, field): + if g.get('csrf_valid', False): + return + + try: + validate_csrf( + + +## ... source file abbreviated to get to current_app examples ... + + + def csrf_protect(): + if not app.config['WTF_CSRF_ENABLED']: + return + + if not app.config['WTF_CSRF_CHECK_DEFAULT']: + return + + if request.method not in app.config['WTF_CSRF_METHODS']: + return + + if not request.endpoint: + return + + if request.blueprint in self._exempt_blueprints: + return + + view = app.view_functions.get(request.endpoint) + dest = f'{view.__module__}.{view.__name__}' + + if dest in self._exempt_views: + return + + self.protect() + + def _get_csrf_token(self): +~~ field_name = current_app.config['WTF_CSRF_FIELD_NAME'] + base_token = request.form.get(field_name) + + if base_token: + return base_token + + for key in request.form: + if key.endswith(field_name): + csrf_token = request.form[key] + + if csrf_token: + return csrf_token + +~~ for header_name in current_app.config['WTF_CSRF_HEADERS']: + csrf_token = request.headers.get(header_name) + + if csrf_token: + return csrf_token + + return None + + def protect(self): +~~ if request.method not in current_app.config['WTF_CSRF_METHODS']: + return + + try: + validate_csrf(self._get_csrf_token()) + except ValidationError as e: + logger.info(e.args[0]) + self._error_response(e.args[0]) + +~~ if request.is_secure and current_app.config['WTF_CSRF_SSL_STRICT']: + if not request.referrer: + self._error_response('The referrer header is missing.') + + good_referrer = f'https://{request.host}/' + + if not same_origin(request.referrer, good_referrer): + self._error_response('The referrer does not match the host.') + + g.csrf_valid = True # mark this request as CSRF valid + + def exempt(self, view): + + if isinstance(view, Blueprint): + self._exempt_blueprints.add(view.name) + return view + + if isinstance(view, str): + view_location = view + else: + view_location = '.'.join((view.__module__, view.__name__)) + + self._exempt_views.add(view_location) + return view + + def _error_response(self, reason): + raise CSRFError(reason) + + def error_handler(self, view): + + warnings.warn(FlaskWTFDeprecationWarning( + '"@csrf.error_handler" is deprecated. Use the standard Flask ' + 'error system with "@app.errorhandler(CSRFError)" instead. This ' + 'will be removed in 1.0.' + ), stacklevel=2) + + @wraps(view) + def handler(reason): +~~ response = current_app.make_response(view(reason)) + raise CSRFError(response=response) + + self._error_response = handler + return view + + +class CsrfProtect(CSRFProtect): + + def __init__(self, app=None): + warnings.warn(FlaskWTFDeprecationWarning( + '"flask_wtf.CsrfProtect" has been renamed to "CSRFProtect" ' + 'and will be removed in 1.0.' + ), stacklevel=2) + super().__init__(app=app) + + +class CSRFError(BadRequest): + + description = 'CSRF validation failed.' + + +def same_origin(current_uri, compare_uri): + current = urlparse(current_uri) + compare = urlparse(compare_uri) + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 15 from Flask-Security-Too +[Flask-Security-Too](https://github.com/Flask-Middleware/flask-security/) +([PyPi page](https://pypi.org/project/Flask-Security-Too/) and +[project documentation](https://flask-security-too.readthedocs.io/en/stable/)) +is a maintained fork of the original +[Flask-Security](https://github.com/mattupstate/flask-security) project that +makes it easier to add common security features to [Flask](/flask.html) +web applications. A few of the critical goals of the Flask-Security-Too +project are ensuring JavaScript client-based single-page applications (SPAs) +can work securely with Flask-based backends and that guidance by the +[OWASP](https://owasp.org/) organization is followed by default. + +The Flask-Security-Too project is provided as open source under the +[MIT license](https://github.com/Flask-Middleware/flask-security/blob/master/LICENSE). + +[**Flask-Security-Too / flask_security / core.py**](https://github.com/Flask-Middleware/flask-security/blob/master/flask_security/./core.py) + +```python +# core.py + +from datetime import datetime, timedelta +import re +import typing as t +import warnings + +import pkg_resources +~~from flask import _request_ctx_stack, current_app +from flask.json import JSONEncoder +from flask_login import AnonymousUserMixin, LoginManager +from flask_login import UserMixin as BaseUserMixin +from flask_login import current_user +from flask_principal import Identity, Principal, RoleNeed, UserNeed, identity_loaded +from flask_wtf import FlaskForm +from itsdangerous import URLSafeTimedSerializer +from passlib.context import CryptContext +from werkzeug.datastructures import ImmutableList +from werkzeug.local import LocalProxy + +from .babel import FsDomain +from .decorators import ( + default_reauthn_handler, + default_unauthn_handler, + default_unauthz_handler, +) +from .forms import ( + ChangePasswordForm, + ConfirmRegisterForm, + ForgotPasswordForm, + LoginForm, + PasswordlessLoginForm, + RegisterForm, + + +## ... source file abbreviated to get to current_app examples ... + + + "TRACKABLE": False, + "PASSWORDLESS": False, + "CHANGEABLE": False, + "TWO_FACTOR": False, + "SEND_REGISTER_EMAIL": True, + "SEND_PASSWORD_CHANGE_EMAIL": True, + "SEND_PASSWORD_RESET_EMAIL": True, + "SEND_PASSWORD_RESET_NOTICE_EMAIL": True, + "LOGIN_WITHIN": "1 days", + "TWO_FACTOR_AUTHENTICATOR_VALIDITY": 120, + "TWO_FACTOR_MAIL_VALIDITY": 300, + "TWO_FACTOR_SMS_VALIDITY": 120, + "TWO_FACTOR_ALWAYS_VALIDATE": True, + "TWO_FACTOR_LOGIN_VALIDITY": "30 days", + "TWO_FACTOR_VALIDITY_SALT": "tf-validity-salt", + "TWO_FACTOR_VALIDITY_COOKIE": { + "httponly": True, + "secure": False, + "samesite": "Strict", + }, + "CONFIRM_EMAIL_WITHIN": "5 days", + "RESET_PASSWORD_WITHIN": "5 days", + "LOGIN_WITHOUT_CONFIRMATION": False, + "AUTO_LOGIN_AFTER_CONFIRM": True, + "EMAIL_SENDER": LocalProxy( +~~ lambda: current_app.config.get("MAIL_DEFAULT_SENDER", "no-reply@localhost") + ), + "TWO_FACTOR_RESCUE_MAIL": "no-reply@localhost", + "TOKEN_AUTHENTICATION_KEY": "auth_token", + "TOKEN_AUTHENTICATION_HEADER": "Authentication-Token", + "TOKEN_MAX_AGE": None, + "CONFIRM_SALT": "confirm-salt", + "RESET_SALT": "reset-salt", + "LOGIN_SALT": "login-salt", + "CHANGE_SALT": "change-salt", + "REMEMBER_SALT": "remember-salt", + "DEFAULT_REMEMBER_ME": False, + "DEFAULT_HTTP_AUTH_REALM": _("Login Required"), + "EMAIL_SUBJECT_REGISTER": _("Welcome"), + "EMAIL_SUBJECT_CONFIRM": _("Please confirm your email"), + "EMAIL_SUBJECT_PASSWORDLESS": _("Login instructions"), + "EMAIL_SUBJECT_PASSWORD_NOTICE": _("Your password has been reset"), + "EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE": _("Your password has been changed"), + "EMAIL_SUBJECT_PASSWORD_RESET": _("Password reset instructions"), + "EMAIL_PLAINTEXT": True, + "EMAIL_HTML": True, + "EMAIL_SUBJECT_TWO_FACTOR": _("Two-factor Login"), + "EMAIL_SUBJECT_TWO_FACTOR_RESCUE": _("Two-factor Rescue"), + "USER_IDENTITY_ATTRIBUTES": [ + {"email": {"mapper": uia_email_mapper, "case_insensitive": True}} + + +## ... source file abbreviated to get to current_app examples ... + + + for key, value in get_config(app).items(): + setattr(self, key.lower(), value) + + identity_loaded.connect_via(app)(_on_identity_loaded) + + if hasattr(self.datastore, "user_model") and not hasattr( + self.datastore.user_model, "fs_uniquifier" + ): # pragma: no cover + raise ValueError("User model must contain fs_uniquifier as of 4.0.0") + + for uia in cv("USER_IDENTITY_ATTRIBUTES", app=app): # pragma: no cover + if not isinstance(uia, dict): + raise ValueError( + "SECURITY_USER_IDENTITY_ATTRIBUTES changed semantics" + " in 4.0 - please see release notes." + ) + if len(list(uia.keys())) != 1: + raise ValueError( + "Each element in SECURITY_USER_IDENTITY_ATTRIBUTES" + " must have one and only one key." + ) + + @app.before_first_request + def _register_i18n(): + if "_" not in app.jinja_env.globals: +~~ current_app.jinja_env.globals["_"] = self.i18n_domain.gettext +~~ current_app.jinja_env.globals["_fsdomain"] = self.i18n_domain.gettext + + @app.before_first_request + def _csrf_init(): +~~ if not current_app.config.get("WTF_CSRF_ENABLED", True): + return +~~ csrf = current_app.extensions.get("csrf", None) + + if cv("CSRF_PROTECT_MECHANISMS") != AUTHN_MECHANISMS: + if not csrf: + raise ValueError( + "CSRF_PROTECT_MECHANISMS defined but" + " CsrfProtect not part of application" + ) +~~ if current_app.config.get("WTF_CSRF_CHECK_DEFAULT", True): + raise ValueError( + "WTF_CSRF_CHECK_DEFAULT must be set to False if" + " CSRF_PROTECT_MECHANISMS is set" + ) + if ( + cv("CSRF_IGNORE_UNAUTH_ENDPOINTS") + and csrf +~~ and current_app.config.get("WTF_CSRF_CHECK_DEFAULT", False) + ): + raise ValueError( + "To ignore unauth endpoints you must set WTF_CSRF_CHECK_DEFAULT" + " to False" + ) + + csrf_cookie = cv("CSRF_COOKIE") + if csrf_cookie and csrf_cookie.get("key", None): +~~ current_app.config["SECURITY_CSRF_COOKIE_NAME"] = csrf_cookie.pop("key") + if cv("CSRF_COOKIE_NAME") and not csrf: + raise ValueError( + "CSRF_COOKIE defined however CsrfProtect not part of application" + ) + + if csrf: + csrf.exempt("flask_security.views.logout") + if cv("CSRF_COOKIE_NAME"): +~~ current_app.after_request(csrf_cookie_handler) +~~ current_app.config["WTF_CSRF_HEADERS"].append(cv("CSRF_HEADER")) + + self._phone_util = self.phone_util_cls(app) + self._mail_util = self.mail_util_cls(app) + self._password_util = self.password_util_cls(app) + self._username_util = self.username_util_cls(app) + rvre = cv("REDIRECT_VALIDATE_RE", app=app) + if rvre: + self._redirect_validate_re = re.compile(rvre) + + if not hasattr(app, "login_manager") or not self.login_manager: + self.login_manager = _get_login_manager(app, self.anonymous_user) + + self.remember_token_serializer = _get_serializer(app, "remember") + self.login_serializer = _get_serializer(app, "login") + self.reset_serializer = _get_serializer(app, "reset") + self.confirm_serializer = _get_serializer(app, "confirm") + self.us_setup_serializer = _get_serializer(app, "us_setup") + self.tf_validity_serializer = _get_serializer(app, "two_factor_validity") + self.principal = _get_principal(app) + self.pwd_context = _get_pwd_context(app) + self.hashing_context = _get_hashing_context(app) + self.i18n_domain = FsDomain(app) + + if cv("USERNAME_ENABLE", app): + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 16 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / user_manager.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/./user_manager.py) + +```python +# user_manager.py + + +import datetime + +~~from flask import abort, Blueprint, current_app, Flask, session +from flask_login import LoginManager +from wtforms import ValidationError + +from . import ConfigError +from . import forms +from .db_manager import DBManager +from .email_manager import EmailManager +from .password_manager import PasswordManager +from .token_manager import TokenManager +from .translation_utils import lazy_gettext as _ # map _() to lazy_gettext() +from .user_manager__settings import UserManager__Settings +from .user_manager__utils import UserManager__Utils +from .user_manager__views import UserManager__Views + + +class UserManager(UserManager__Settings, UserManager__Utils, UserManager__Views): + + def __init__(self, app, db, UserClass, **kwargs): + + self.app = app + if app: + self.init_app(app, db, UserClass, **kwargs) + + def init_app( + + +## ... source file abbreviated to get to current_app examples ... + + + @app.before_request + def advance_session_timeout(): + session.permanent = True # Timeout after app.permanent_session_lifetime period + session.modified = True # Advance session timeout each time a user visits a page + + self.login_manager = LoginManager(app) + self.login_manager.login_view = 'user.login' + + @self.login_manager.user_loader + def load_user_by_user_token(user_token): + user = self.db_manager.UserClass.get_user_by_token(user_token) + return user + + self.babel = app.extensions.get('babel', None) + from .translation_utils import init_translations + init_translations(self.babel) + + if not hasattr(app.jinja_env, 'install_gettext_callables'): + app.jinja_env.add_extension('jinja2.ext.i18n') + app.jinja_env.install_null_translations() + + def flask_user_context_processor(): + def call_or_get(function_or_property): + return function_or_property() if callable(function_or_property) else function_or_property + +~~ return dict( +~~ user_manager=current_app.user_manager, + call_or_get=call_or_get, + ) + + app.context_processor(flask_user_context_processor) + + blueprint = Blueprint('flask_user', __name__, template_folder='templates') + app.register_blueprint(blueprint) + + self.AddEmailFormClass = forms.AddEmailForm + self.ChangePasswordFormClass = forms.ChangePasswordForm + self.ChangeUsernameFormClass = forms.ChangeUsernameForm + self.EditUserProfileFormClass = forms.EditUserProfileForm + self.ForgotPasswordFormClass = forms.ForgotPasswordForm + self.InviteUserFormClass = forms.InviteUserForm + self.LoginFormClass = forms.LoginForm + self.RegisterFormClass = forms.RegisterForm + self.ResendEmailConfirmationFormClass = forms.ResendEmailConfirmationForm + self.ResetPasswordFormClass = forms.ResetPasswordForm + + self.db_manager = DBManager(app, db, UserClass, UserEmailClass, UserInvitationClass, RoleClass) + + self.password_manager = PasswordManager(app) + + if self.USER_ENABLE_EMAIL: + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 17 from Flask-VueJs-Template +[Flask-VueJs-Template](https://github.com/gtalarico/flask-vuejs-template) +([demo site](https://flask-vuejs-template.herokuapp.com/)) +is a minimal [Flask](/flask.html) boilerplate starter project that +combines Flask, [Vue.js](https://www.fullstackpython.com/vuejs.html), +and [Flask-RESTPlus](https://flask-restplus.readthedocs.io/en/stable/). +The project provides some sensible defaults that are easy to continue +building on, and the source code is open source under the +[MIT license](https://github.com/gtalarico/flask-vuejs-template/blob/master/LICENSE.md). + +[**Flask-VueJs-Template / app / __init__.py**](https://github.com/gtalarico/flask-vuejs-template/blob/master/app/./__init__.py) + +```python +# __init__.py +import os +~~from flask import Flask, current_app, send_file + +from .api import api_bp +from .client import client_bp + +app = Flask(__name__, static_folder='../dist/static') +app.register_blueprint(api_bp) + +from .config import Config +app.logger.info('>>> {}'.format(Config.FLASK_ENV)) + +@app.route('/') +def index_client(): +~~ dist_dir = current_app.config['DIST_DIR'] + entry = os.path.join(dist_dir, 'index.html') + return send_file(entry) + + + + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 18 from Flasky +[Flasky](https://github.com/miguelgrinberg/flasky) is a wonderful +example application by +[Miguel Grinberg](https://github.com/miguelgrinberg) that he builds +while teaching developers how to use [Flask](/flask.html) in +[his books and videos](https://courses.miguelgrinberg.com/). Flasky +is [open sourced under the MIT license](https://github.com/miguelgrinberg/flasky/blob/master/LICENSE). + +[**Flasky / migrations / env.py**](https://github.com/miguelgrinberg/flasky/blob/master/./migrations/env.py) + +```python +# env.py +from __future__ import with_statement +from alembic import context +from sqlalchemy import engine_from_config, pool +from logging.config import fileConfig + +config = context.config + +fileConfig(config.config_file_name) + +~~from flask import current_app +~~config.set_main_option('sqlalchemy.url', current_app.config.get('SQLALCHEMY_DATABASE_URI')) +~~target_metadata = current_app.extensions['migrate'].db.metadata + + +def run_migrations_offline(): + url = config.get_main_option("sqlalchemy.url") + context.configure(url=url) + + with context.begin_transaction(): + context.run_migrations() + +def run_migrations_online(): + engine = engine_from_config( + config.get_section(config.config_ini_section), + prefix='sqlalchemy.', + poolclass=pool.NullPool) + + connection = engine.connect() + context.configure( + connection=connection, + target_metadata=target_metadata + ) + + try: + with context.begin_transaction(): + context.run_migrations() + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 19 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / migrations / env.py**](https://github.com/indico/indico/blob/master/indico/migrations/env.py) + +```python +# env.py + +import logging.config + +from alembic import context +~~from flask import current_app +from sqlalchemy import engine_from_config, pool + +from indico.core.db.sqlalchemy.util.models import import_all_models + + +import_all_models() + +config = context.config +logging.config.fileConfig(config.config_file_name) + +~~config.set_main_option('sqlalchemy.url', current_app.config.get('SQLALCHEMY_DATABASE_URI')) +~~target_metadata = current_app.extensions['migrate'].db.metadata + + +def _include_object(object_, name, type_, reflected, compare_to): + if type_ != 'table': + return True + if object_.schema and object_.schema.startswith('plugin_'): + return False + return name != 'alembic_version' and not name.startswith('alembic_version_') + + +def _render_item(type_, obj, autogen_context): + if hasattr(obj, 'info') and obj.info.get('alembic_dont_render'): + return None + func = getattr(obj, 'alembic_render_' + type_, None) + if func is None: + return False + return func(autogen_context, autogen_context.opts['template_args']['toplevel_code']) + + +def run_migrations_offline(): + url = config.get_main_option('sqlalchemy.url') + context.configure(url=url, target_metadata=target_metadata, include_schemas=True, + version_table_schema='public', include_object=_include_object, render_item=_render_item, + template_args={'toplevel_code': set()}) + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 20 from sandman2 +[sandman2](https://github.com/jeffknupp/sandman2) +([project documentation](https://sandman2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/sandman2/)) +is a code library for automatically generating +[RESTful APIs](/application-programming-interfaces.html) from +existing database schemas. This approach is handy for solving +straightforward situations where you want to put an abstraction +layer between one or more applications and your +[relational database](/databases.html) to prevent or reduce +direct database access. + +The sandman2 project is provided under the +[Apache License 2.0](https://github.com/jeffknupp/sandman2/blob/master/LICENSE). + +[**sandman2 / sandman2 / app.py**](https://github.com/jeffknupp/sandman2/blob/master/sandman2/./app.py) + +```python +# app.py + +~~from flask import Flask, current_app, jsonify +from sqlalchemy.sql import sqltypes + +from sandman2.exception import ( + BadRequestException, + ForbiddenException, + NotFoundException, + NotAcceptableException, + NotImplementedException, + ConflictException, + ServerErrorException, + ServiceUnavailableException, + ) +from sandman2.service import Service +from sandman2.model import db, Model, AutomapModel +from sandman2.admin import CustomAdminView +from flask_admin import Admin +from flask_httpauth import HTTPBasicAuth + +auth = HTTPBasicAuth() + +def get_app( + database_uri, + exclude_tables=None, + user_models=None, + + +## ... source file abbreviated to get to current_app examples ... + + + cls.__model__.primary_key()) + return jsonify(routes) + return app + + +def _register_error_handlers(app): + @app.errorhandler(BadRequestException) + @app.errorhandler(ForbiddenException) + @app.errorhandler(NotAcceptableException) + @app.errorhandler(NotFoundException) + @app.errorhandler(ConflictException) + @app.errorhandler(ServerErrorException) + @app.errorhandler(NotImplementedException) + @app.errorhandler(ServiceUnavailableException) + def handle_application_error(error): # pylint:disable=unused-variable + response = jsonify(error.to_dict()) + response.status_code = error.code + return response + + +def register_service(cls, primary_key_type): + view_func = cls.as_view(cls.__name__.lower()) # pylint: disable=no-member + methods = set(cls.__model__.__methods__) # pylint: disable=no-member + + if 'GET' in methods: # pylint: disable=no-member +~~ current_app.add_url_rule( + cls.__model__.__url__ + '/', defaults={'resource_id': None}, + view_func=view_func, + methods=['GET']) +~~ current_app.add_url_rule( + '{resource}/meta'.format(resource=cls.__model__.__url__), + view_func=view_func, + methods=['GET']) + if 'POST' in methods: # pylint: disable=no-member +~~ current_app.add_url_rule( + cls.__model__.__url__ + '/', view_func=view_func, methods=['POST', ]) +~~ current_app.add_url_rule( + '{resource}/<{pk_type}:{pk}>'.format( + resource=cls.__model__.__url__, + pk='resource_id', pk_type=primary_key_type), + view_func=view_func, + methods=methods - {'POST'}) +~~ current_app.classes.append(cls) + + +def _reflect_all(exclude_tables=None, admin=None, read_only=False, schema=None): + AutomapModel.prepare( # pylint:disable=maybe-no-member + db.engine, reflect=True, schema=schema) + for cls in AutomapModel.classes: + if exclude_tables and cls.__table__.name in exclude_tables: + continue + if read_only: + cls.__methods__ = {'GET'} + register_model(cls, admin) + + +def register_model(cls, admin=None): + cls.__url__ = '/{}'.format(cls.__name__.lower()) + service_class = type( + cls.__name__ + 'Service', + (Service,), + { + '__model__': cls, + }) + + cols = list(cls().__table__.primary_key.columns) + + + +## ... source file continues with no further current_app examples... + +``` + + +## Example 21 from tedivms-flask +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + +[**tedivms-flask / app / utils / api.py**](https://github.com/tedivm/tedivms-flask/blob/master/app/utils/api.py) + +```python +# api.py +from app.models import user_models as users +from functools import wraps +~~from flask import request, abort, current_app + + +def is_authorized_api_user(roles=False): + if 'API_ID' not in request.headers: + return False + if 'API_KEY' not in request.headers: + return False + api_key = users.ApiKey.query.filter(users.ApiKey.id==request.headers['API_ID']).first() + if not api_key: + return False +~~ if not current_app.user_manager.verify_password(request.headers['API_KEY'], api_key.hash): + return False + if not roles: + return True + if api_key.user.has_role('admin'): + return True + for role in roles: + if api_key.user.has_role(role): + return True + return False + + +def roles_accepted_api(*role_names): + def wrapper(view_function): + @wraps(view_function) + def decorated_view_function(*args, **kwargs): + if not is_authorized_api_user(role_names): + return abort(403) + return view_function(*args, **kwargs) + return decorated_view_function + return wrapper + + +def api_credentials_required(): + def wrapper(view_function): + + +## ... source file continues with no further current_app examples... + +``` + diff --git a/content/pages/examples/flask/flask-globals-g.markdown b/content/pages/examples/flask/flask-globals-g.markdown new file mode 100644 index 000000000..6c47941e6 --- /dev/null +++ b/content/pages/examples/flask/flask-globals-g.markdown @@ -0,0 +1,1196 @@ +title: flask.globals g Example Code +category: page +slug: flask-globals-g-examples +sortorder: 500021015 +toc: False +sidebartitle: flask.globals g +meta: Python example code that shows how to use the g callable from the flask.globals module of the Flask project. + + +[g](https://flask.palletsprojects.com/en/1.1.x/api/#flask.g) is +an object for storing data during the +[application context](https://flask.palletsprojects.com/en/1.1.x/appcontext/) +of a running [Flask](/flask.html) web app. + +`g` can also be imported directly from the `flask` module instead +of `flask.globals`, so you will often see that shortcut in example code. + +current_app, +request, +and session +are several other callables with code examples from the same `flask.globals` package. + +## Example 1 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / security / manager.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/security/manager.py) + +```python +# manager.py +import base64 +import datetime +import json +import logging +import re +from typing import Dict, List, Optional, Set, Tuple + +~~from flask import g, session, url_for +from flask_babel import lazy_gettext as _ +from flask_jwt_extended import current_user as current_user_jwt +from flask_jwt_extended import JWTManager +from flask_login import current_user, LoginManager +from werkzeug.security import check_password_hash, generate_password_hash + +from .api import SecurityApi +from .registerviews import ( + RegisterUserDBView, + RegisterUserOAuthView, + RegisterUserOIDView, +) +from .views import ( + AuthDBView, + AuthLDAPView, + AuthOAuthView, + AuthOIDView, + AuthRemoteUserView, + PermissionModelView, + PermissionViewModelView, + RegisterUserModelView, + ResetMyPasswordView, + ResetPasswordView, + RoleModelView, + + +## ... source file abbreviated to get to g examples ... + + + return self.appbuilder.get_app.config["AUTH_LDAP_TLS_CACERTDIR"] + + @property + def auth_ldap_tls_cacertfile(self): + return self.appbuilder.get_app.config["AUTH_LDAP_TLS_CACERTFILE"] + + @property + def auth_ldap_tls_certfile(self): + return self.appbuilder.get_app.config["AUTH_LDAP_TLS_CERTFILE"] + + @property + def auth_ldap_tls_keyfile(self): + return self.appbuilder.get_app.config["AUTH_LDAP_TLS_KEYFILE"] + + @property + def openid_providers(self): + return self.appbuilder.get_app.config["OPENID_PROVIDERS"] + + @property + def oauth_providers(self): + return self.appbuilder.get_app.config["OAUTH_PROVIDERS"] + + @property + def current_user(self): + if current_user.is_authenticated: +~~ return g.user + elif current_user_jwt: + return current_user_jwt + + def oauth_user_info_getter(self, f): + + def wraps(provider, response=None): + ret = f(self, provider, response=response) + if not type(ret) == dict: + log.error( + "OAuth user info decorated function " + "did not returned a dict, but: {0}".format(type(ret)) + ) + return {} + return ret + + self.oauth_user_info = wraps + return wraps + + def get_oauth_token_key_name(self, provider): + for _provider in self.oauth_providers: + if _provider["name"] == provider: + return _provider.get("token_key", "oauth_token") + + def get_oauth_token_secret_name(self, provider): + + +## ... source file abbreviated to get to g examples ... + + + role, permission_name, view_menu_name + ): + result.add(view_menu_name) + else: + db_role_ids.append(role.id) + pvms_names = [ + pvm.view_menu.name + for pvm in self.find_roles_permission_view_menus( + permission_name, db_role_ids + ) + ] + result.update(pvms_names) + return result + + def has_access(self, permission_name, view_name): + if current_user.is_authenticated: + return self._has_view_access(g.user, permission_name, view_name) + elif current_user_jwt: + return self._has_view_access(current_user_jwt, permission_name, view_name) + else: + return self.is_item_public(permission_name, view_name) + + def get_user_menu_access(self, menu_names: List[str] = None) -> Set[str]: + if current_user.is_authenticated: + return self._get_user_permission_view_menus( +~~ g.user, "menu_access", view_menus_name=menu_names + ) + elif current_user_jwt: + return self._get_user_permission_view_menus( + current_user_jwt, "menu_access", view_menus_name=menu_names + ) + else: + return self._get_user_permission_view_menus( + None, "menu_access", view_menus_name=menu_names + ) + + def add_permissions_view(self, base_permissions, view_menu): + view_menu_db = self.add_view_menu(view_menu) + perm_views = self.find_permissions_view_menu(view_menu_db) + + if not perm_views: + for permission in base_permissions: + pv = self.add_permission_view_menu(permission, view_menu) + if self.auth_role_admin not in self.builtin_roles: + role_admin = self.find_role(self.auth_role_admin) + self.add_permission_role(role_admin, pv) + else: + role_admin = self.find_role(self.auth_role_admin) + for permission in base_permissions: + if not self.exist_permission_on_views(perm_views, permission): + + +## ... source file abbreviated to get to g examples ... + + + raise NotImplementedError + + def exist_permission_on_views(self, lst, item): + raise NotImplementedError + + def exist_permission_on_view(self, lst, permission, view_menu): + raise NotImplementedError + + def add_permission_role(self, role, perm_view): + raise NotImplementedError + + def del_permission_role(self, role, perm_view): + raise NotImplementedError + + def export_roles(self, path: Optional[str] = None) -> None: + raise NotImplementedError + + def import_roles(self, path: str) -> None: + raise NotImplementedError + + def load_user(self, pk): + return self.get_user_by_id(int(pk)) + + def load_user_jwt(self, pk): + user = self.load_user(pk) +~~ g.user = user + return user + + @staticmethod + def before_request(): +~~ g.user = current_user + + + +## ... source file continues with no further g examples... + +``` + + +## Example 2 from flask-bones +[flask-bones](https://github.com/cburmeister/flask-bones) +([demo](http://flask-bones.herokuapp.com/)) +is large scale [Flask](/flask.html) example application built +with [Blueprints](https://flask.palletsprojects.com/en/1.1.x/blueprints/) +([example Blueprint code](/flask-blueprints-blueprint-examples.html)). +This project is provided as open source under the +[MIT license](https://github.com/cburmeister/flask-bones/blob/master/LICENSE). + +[**flask-bones / app / __init__.py**](https://github.com/cburmeister/flask-bones/blob/master/app/./__init__.py) + +```python +# __init__.py +import time + +~~from flask import Flask, g, render_template, request +import arrow +import requests + +from app import config +from app.assets import assets +from app.auth import auth +from app.commands import create_db, drop_db, populate_db, recreate_db +from app.database import db +from app.extensions import lm, travis, mail, migrate, bcrypt, babel, rq, limiter +from app.user import user +from app.utils import url_for_other_page + + +def create_app(config=config.base_config): + app = Flask(__name__) + app.config.from_object(config) + + register_extensions(app) + register_blueprints(app) + register_errorhandlers(app) + register_jinja_env(app) + register_commands(app) + + def get_locale(): + return request.accept_languages.best_match(config.SUPPORTED_LOCALES) + + if babel.locale_selector_func is None: + babel.locale_selector_func = get_locale + + @app.before_request + def before_request(): +~~ g.request_start_time = time.time() +~~ g.request_time = lambda: '%.5fs' % (time.time() - g.request_start_time) +~~ g.pjax = 'X-PJAX' in request.headers + + @app.route('/', methods=['GET']) + def index(): + return render_template('index.html') + + return app + + +def register_commands(app): + for command in [create_db, drop_db, populate_db, recreate_db]: + app.cli.command()(command) + + +def register_extensions(app): + travis.init_app(app) + db.init_app(app) + lm.init_app(app) + mail.init_app(app) + bcrypt.init_app(app) + assets.init_app(app) + babel.init_app(app) + rq.init_app(app) + migrate.init_app(app, db) + limiter.init_app(app) + + +## ... source file continues with no further g examples... + +``` + + +## Example 3 from flask-bookshelf +[flask-bookshelf](https://github.com/damyanbogoev/flask-bookshelf) is the +example [Flask](/flask.html) application that developers create when +going through +[this Flask series of blog posts](https://damyanon.net/tags/flask-series/). + +[**flask-bookshelf / bookshelf / __init__.py**](https://github.com/damyanbogoev/flask-bookshelf/blob/master/bookshelf/./__init__.py) + +```python +# __init__.py +~~from flask import abort, Flask, g, render_template, request, current_app +from flask_babel import Babel +from flask_security import current_user +from bookshelf.utils import get_instance_folder_path +from bookshelf.main.controllers import main +from bookshelf.admin.controllers import admin +from bookshelf.cache import cache +from bookshelf.config import configure_app +from bookshelf.data.models import db + +app = Flask( + __name__, + instance_path=get_instance_folder_path(), + instance_relative_config=True, + template_folder="templates", +) + +babel = Babel(app) +configure_app(app) +cache.init_app(app) +db.init_app(app) +app.jinja_env.add_extension("jinja2.ext.loopcontrols") + + +@app.url_defaults +def set_language_code(endpoint, values): +~~ if "lang_code" in values or not g.get("lang_code", None): + return + if app.url_map.is_endpoint_expecting(endpoint, "lang_code"): +~~ values["lang_code"] = g.lang_code + + +@app.url_value_preprocessor +def get_lang_code(endpoint, values): + if values is not None: +~~ g.lang_code = values.pop("lang_code", None) + + +@app.before_request +def ensure_lang_support(): +~~ lang_code = g.get("lang_code", None) + if lang_code and lang_code not in app.config["SUPPORTED_LANGUAGES"].keys(): + abort(404) + + +@babel.localeselector +def get_locale(): +~~ return g.get("lang_code", app.config["BABEL_DEFAULT_LOCALE"]) + + +@babel.timezoneselector +def get_timezone(): +~~ user = g.get("user", None) + if user is not None: + return user.timezone + return "UTC" + + +@app.errorhandler(404) +def page_not_found(error): + current_app.logger.error("Page not found: %s", (request.path, error)) + return render_template("404.htm"), 404 + + +@app.errorhandler(500) +def internal_server_error(error): + current_app.logger.error("Server Error: %s", (error)) + return render_template("500.htm"), 500 + + +@app.errorhandler(Exception) +def unhandled_exception(error): + current_app.logger.error("Unhandled Exception: %s", (error)) + return render_template("500.htm"), 500 + + +@app.context_processor +def inject_data(): +~~ return dict(user=current_user, lang_code=g.get("lang_code", None)) + + +@app.route("/") +@app.route("//") +@cache.cached(300) +def home(lang_code=None): + return render_template("index.htm") + + +app.register_blueprint(main, url_prefix="/main") +app.register_blueprint(main, url_prefix="//main") +app.register_blueprint(admin, url_prefix="/admin") +app.register_blueprint(admin, url_prefix="//admin") + + + +## ... source file continues with no further g examples... + +``` + + +## Example 4 from flask-debugtoolbar +[Flask Debug-toolbar](https://github.com/flask-debugtoolbar/flask-debugtoolbar) +([documentation](https://flask-debugtoolbar.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/Flask-DebugToolbar/)) +is a [Flask](/flask.html) conversion of the popular +[Django Debug Toolbar](https://github.com/jazzband/django-debug-toolbar) +project. This extension creates a sidebar with useful debugging +information when you are running a Flask application in development +mode. The project is provided as open source under +[this license](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/LICENSE). + +[**flask-debugtoolbar / flask_debugtoolbar / __init__.py**](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/flask_debugtoolbar/./__init__.py) + +```python +# __init__.py +import os +import warnings + +~~from flask import Blueprint, current_app, request, g, send_from_directory, url_for +from flask.globals import _request_ctx_stack +from jinja2 import Environment, PackageLoader +from werkzeug.urls import url_quote_plus + +from flask_debugtoolbar.compat import iteritems +from flask_debugtoolbar.toolbar import DebugToolbar +from flask_debugtoolbar.utils import decode_text, gzip_compress, gzip_decompress + +try: + from importlib.metadata import version + + __version__ = version("Flask-DebugToolbar") +except ImportError: + import pkg_resources + + __version__ = pkg_resources.get_distribution("Flask-DebugToolbar").version + + +module = Blueprint('debugtoolbar', __name__) + + +def replace_insensitive(string, target, replacement): + no_case = string.lower() + index = no_case.rfind(target.lower()) + + +## ... source file abbreviated to get to g examples ... + + + rule = req.url_rule + + if getattr(rule, 'provide_automatic_options', False) \ + and req.method == 'OPTIONS': + return app.make_default_options_response() + + view_func = app.view_functions[rule.endpoint] + view_func = self.process_view(app, view_func, req.view_args) + + return view_func(**req.view_args) + + def _show_toolbar(self): + if request.blueprint == 'debugtoolbar': + return False + + hosts = current_app.config['DEBUG_TB_HOSTS'] + if hosts and request.remote_addr not in hosts: + return False + + return True + + def send_static_file(self, filename): + return send_from_directory(self._static_dir, filename) + + def process_request(self): +~~ g.debug_toolbar = self + + if not self._show_toolbar(): + return + + real_request = request._get_current_object() + + self.debug_toolbars[real_request] = ( + DebugToolbar(real_request, self.jinja_env)) + + for panel in self.debug_toolbars[real_request].panels: + panel.process_request(real_request) + + def process_view(self, app, view_func, view_kwargs): + real_request = request._get_current_object() + try: + toolbar = self.debug_toolbars[real_request] + except KeyError: + return view_func + + for panel in toolbar.panels: + new_view = panel.process_view(real_request, view_func, view_kwargs) + if new_view: + view_func = new_view + + + +## ... source file continues with no further g examples... + +``` + + +## Example 5 from Flask-HTTPAuth +[Flask-HTTPAuth](https://github.com/miguelgrinberg/Flask-HTTPAuth) +([documentation](https://flask-httpauth.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/Flask-HTTPAuth/)) +is a [Flask](/flask.html) framework extension that creates +Basic and Digest HTTP authentication for routes. This project +is primarily built and maintained by +[Miguel Grinberg](https://blog.miguelgrinberg.com/). It is provided +as open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/LICENSE). + +[**Flask-HTTPAuth / flask_httpauth.py**](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/././flask_httpauth.py) + +```python +# flask_httpauth.py + +from base64 import b64decode +from functools import wraps +from hashlib import md5 +from random import Random, SystemRandom +~~from flask import request, make_response, session, g, Response +from werkzeug.datastructures import Authorization +from werkzeug.security import safe_str_cmp + +__version__ = '4.2.1dev' + + +class HTTPAuth(object): + def __init__(self, scheme=None, realm=None, header=None): + self.scheme = scheme + self.realm = realm or "Authentication Required" + self.header = header + self.get_password_callback = None + self.get_user_roles_callback = None + self.auth_error_callback = None + + def default_get_password(username): + return None + + def default_auth_error(status): + return "Unauthorized Access", status + + self.get_password(default_get_password) + self.error_handler(default_auth_error) + + + +## ... source file abbreviated to get to g examples ... + + + (role is not None or optional is not None): # pragma: no cover + raise ValueError( + 'role and optional are the only supported arguments') + + def login_required_internal(f): + @wraps(f) + def decorated(*args, **kwargs): + auth = self.get_auth() + + if request.method != 'OPTIONS': # pragma: no cover + password = self.get_auth_password(auth) + + status = None + user = self.authenticate(auth, password) + if user in (False, None): + status = 401 + elif not self.authorize(role, user, auth): + status = 403 + if not optional and status: + request.data + try: + return self.auth_error_callback(status) + except TypeError: + return self.auth_error_callback() + +~~ g.flask_httpauth_user = user if user is not True \ + else auth.username if auth else None + return f(*args, **kwargs) + return decorated + + if f: + return login_required_internal(f) + return login_required_internal + + def username(self): + auth = self.get_auth() + if not auth: + return "" + return auth.username + + def current_user(self): + if hasattr(g, 'flask_httpauth_user'): +~~ return g.flask_httpauth_user + + +class HTTPBasicAuth(HTTPAuth): + def __init__(self, scheme=None, realm=None): + super(HTTPBasicAuth, self).__init__(scheme or 'Basic', realm) + + self.hash_password_callback = None + self.verify_password_callback = None + + def hash_password(self, f): + self.hash_password_callback = f + return f + + def verify_password(self, f): + self.verify_password_callback = f + return f + + def get_auth(self): + header = self.header or 'Authorization' + if header not in request.headers: + return None + value = request.headers[header].encode('utf-8') + try: + scheme, credentials = value.split(b' ', 1) + + +## ... source file abbreviated to get to g examples ... + + + selected_auth = None + if 'Authorization' in request.headers: + try: + scheme, creds = request.headers[ + 'Authorization'].split(None, 1) + except ValueError: + pass + else: + for auth in self.additional_auth: + if auth.scheme == scheme: + selected_auth = auth + break + if selected_auth is None: + selected_auth = self.main_auth + return selected_auth.login_required(role=role, + optional=optional + )(f)(*args, **kwargs) + return decorated + + if f: + return login_required_internal(f) + return login_required_internal + + def current_user(self): + if hasattr(g, 'flask_httpauth_user'): # pragma: no cover +~~ return g.flask_httpauth_user + + + +## ... source file continues with no further g examples... + +``` + + +## Example 6 from Flask-WTF +[Flask-WTF](https://github.com/lepture/flask-wtf) +([project documentation](https://flask-wtf.readthedocs.io/) +and +[PyPI page](https://pypi.org/project/Flask-WTF/)) +provides a bridge between [Flask](/flask.html) and the the +[WTForms](https://wtforms.readthedocs.io/en/2.3.x/) form-handling library. +It makes it easier to use WTForms by reducing boilerplate code and +shorter examples for common form operations as well as common security +practices such as [CSRF](/cross-site-request-forgery-csrf.html). + +[**Flask-WTF / flask_wtf / csrf.py**](https://github.com/lepture/flask-wtf/blob/master/flask_wtf/./csrf.py) + +```python +# csrf.py +import hashlib +import logging +import os +import warnings +from urllib.parse import urlparse +from functools import wraps + +~~from flask import Blueprint, current_app, g, request, session +from itsdangerous import BadData, SignatureExpired, URLSafeTimedSerializer +from werkzeug.exceptions import BadRequest +from werkzeug.security import safe_str_cmp +from wtforms import ValidationError +from wtforms.csrf.core import CSRF + +from ._compat import FlaskWTFDeprecationWarning + +__all__ = ('generate_csrf', 'validate_csrf', 'CSRFProtect') +logger = logging.getLogger(__name__) + + +def generate_csrf(secret_key=None, token_key=None): + + secret_key = _get_config( + secret_key, 'WTF_CSRF_SECRET_KEY', current_app.secret_key, + message='A secret key is required to use CSRF.' + ) + field_name = _get_config( + token_key, 'WTF_CSRF_FIELD_NAME', 'csrf_token', + message='A field name is required to use CSRF.' + ) + +~~ if field_name not in g: + s = URLSafeTimedSerializer(secret_key, salt='wtf-csrf-token') + + if field_name not in session: + session[field_name] = hashlib.sha1(os.urandom(64)).hexdigest() + + try: + token = s.dumps(session[field_name]) + except TypeError: + session[field_name] = hashlib.sha1(os.urandom(64)).hexdigest() + token = s.dumps(session[field_name]) + + setattr(g, field_name, token) + +~~ return g.get(field_name) + + +def validate_csrf(data, secret_key=None, time_limit=None, token_key=None): + + secret_key = _get_config( + secret_key, 'WTF_CSRF_SECRET_KEY', current_app.secret_key, + message='A secret key is required to use CSRF.' + ) + field_name = _get_config( + token_key, 'WTF_CSRF_FIELD_NAME', 'csrf_token', + message='A field name is required to use CSRF.' + ) + time_limit = _get_config( + time_limit, 'WTF_CSRF_TIME_LIMIT', 3600, required=False + ) + + if not data: + raise ValidationError('The CSRF token is missing.') + + if field_name not in session: + raise ValidationError('The CSRF session token is missing.') + + s = URLSafeTimedSerializer(secret_key, salt='wtf-csrf-token') + + + +## ... source file abbreviated to get to g examples ... + + + value, config_name, default=None, + required=True, message='CSRF is not configured.' +): + + if value is None: + value = current_app.config.get(config_name, default) + + if required and value is None: + raise RuntimeError(message) + + return value + + +class _FlaskFormCSRF(CSRF): + def setup_form(self, form): + self.meta = form.meta + return super().setup_form(form) + + def generate_csrf_token(self, csrf_token_field): + return generate_csrf( + secret_key=self.meta.csrf_secret, + token_key=self.meta.csrf_field_name + ) + + def validate_csrf_token(self, form, field): +~~ if g.get('csrf_valid', False): + return + + try: + validate_csrf( + field.data, + self.meta.csrf_secret, + self.meta.csrf_time_limit, + self.meta.csrf_field_name + ) + except ValidationError as e: + logger.info(e.args[0]) + raise + + +class CSRFProtect: + + def __init__(self, app=None): + self._exempt_views = set() + self._exempt_blueprints = set() + + if app: + self.init_app(app) + + def init_app(self, app): + + +## ... source file abbreviated to get to g examples ... + + + + if csrf_token: + return csrf_token + + return None + + def protect(self): + if request.method not in current_app.config['WTF_CSRF_METHODS']: + return + + try: + validate_csrf(self._get_csrf_token()) + except ValidationError as e: + logger.info(e.args[0]) + self._error_response(e.args[0]) + + if request.is_secure and current_app.config['WTF_CSRF_SSL_STRICT']: + if not request.referrer: + self._error_response('The referrer header is missing.') + + good_referrer = f'https://{request.host}/' + + if not same_origin(request.referrer, good_referrer): + self._error_response('The referrer does not match the host.') + +~~ g.csrf_valid = True # mark this request as CSRF valid + + def exempt(self, view): + + if isinstance(view, Blueprint): + self._exempt_blueprints.add(view.name) + return view + + if isinstance(view, str): + view_location = view + else: + view_location = '.'.join((view.__module__, view.__name__)) + + self._exempt_views.add(view_location) + return view + + def _error_response(self, reason): + raise CSRFError(reason) + + def error_handler(self, view): + + warnings.warn(FlaskWTFDeprecationWarning( + '"@csrf.error_handler" is deprecated. Use the standard Flask ' + 'error system with "@app.errorhandler(CSRFError)" instead. This ' + 'will be removed in 1.0.' + + +## ... source file continues with no further g examples... + +``` + + +## Example 7 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / decorators.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/./decorators.py) + +```python +# decorators.py + + +from functools import wraps +~~from flask import current_app, g +from flask_login import current_user + +def _is_logged_in_with_confirmed_email(user_manager): + if user_manager.call_or_get(current_user.is_authenticated): + unconfirmed_email_allowed = \ + getattr(g, '_flask_user_allow_unconfirmed_email', False) + + if unconfirmed_email_allowed or user_manager.db_manager.user_has_confirmed_email(current_user): + return True + + return False + + +def login_required(view_function): + @wraps(view_function) # Tells debuggers that is is a function wrapper + def decorator(*args, **kwargs): + user_manager = current_app.user_manager + + allowed = _is_logged_in_with_confirmed_email(user_manager) + if not allowed: + return user_manager.unauthenticated_view() + + return view_function(*args, **kwargs) + + + +## ... source file abbreviated to get to g examples ... + + +def roles_required(*role_names): + def wrapper(view_function): + + @wraps(view_function) # Tells debuggers that is is a function wrapper + def decorator(*args, **kwargs): + user_manager = current_app.user_manager + + allowed = _is_logged_in_with_confirmed_email(user_manager) + if not allowed: + return user_manager.unauthenticated_view() + + if not current_user.has_roles(*role_names): + return user_manager.unauthorized_view() + + return view_function(*args, **kwargs) + + return decorator + + return wrapper + + + +def allow_unconfirmed_email(view_function): + @wraps(view_function) # Tells debuggers that is is a function wrapper + def decorator(*args, **kwargs): +~~ g._flask_user_allow_unconfirmed_email = True + + try: + user_manager = current_app.user_manager + + allowed = _is_logged_in_with_confirmed_email(user_manager) + if not allowed: + return user_manager.unauthenticated_view() + + return view_function(*args, **kwargs) + + finally: +~~ g._flask_user_allow_unconfirmed_email = False + + return decorator + + + +## ... source file continues with no further g examples... + +``` + + +## Example 8 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / core / config.py**](https://github.com/indico/indico/blob/master/indico/core/config.py) + +```python +# config.py + +import ast +import codecs +import os +import re +import socket +import warnings +from datetime import timedelta + +import pytz +from celery.schedules import crontab +~~from flask import current_app, g +from flask.helpers import get_root_path +from werkzeug.datastructures import ImmutableDict +from werkzeug.urls import url_parse + +from indico.util.caching import make_hashable +from indico.util.fs import resolve_link +from indico.util.packaging import package_is_editable +from indico.util.string import crc32, snakify + + +DEFAULTS = { + 'ATTACHMENT_STORAGE': 'default', + 'AUTH_PROVIDERS': {}, + 'BASE_URL': None, + 'CACHE_DIR': '/opt/indico/cache', + 'CATEGORY_CLEANUP': {}, + 'CELERY_BROKER': None, + 'CELERY_CONFIG': {}, + 'CELERY_RESULT_BACKEND': None, + 'COMMUNITY_HUB_URL': 'https://hub.getindico.io', + 'CUSTOMIZATION_DEBUG': False, + 'CUSTOMIZATION_DIR': None, + 'CUSTOM_COUNTRIES': {}, + 'CUSTOM_LANGUAGES': {}, + + +## ... source file abbreviated to get to g examples ... + + +class IndicoConfig: + + __slots__ = ('_config', '_exc') + + def __init__(self, config=None, exc=AttributeError): + object.__setattr__(self, '_config', config) + object.__setattr__(self, '_exc', exc) + + @property + def data(self): + try: + return self._config or current_app.config['INDICO'] + except KeyError: + raise RuntimeError('config not loaded') + + @property + def hash(self): + return crc32(repr(make_hashable(sorted(self.data.items())))) + + @property + def CONFERENCE_CSS_TEMPLATES_BASE_URL(self): + return self.BASE_URL + '/css/confTemplates' + + @property + def IMAGES_BASE_URL(self): +~~ return 'static/images' if g.get('static_site') else url_parse(f'{self.BASE_URL}/images').path + + @property + def LATEX_ENABLED(self): + return bool(self.XELATEX_PATH) + + def validate(self): + from indico.core.auth import login_rate_limiter + login_rate_limiter._get_current_object() # fail in case FAILED_LOGIN_RATE_LIMIT invalid + if self.DEFAULT_TIMEZONE not in pytz.all_timezones_set: + raise ValueError(f'Invalid default timezone: {self.DEFAULT_TIMEZONE}') + + def __getattr__(self, name): + try: + return self.data[name] + except KeyError: + raise self._exc('no such setting: ' + name) + + def __setattr__(self, key, value): + raise AttributeError('cannot change config at runtime') + + def __delattr__(self, key): + raise AttributeError('cannot change config at runtime') + + + + +## ... source file continues with no further g examples... + +``` + + +## Example 9 from tedivms-flask +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + +[**tedivms-flask / app / extensions / ldap.py**](https://github.com/tedivm/tedivms-flask/blob/master/app/extensions/ldap.py) + +```python +# ldap.py + +~~from flask import current_app, g +from flask_login import current_user +from flask_user import UserManager +from flask_user.forms import LoginForm +from flask_user.translation_utils import lazy_gettext as _ # map _() to lazy_gettext() + +import datetime +from ldap3 import Server, Connection, ALL +from app import db +from app.models import user_models + + +def authenticate(user, password): + s = Server(current_app.config['LDAP_HOST'], get_info=ALL) # define an unsecure LDAP server, requesting info on DSE and schema + + user_dn = get_dn_from_user(user) + c = Connection(current_app.config['LDAP_HOST'], user=user_dn, password=password) + + if not c.bind(): + print('Unable to bind user %s' % (user_dn)) + return False + + return True + + + + +## ... source file abbreviated to get to g examples ... + + + email_attribute = current_app.config.get('LDAP_EMAIL_ATTRIBUTE', False) + if not email_attribute: + return False + conn = get_bound_connection() + user_search = get_dn_from_user(user) + user_object = '(objectclass=%s)' % (current_app.config['LDAP_USER_OBJECT_CLASS'],) + conn.search(user_search, user_object, attributes=[email_attribute]) + if len(conn.entries) < 1: + return False + return getattr(conn.entries[0], email_attribute, False)[0] + + +def user_in_group(user, group): + conn = get_bound_connection() + group_search = get_dn_from_group(group) + group_object = '(objectclass=%s)' % (current_app.config['LDAP_GROUP_OBJECT_CLASS'],) + conn.search(group_search, group_object, attributes=['memberUid']) + if len(conn.entries) < 1: + return False + members = conn.entries[0].memberUid + return user in members + + +def get_bound_connection(): +~~ if 'ldap_connection' in g: +~~ return g.ldap_connection + server = Server(current_app.config['LDAP_HOST'], get_info=ALL) # define an unsecure LDAP server, requesting info on DSE and schema +~~ g.ldap_connection = Connection(server, current_app.config['LDAP_BIND_DN'], current_app.config['LDAP_BIND_PASSWORD'], auto_bind=True) +~~ return g.ldap_connection + + +def get_dn_from_user(user): + return "%s=%s,%s" % (current_app.config['LDAP_USERNAME_ATTRIBUTE'], user, current_app.config['LDAP_USER_BASE'] ) + + +def get_dn_from_group(group): + return '%s=%s,%s' % (current_app.config['LDAP_GROUP_ATTRIBUTE'], group, current_app.config['LDAP_GROUP_BASE']) + + +class TedivmLoginForm(LoginForm): + + def validate_user(self): + user_manager = current_app.user_manager + if current_app.config.get('USER_LDAP', False): + if not authenticate(self.username.data, self.password.data): + return False + user = user_manager.db_manager.find_user_by_username(self.username.data) + if not user: + email = get_user_email(self.username.data) + if not email: + email = None + + user = user_models.User(username=self.username.data, +def get_user_email(user): + + +## ... source file continues with no further g examples... + +``` + diff --git a/content/pages/examples/flask/flask-globals-request.markdown b/content/pages/examples/flask/flask-globals-request.markdown new file mode 100644 index 000000000..be097b278 --- /dev/null +++ b/content/pages/examples/flask/flask-globals-request.markdown @@ -0,0 +1,3674 @@ +title: flask.globals request Example Code +category: page +slug: flask-globals-request-examples +sortorder: 500021016 +toc: False +sidebartitle: flask.globals request +meta: Python example code that shows how to use the request callable from the flask.globals module of the Flask project. + + +[request](https://github.com/pallets/flask/blob/master/src/flask/globals.py) +is function in [Flask](/flask.html)'s `flask.globals` module and is an +instance of +[LocalProxy](https://github.com/pallets/werkzeug/blob/master/src/werkzeug/local.py) +from the [Werkzeug](https://werkzeug.palletsprojects.com/en/1.0.x/) library. +`request` stores data about the active HTTP request and can be used to access +data about that request. + +Note that `request` is typically imported directly from `flask` instead of +from `flask.globals`, even though it is defined within the `globals` module. +It's the same import, just less characters to type when you import it +from `flask`. + +current_app, +g, +and session +are several other callables with code examples from the same `flask.globals` package. + +## Example 1 from Braintree Flask app +[Braintree's Flask example payments app](https://github.com/braintree/braintree_flask_example) +demonstrates how to incorporate this payment provider's +[API](/application-programming-interfaces.html) into your +[Flask](/flask.html) [web application](/web-development.html). +The code is open sourced under the +[MIT license](https://github.com/braintree/braintree_flask_example/blob/master/LICENSE). + +[**Braintree Flask app / app.py**](https://github.com/braintree/braintree_flask_example/blob/master/././app.py) + +```python +# app.py +~~from flask import Flask, redirect, url_for, render_template, request, flash + +import os +from os.path import join, dirname +from dotenv import load_dotenv +import braintree +from gateway import generate_client_token, transact, find_transaction + +load_dotenv() + +app = Flask(__name__) +app.secret_key = os.environ.get('APP_SECRET_KEY') + +PORT = int(os.environ.get('PORT', 4567)) + +TRANSACTION_SUCCESS_STATUSES = [ + braintree.Transaction.Status.Authorized, + braintree.Transaction.Status.Authorizing, + braintree.Transaction.Status.Settled, + braintree.Transaction.Status.SettlementConfirmed, + braintree.Transaction.Status.SettlementPending, + braintree.Transaction.Status.Settling, + braintree.Transaction.Status.SubmittedForSettlement +] + + + +## ... source file abbreviated to get to request examples ... + + + client_token = generate_client_token() + return render_template('checkouts/new.html', client_token=client_token) + +@app.route('/checkouts/', methods=['GET']) +def show_checkout(transaction_id): + transaction = find_transaction(transaction_id) + result = {} + if transaction.status in TRANSACTION_SUCCESS_STATUSES: + result = { + 'header': 'Sweet Success!', + 'icon': 'success', + 'message': 'Your test transaction has been successfully processed. See the Braintree API response and try again.' + } + else: + result = { + 'header': 'Transaction Failed', + 'icon': 'fail', + 'message': 'Your test transaction has a status of ' + transaction.status + '. See the Braintree API response and try again.' + } + + return render_template('checkouts/show.html', transaction=transaction, result=result) + +@app.route('/checkouts', methods=['POST']) +def create_checkout(): + result = transact({ +~~ 'amount': request.form['amount'], +~~ 'payment_method_nonce': request.form['payment_method_nonce'], + 'options': { + "submit_for_settlement": True + } + }) + + if result.is_success or result.transaction: + return redirect(url_for('show_checkout',transaction_id=result.transaction.id)) + else: + for x in result.errors.deep_errors: flash('Error: %s: %s' % (x.code, x.message)) + return redirect(url_for('new_checkout')) + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=PORT, debug=True) + + + +## ... source file continues with no further request examples... + +``` + + +## Example 2 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / tests / test_themes.py**](https://github.com/CTFd/CTFd/blob/master/./tests/test_themes.py) + +```python +# test_themes.py + +import os +import shutil + +import pytest +~~from flask import render_template, render_template_string, request +from jinja2.exceptions import TemplateNotFound +from jinja2.sandbox import SecurityError +from werkzeug.test import Client + +from CTFd.config import TestingConfig +from CTFd.utils import get_config, set_config +from tests.helpers import create_ctfd, destroy_ctfd, gen_user, login_as_user + + +def test_themes_run_in_sandbox(): + app = create_ctfd() + with app.app_context(): + try: + app.jinja_env.from_string( + "{{ ().__class__.__bases__[0].__subclasses__()[40]('./test_utils.py').read() }}" + ).render() + except SecurityError: + pass + except Exception as e: + raise e + destroy_ctfd(app) + + +def test_themes_cant_access_configpy_attributes(): + + +## ... source file abbreviated to get to request examples ... + + + r = client.post("/setup", data=data) + assert r.status_code == 302 + assert r.location == "http://localhost/ctf/" + + c = Client(app) + app_iter, status, headers = c.get("/") + headers = dict(headers) + assert status == "302 FOUND" + assert headers["Location"] == "http://localhost/ctf/" + + r = client.get("/challenges") + assert r.status_code == 200 + assert "Challenges" in r.get_data(as_text=True) + + r = client.get("/scoreboard") + assert r.status_code == 200 + assert "Scoreboard" in r.get_data(as_text=True) + destroy_ctfd(app) + + +def test_that_request_path_hijacking_works_properly(): + app = create_ctfd(setup=False, application_root="/ctf") + assert app.request_class.__name__ == "CTFdRequest" + with app.app_context(): + with app.test_request_context("/challenges"): +~~ assert request.path == "/ctf/challenges" + destroy_ctfd(app) + + app = create_ctfd() + assert app.request_class.__name__ == "CTFdRequest" + with app.app_context(): + with app.test_request_context("/challenges"): +~~ assert request.path == "/challenges" + + from flask import Flask + + test_app = Flask("test") + assert test_app.request_class.__name__ == "Request" + with test_app.test_request_context("/challenges"): +~~ assert request.path == "/challenges" + destroy_ctfd(app) + + +def test_theme_fallback_config(): + + class ThemeFallbackConfig(TestingConfig): + THEME_FALLBACK = False + + app = create_ctfd(config=ThemeFallbackConfig) + try: + os.mkdir(os.path.join(app.root_path, "themes", "foo_fallback")) + except OSError: + pass + + with app.app_context(): + app.config["THEME_FALLBACK"] = False + set_config("ctf_theme", "foo_fallback") + assert app.config["THEME_FALLBACK"] == False + with app.test_client() as client: + try: + r = client.get("/") + except TemplateNotFound: + pass + try: + + +## ... source file continues with no further request examples... + +``` + + +## Example 3 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / urltools.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/./urltools.py) + +```python +# urltools.py +import re + +~~from flask import request + + +class Stack(object): + + def __init__(self, list=None, size=5): + self.size = size + self.data = list or [] + + def push(self, item): + if self.data: + if item != self.data[len(self.data) - 1]: + self.data.append(item) + else: + self.data.append(item) + if len(self.data) > self.size: + self.data.pop(0) + + def pop(self): + if len(self.data) == 0: + return None + return self.data.pop(len(self.data) - 1) + + def to_json(self): + return self.data + + +def get_group_by_args(): +~~ group_by = request.args.get("group_by") + if not group_by: + group_by = "" + return group_by + + +def get_page_args(): + pages = {} +~~ for arg in request.args: + re_match = re.findall("page_(.*)", arg) + if re_match: + pages[re_match[0]] = int(request.args.get(arg)) + return pages + + +def get_page_size_args(): + page_sizes = {} +~~ for arg in request.args: + re_match = re.findall("psize_(.*)", arg) + if re_match: + page_sizes[re_match[0]] = int(request.args.get(arg)) + return page_sizes + + +def get_order_args(): + orders = {} +~~ for arg in request.args: + re_match = re.findall("_oc_(.*)", arg) + if re_match: +~~ order_direction = request.args.get("_od_" + re_match[0]) + if order_direction in ("asc", "desc"): + orders[re_match[0]] = (request.args.get(arg), order_direction) + return orders + + +def get_filter_args(filters): + filters.clear_filters() +~~ for arg in request.args: + re_match = re.findall("_flt_(\d)_(.*)", arg) + if re_match: + filters.add_filter_index( +~~ re_match[0][1], int(re_match[0][0]), request.args.get(arg) + ) + + + +## ... source file continues with no further request examples... + +``` + + +## Example 4 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / management / views.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/management/views.py) + +```python +# views.py +import logging +import sys + +from celery import __version__ as celery_version +from flask import __version__ as flask_version +~~from flask import (Blueprint, current_app, flash, jsonify, redirect, request, + url_for) +from flask.views import MethodView +from flask_allows import Not, Permission +from flask_babelplus import gettext as _ +from flask_login import current_user, login_fresh +from pluggy import HookimplMarker + +from flaskbb import __version__ as flaskbb_version +from flaskbb.extensions import allows, celery, db +from flaskbb.forum.forms import UserSearchForm +from flaskbb.forum.models import Category, Forum, Post, Report, Topic +from flaskbb.management.forms import (AddForumForm, AddGroupForm, AddUserForm, + CategoryForm, EditForumForm, + EditGroupForm, EditUserForm) +from flaskbb.management.models import Setting, SettingsGroup +from flaskbb.plugins.models import PluginRegistry, PluginStore +from flaskbb.plugins.utils import validate_plugin +from flaskbb.user.models import Group, Guest, User +from flaskbb.utils.forms import populate_settings_dict, populate_settings_form +from flaskbb.utils.helpers import (get_online_users, register_view, + render_template, redirect_or_next, + time_diff, time_utcnow, FlashAndRedirect) +from flaskbb.utils.requirements import (CanBanUser, CanEditUser, IsAdmin, + IsAtleastModerator, + + +## ... source file abbreviated to get to request examples ... + + + flash(_("Settings saved."), "success") + + return render_template( + "management/settings.html", + form=form, + all_groups=all_groups, + all_plugins=all_plugins, + active_nav=active_nav + ) + + +class ManageUsers(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to manage users"), + level="danger", + endpoint="management.overview" + ) + ) + ] + form = UserSearchForm + + def get(self): +~~ page = request.args.get('page', 1, type=int) + form = self.form() + + users = User.query.order_by(User.id.asc()).paginate( + page, flaskbb_config['USERS_PER_PAGE'], False + ) + + return render_template( + 'management/users.html', users=users, search_form=form + ) + + def post(self): +~~ page = request.args.get('page', 1, type=int) + form = self.form() + + if form.validate(): + users = form.get_results().\ + paginate(page, flaskbb_config['USERS_PER_PAGE'], False) + return render_template( + 'management/users.html', users=users, search_form=form + ) + + users = User.query.order_by(User.id.asc()).paginate( + page, flaskbb_config['USERS_PER_PAGE'], False + ) + + return render_template( + 'management/users.html', users=users, search_form=form + ) + + +class EditUser(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, CanEditUser, + on_fail=FlashAndRedirect( + message=_("You are not allowed to manage users"), + + +## ... source file abbreviated to get to request examples ... + + + user.password = form.password.data + + user.save(groups=form.secondary_groups.data) + + flash(_('User updated.'), 'success') + return redirect(url_for('management.edit_user', user_id=user.id)) + + return render_template( + 'management/user_form.html', form=form, title=_('Edit User') + ) + + +class DeleteUser(MethodView): + decorators = [ + allows.requires( + IsAdmin, + on_fail=FlashAndRedirect( + message=_("You are not allowed to manage users"), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def post(self, user_id=None): +~~ if request.get_json() is not None: +~~ ids = request.get_json().get("ids") + if not ids: + return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + data = [] + for user in User.query.filter(User.id.in_(ids)).all(): + if current_user.id == user.id: + continue + + if user.delete(): + data.append( + { + "id": user.id, + "type": "delete", + "reverse": False, + "reverse_name": None, + "reverse_url": None + } + ) + + return jsonify( + message=f"{len(data)} users deleted.", + + +## ... source file abbreviated to get to request examples ... + + + form = self.form() + if form.validate_on_submit(): + form.save() + flash(_('User added.'), 'success') + return redirect(url_for('management.users')) + + return render_template( + 'management/user_form.html', form=form, title=_('Add User') + ) + + +class BannedUsers(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to manage users"), + level="danger", + endpoint="management.overview" + ) + ) + ] + form = UserSearchForm + + def get(self): +~~ page = request.args.get('page', 1, type=int) + search_form = self.form() + + users = User.query.filter( + Group.banned == True, Group.id == User.primary_group_id + ).paginate(page, flaskbb_config['USERS_PER_PAGE'], False) + + return render_template( + 'management/banned_users.html', + users=users, + search_form=search_form + ) + + def post(self): +~~ page = request.args.get('page', 1, type=int) + search_form = self.form() + + users = User.query.filter( + Group.banned == True, Group.id == User.primary_group_id + ).paginate(page, flaskbb_config['USERS_PER_PAGE'], False) + + if search_form.validate(): + users = search_form.get_results().\ + paginate(page, flaskbb_config['USERS_PER_PAGE'], False) + + return render_template( + 'management/banned_users.html', + users=users, + search_form=search_form + ) + + return render_template( + 'management/banned_users.html', + users=users, + search_form=search_form + ) + + +class BanUser(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to manage users"), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def post(self, user_id=None): + if not Permission(CanBanUser, identity=current_user): + flash( + _("You do not have the permissions to ban this user."), + "danger" + ) + return redirect(url_for("management.overview")) + +~~ if request.get_json() is not None: +~~ ids = request.get_json().get("ids") + if not ids: + return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + + data = [] + users = User.query.filter(User.id.in_(ids)).all() + for user in users: + if (current_user.id == user.id or + Permission(IsAdmin, identity=user) and + Permission(Not(IsAdmin), current_user)): + continue + + elif user.ban(): + data.append({ + "id": user.id, + "type": "ban", + "reverse": "unban", + "reverse_name": _("Unban"), + "reverse_url": url_for("management.unban_user", user_id=user.id) + }) + + + +## ... source file abbreviated to get to request examples ... + + + return redirect_or_next(url_for("management.banned_users")) + + +class UnbanUser(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to manage users"), + level="danger", + endpoint="management.overview" + ) + + ) + ] + + def post(self, user_id=None): + + if not Permission(CanBanUser, identity=current_user): + flash( + _("You do not have the permissions to unban this user."), + "danger" + ) + return redirect(url_for("management.overview")) + +~~ if request.get_json() is not None: +~~ ids = request.get_json().get("ids") + if not ids: + return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + + data = [] + for user in User.query.filter(User.id.in_(ids)).all(): + if user.unban(): + data.append( + { + "id": user.id, + "type": "ban", + "reverse": "ban", + "reverse_name": _("Ban"), + "reverse_url": url_for("management.ban_user", + user_id=user.id) + } + ) + + return jsonify( + message=f"{len(data)} users unbanned.", + category="success", + + +## ... source file abbreviated to get to request examples ... + + + + user = User.query.filter_by(id=user_id).first_or_404() + + if user.unban(): + flash(_("User is now unbanned."), "success") + else: + flash(_("Could not unban user."), "danger") + + return redirect_or_next(url_for("management.users")) + + +class Groups(MethodView): + decorators = [ + allows.requires( + IsAdmin, + on_fail=FlashAndRedirect( + message=_("You are not allowed to modify groups."), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def get(self): + +~~ page = request.args.get("page", 1, type=int) + + groups = Group.query.\ + order_by(Group.id.asc()).\ + paginate(page, flaskbb_config['USERS_PER_PAGE'], False) + + return render_template("management/groups.html", groups=groups) + + +class AddGroup(MethodView): + decorators = [ + allows.requires( + IsAdmin, + on_fail=FlashAndRedirect( + message=_("You are not allowed to modify groups."), + level="danger", + endpoint="management.overview" + ) + ) + ] + form = AddGroupForm + + def get(self): + return render_template( + 'management/group_form.html', + + +## ... source file abbreviated to get to request examples ... + + + + if group.guest: + Guest.invalidate_cache() + + flash(_('Group updated.'), 'success') + return redirect(url_for('management.groups', group_id=group.id)) + + return render_template( + 'management/group_form.html', form=form, title=_('Edit Group') + ) + + +class DeleteGroup(MethodView): + decorators = [ + allows.requires( + IsAdmin, + on_fail=FlashAndRedirect( + message=_("You are not allowed to modify groups."), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def post(self, group_id=None): +~~ if request.get_json() is not None: +~~ ids = request.get_json().get("ids") + if not ids: + return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + + if not (set(ids) & set(["1", "2", "3", "4", "5", "6"])): + data = [] + for group in Group.query.filter(Group.id.in_(ids)).all(): + group.delete() + data.append( + { + "id": group.id, + "type": "delete", + "reverse": False, + "reverse_name": None, + "reverse_url": None + } + ) + + return jsonify( + message="{} groups deleted.".format(len(data)), + category="success", + + +## ... source file abbreviated to get to request examples ... + + + category = Category.query.filter_by(id=category_id).first_or_404() + + involved_users = User.query.filter( + Forum.category_id == category.id, Topic.forum_id == Forum.id, + Post.user_id == User.id + ).all() + + category.delete(involved_users) + flash(_("Category with all associated forums deleted."), "success") + return redirect(url_for("management.forums")) + + +class Reports(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to view reports."), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def get(self): +~~ page = request.args.get("page", 1, type=int) + reports = Report.query.\ + order_by(Report.id.asc()).\ + paginate(page, flaskbb_config['USERS_PER_PAGE'], False) + + return render_template("management/reports.html", reports=reports) + + +class UnreadReports(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to view reports."), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def get(self): +~~ page = request.args.get("page", 1, type=int) + reports = Report.query.\ + filter(Report.zapped == None).\ + order_by(Report.id.desc()).\ + paginate(page, flaskbb_config['USERS_PER_PAGE'], False) + + return render_template("management/reports.html", reports=reports) + + +class MarkReportRead(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to view reports."), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def post(self, report_id=None): + +~~ if request.get_json() is not None: +~~ ids = request.get_json().get("ids") + if not ids: + return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + data = [] + + for report in Report.query.filter(Report.id.in_(ids)).all(): + report.zapped_by = current_user.id + report.zapped = time_utcnow() + report.save() + data.append( + { + "id": report.id, + "type": "read", + "reverse": False, + "reverse_name": None, + "reverse_url": None + } + ) + + return jsonify( + message="{} reports marked as read.".format(len(data)), + + +## ... source file abbreviated to get to request examples ... + + + for report in reports: + report.zapped_by = current_user.id + report.zapped = time_utcnow() + report_list.append(report) + + db.session.add_all(report_list) + db.session.commit() + + flash(_("All reports were marked as read."), "success") + return redirect_or_next(url_for("management.reports")) + + +class DeleteReport(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to view reports."), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def post(self, report_id=None): +~~ if request.get_json() is not None: +~~ ids = request.get_json().get("ids") + if not ids: + return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + + data = [] + for report in Report.query.filter(Report.id.in_(ids)).all(): + if report.delete(): + data.append( + { + "id": report.id, + "type": "delete", + "reverse": False, + "reverse_name": None, + "reverse_url": None + } + ) + + return jsonify( + message="{} reports deleted.".format(len(data)), + category="success", + data=data, + + +## ... source file continues with no further request examples... + +``` + + +## Example 5 from flask-bones +[flask-bones](https://github.com/cburmeister/flask-bones) +([demo](http://flask-bones.herokuapp.com/)) +is large scale [Flask](/flask.html) example application built +with [Blueprints](https://flask.palletsprojects.com/en/1.1.x/blueprints/) +([example Blueprint code](/flask-blueprints-blueprint-examples.html)). +This project is provided as open source under the +[MIT license](https://github.com/cburmeister/flask-bones/blob/master/LICENSE). + +[**flask-bones / app / __init__.py**](https://github.com/cburmeister/flask-bones/blob/master/app/./__init__.py) + +```python +# __init__.py +import time + +~~from flask import Flask, g, render_template, request +import arrow +import requests + +from app import config +from app.assets import assets +from app.auth import auth +from app.commands import create_db, drop_db, populate_db, recreate_db +from app.database import db +from app.extensions import lm, travis, mail, migrate, bcrypt, babel, rq, limiter +from app.user import user +from app.utils import url_for_other_page + + +def create_app(config=config.base_config): + app = Flask(__name__) + app.config.from_object(config) + + register_extensions(app) + register_blueprints(app) + register_errorhandlers(app) + register_jinja_env(app) + register_commands(app) + + def get_locale(): +~~ return request.accept_languages.best_match(config.SUPPORTED_LOCALES) + + if babel.locale_selector_func is None: + babel.locale_selector_func = get_locale + + @app.before_request + def before_request(): + g.request_start_time = time.time() + g.request_time = lambda: '%.5fs' % (time.time() - g.request_start_time) +~~ g.pjax = 'X-PJAX' in request.headers + + @app.route('/', methods=['GET']) + def index(): + return render_template('index.html') + + return app + + +def register_commands(app): + for command in [create_db, drop_db, populate_db, recreate_db]: + app.cli.command()(command) + + +def register_extensions(app): + travis.init_app(app) + db.init_app(app) + lm.init_app(app) + mail.init_app(app) + bcrypt.init_app(app) + assets.init_app(app) + babel.init_app(app) + rq.init_app(app) + migrate.init_app(app, db) + limiter.init_app(app) + + +## ... source file continues with no further request examples... + +``` + + +## Example 6 from flask-bookshelf +[flask-bookshelf](https://github.com/damyanbogoev/flask-bookshelf) is the +example [Flask](/flask.html) application that developers create when +going through +[this Flask series of blog posts](https://damyanon.net/tags/flask-series/). + +[**flask-bookshelf / bookshelf / admin / controllers.py**](https://github.com/damyanbogoev/flask-bookshelf/blob/master/bookshelf/admin/controllers.py) + +```python +# controllers.py +from sqlalchemy import exc +from flask import Blueprint, render_template, flash +~~from flask import current_app, redirect, request, url_for +from flask_security.decorators import roles_required +from bookshelf.admin.forms.author_forms import CreateAuthorForm +from bookshelf.cache import cache +from bookshelf.data.models import Author, db + + +admin = Blueprint("admin", __name__, template_folder="templates") + + +@admin.route("/") +@roles_required("admin") +def index(): + return render_template("admin_index.htm") + + +@admin.route("/author/create", methods=["GET", "POST"]) +@roles_required("admin") +def create_author(): + form = CreateAuthorForm(request.form) +~~ if request.method == "POST" and form.validate(): + names = form.names.data + current_app.logger.info("Adding a new author %s.", (names)) + author = Author(names) + + try: + db.session.add(author) + db.session.commit() + cache.clear() + flash("Author successfully created.") + except exc.SQLAlchemyError as e: + flash("Author was not created.") + current_app.logger.error(e) + + return redirect(url_for("admin.create_author")) + + return redirect(url_for("main.display_authors")) + + return render_template("create_author.htm", form=form) + + + +## ... source file continues with no further request examples... + +``` + + +## Example 7 from flask-debugtoolbar +[Flask Debug-toolbar](https://github.com/flask-debugtoolbar/flask-debugtoolbar) +([documentation](https://flask-debugtoolbar.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/Flask-DebugToolbar/)) +is a [Flask](/flask.html) conversion of the popular +[Django Debug Toolbar](https://github.com/jazzband/django-debug-toolbar) +project. This extension creates a sidebar with useful debugging +information when you are running a Flask application in development +mode. The project is provided as open source under +[this license](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/LICENSE). + +[**flask-debugtoolbar / flask_debugtoolbar / __init__.py**](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/flask_debugtoolbar/./__init__.py) + +```python +# __init__.py +import os +import warnings + +~~from flask import Blueprint, current_app, request, g, send_from_directory, url_for +from flask.globals import _request_ctx_stack +from jinja2 import Environment, PackageLoader +from werkzeug.urls import url_quote_plus + +from flask_debugtoolbar.compat import iteritems +from flask_debugtoolbar.toolbar import DebugToolbar +from flask_debugtoolbar.utils import decode_text, gzip_compress, gzip_decompress + +try: + from importlib.metadata import version + + __version__ = version("Flask-DebugToolbar") +except ImportError: + import pkg_resources + + __version__ = pkg_resources.get_distribution("Flask-DebugToolbar").version + + +module = Blueprint('debugtoolbar', __name__) + + +def replace_insensitive(string, target, replacement): + no_case = string.lower() + index = no_case.rfind(target.lower()) + + +## ... source file abbreviated to get to request examples ... + + + 'flask_debugtoolbar.panels.route_list.RouteListDebugPanel', + 'flask_debugtoolbar.panels.profiler.ProfilerDebugPanel', + 'flask_debugtoolbar.panels.g.GDebugPanel', + ), + } + + def dispatch_request(self): + req = _request_ctx_stack.top.request + app = current_app + + if req.routing_exception is not None: + app.raise_routing_exception(req) + + rule = req.url_rule + + if getattr(rule, 'provide_automatic_options', False) \ + and req.method == 'OPTIONS': + return app.make_default_options_response() + + view_func = app.view_functions[rule.endpoint] + view_func = self.process_view(app, view_func, req.view_args) + + return view_func(**req.view_args) + + def _show_toolbar(self): +~~ if request.blueprint == 'debugtoolbar': + return False + + hosts = current_app.config['DEBUG_TB_HOSTS'] +~~ if hosts and request.remote_addr not in hosts: + return False + + return True + + def send_static_file(self, filename): + return send_from_directory(self._static_dir, filename) + + def process_request(self): + g.debug_toolbar = self + + if not self._show_toolbar(): + return + +~~ real_request = request._get_current_object() + + self.debug_toolbars[real_request] = ( + DebugToolbar(real_request, self.jinja_env)) + + for panel in self.debug_toolbars[real_request].panels: + panel.process_request(real_request) + + def process_view(self, app, view_func, view_kwargs): +~~ real_request = request._get_current_object() + try: + toolbar = self.debug_toolbars[real_request] + except KeyError: + return view_func + + for panel in toolbar.panels: + new_view = panel.process_view(real_request, view_func, view_kwargs) + if new_view: + view_func = new_view + + return view_func + + def process_response(self, response): +~~ real_request = request._get_current_object() + if real_request not in self.debug_toolbars: + return response + + if current_app.config['DEBUG_TB_INTERCEPT_REDIRECTS']: + if response.status_code in self._redirect_codes: + redirect_to = response.location + redirect_code = response.status_code + if redirect_to: + content = self.render('redirect.html', { + 'redirect_to': redirect_to, + 'redirect_code': redirect_code + }) + response.content_length = len(content) + response.location = None + response.response = [content] + response.status_code = 200 + + if not (response.status_code == 200 and + response.is_sequence and + response.headers['content-type'].startswith('text/html')): + return response + + if 'gzip' in response.headers.get('Content-Encoding', ''): + response_html = gzip_decompress(response.data).decode(response.charset) + + +## ... source file continues with no further request examples... + +``` + + +## Example 8 from flaskex +[Flaskex](https://github.com/anfederico/Flaskex) is a working example +[Flask](/flask.html) web application intended as a base to build your +own applications upon. The application comes with pre-built sign up, log in +and related screens, as well as a database backend. Flaskex is provided +as open source under the +[MIT license](https://github.com/anfederico/Flaskex/blob/master/LICENSE.txt). + +[**flaskex / app.py**](https://github.com/anfederico/Flaskex/blob/master/././app.py) + +```python +# app.py + +from scripts import tabledef +from scripts import forms +from scripts import helpers +~~from flask import Flask, redirect, url_for, render_template, request, session +import json +import sys +import os + +app = Flask(__name__) +app.secret_key = os.urandom(12) # Generic key for dev purposes only + + +@app.route('/', methods=['GET', 'POST']) +def login(): + if not session.get('logged_in'): + form = forms.LoginForm(request.form) +~~ if request.method == 'POST': +~~ username = request.form['username'].lower() +~~ password = request.form['password'] + if form.validate(): + if helpers.credentials_valid(username, password): + session['logged_in'] = True + session['username'] = username + return json.dumps({'status': 'Login successful'}) + return json.dumps({'status': 'Invalid user/pass'}) + return json.dumps({'status': 'Both fields required'}) + return render_template('login.html', form=form) + user = helpers.get_user() + return render_template('home.html', user=user) + + +@app.route("/logout") +def logout(): + session['logged_in'] = False + return redirect(url_for('login')) + + +@app.route('/signup', methods=['GET', 'POST']) +def signup(): + if not session.get('logged_in'): + form = forms.LoginForm(request.form) +~~ if request.method == 'POST': +~~ username = request.form['username'].lower() + password = helpers.hash_password(request.form['password']) +~~ email = request.form['email'] + if form.validate(): + if not helpers.username_taken(username): + helpers.add_user(username, password, email) + session['logged_in'] = True + session['username'] = username + return json.dumps({'status': 'Signup successful'}) + return json.dumps({'status': 'Username taken'}) + return json.dumps({'status': 'User/Pass required'}) + return render_template('login.html', form=form) + return redirect(url_for('login')) + + +@app.route('/settings', methods=['GET', 'POST']) +def settings(): + if session.get('logged_in'): +~~ if request.method == 'POST': +~~ password = request.form['password'] + if password != "": + password = helpers.hash_password(password) +~~ email = request.form['email'] + helpers.change_user(password=password, email=email) + return json.dumps({'status': 'Saved'}) + user = helpers.get_user() + return render_template('settings.html', user=user) + return redirect(url_for('login')) + + +if __name__ == "__main__": + app.run(debug=True, use_reloader=True, host="0.0.0.0") + + + +## ... source file continues with no further request examples... + +``` + + +## Example 9 from Flask-HTTPAuth +[Flask-HTTPAuth](https://github.com/miguelgrinberg/Flask-HTTPAuth) +([documentation](https://flask-httpauth.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/Flask-HTTPAuth/)) +is a [Flask](/flask.html) framework extension that creates +Basic and Digest HTTP authentication for routes. This project +is primarily built and maintained by +[Miguel Grinberg](https://blog.miguelgrinberg.com/). It is provided +as open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/LICENSE). + +[**Flask-HTTPAuth / flask_httpauth.py**](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/././flask_httpauth.py) + +```python +# flask_httpauth.py + +from base64 import b64decode +from functools import wraps +from hashlib import md5 +from random import Random, SystemRandom +~~from flask import request, make_response, session, g, Response +from werkzeug.datastructures import Authorization +from werkzeug.security import safe_str_cmp + +__version__ = '4.2.1dev' + + +class HTTPAuth(object): + def __init__(self, scheme=None, realm=None, header=None): + self.scheme = scheme + self.realm = realm or "Authentication Required" + self.header = header + self.get_password_callback = None + self.get_user_roles_callback = None + self.auth_error_callback = None + + def default_get_password(username): + return None + + def default_auth_error(status): + return "Unauthorized Access", status + + self.get_password(default_get_password) + self.error_handler(default_auth_error) + + + +## ... source file abbreviated to get to request examples ... + + + + def get_user_roles(self, f): + self.get_user_roles_callback = f + return f + + def error_handler(self, f): + @wraps(f) + def decorated(*args, **kwargs): + res = f(*args, **kwargs) + check_status_code = not isinstance(res, (tuple, Response)) + res = make_response(res) + if check_status_code and res.status_code == 200: + res.status_code = 401 + if 'WWW-Authenticate' not in res.headers.keys(): + res.headers['WWW-Authenticate'] = self.authenticate_header() + return res + self.auth_error_callback = decorated + return decorated + + def authenticate_header(self): + return '{0} realm="{1}"'.format(self.scheme, self.realm) + + def get_auth(self): + auth = None + if self.header is None or self.header == 'Authorization': +~~ auth = request.authorization +~~ if auth is None and 'Authorization' in request.headers: + try: +~~ auth_type, token = request.headers['Authorization'].split( + None, 1) + auth = Authorization(auth_type, {'token': token}) + except (ValueError, KeyError): + pass +~~ elif self.header in request.headers: + auth = Authorization(self.scheme, +~~ {'token': request.headers[self.header]}) + + if auth is not None and auth.type.lower() != self.scheme.lower(): + auth = None + + return auth + + def get_auth_password(self, auth): + password = None + + if auth and auth.username: + password = self.get_password_callback(auth.username) + + return password + + def authorize(self, role, user, auth): + if role is None: + return True + if isinstance(role, (list, tuple)): + roles = role + else: + roles = [role] + if user is True: + user = auth + if self.get_user_roles_callback is None: # pragma: no cover + + +## ... source file abbreviated to get to request examples ... + + + if user_roles is None: + user_roles = {} + elif not isinstance(user_roles, (list, tuple)): + user_roles = {user_roles} + else: + user_roles = set(user_roles) + for role in roles: + if isinstance(role, (list, tuple)): + role = set(role) + if role & user_roles == role: + return True + elif role in user_roles: + return True + + def login_required(self, f=None, role=None, optional=None): + if f is not None and \ + (role is not None or optional is not None): # pragma: no cover + raise ValueError( + 'role and optional are the only supported arguments') + + def login_required_internal(f): + @wraps(f) + def decorated(*args, **kwargs): + auth = self.get_auth() + +~~ if request.method != 'OPTIONS': # pragma: no cover + password = self.get_auth_password(auth) + + status = None + user = self.authenticate(auth, password) + if user in (False, None): + status = 401 + elif not self.authorize(role, user, auth): + status = 403 + if not optional and status: +~~ request.data + try: + return self.auth_error_callback(status) + except TypeError: + return self.auth_error_callback() + + g.flask_httpauth_user = user if user is not True \ + else auth.username if auth else None + return f(*args, **kwargs) + return decorated + + if f: + return login_required_internal(f) + return login_required_internal + + def username(self): + auth = self.get_auth() + if not auth: + return "" + return auth.username + + def current_user(self): + if hasattr(g, 'flask_httpauth_user'): + return g.flask_httpauth_user + + +class HTTPBasicAuth(HTTPAuth): + def __init__(self, scheme=None, realm=None): + super(HTTPBasicAuth, self).__init__(scheme or 'Basic', realm) + + self.hash_password_callback = None + self.verify_password_callback = None + + def hash_password(self, f): + self.hash_password_callback = f + return f + + def verify_password(self, f): + self.verify_password_callback = f + return f + + def get_auth(self): + header = self.header or 'Authorization' +~~ if header not in request.headers: + return None +~~ value = request.headers[header].encode('utf-8') + try: + scheme, credentials = value.split(b' ', 1) + username, password = b64decode(credentials).split(b':', 1) + except (ValueError, TypeError): + return None + try: + username = username.decode('utf-8') + password = password.decode('utf-8') + except UnicodeDecodeError: + username = None + password = None + return Authorization( + scheme, {'username': username, 'password': password}) + + def authenticate(self, auth, stored_password): + if auth: + username = auth.username + client_password = auth.password + else: + username = "" + client_password = "" + if self.verify_password_callback: + return self.verify_password_callback(username, client_password) + if not auth: + + +## ... source file abbreviated to get to request examples ... + + + a1 = username + ":" + self.realm + ":" + password + a1 = a1.encode('utf-8') + return md5(a1).hexdigest() + + def authenticate_header(self): + nonce = self.get_nonce() + opaque = self.get_opaque() + return '{0} realm="{1}",nonce="{2}",opaque="{3}"'.format( + self.scheme, self.realm, nonce, + opaque) + + def authenticate(self, auth, stored_password_or_ha1): + if not auth or not auth.username or not auth.realm or not auth.uri \ + or not auth.nonce or not auth.response \ + or not stored_password_or_ha1: + return False + if not(self.verify_nonce_callback(auth.nonce)) or \ + not(self.verify_opaque_callback(auth.opaque)): + return False + if self.use_ha1_pw: + ha1 = stored_password_or_ha1 + else: + a1 = auth.username + ":" + auth.realm + ":" + \ + stored_password_or_ha1 + ha1 = md5(a1.encode('utf-8')).hexdigest() +~~ a2 = request.method + ":" + auth.uri + ha2 = md5(a2.encode('utf-8')).hexdigest() + a3 = ha1 + ":" + auth.nonce + ":" + ha2 + response = md5(a3.encode('utf-8')).hexdigest() + return safe_str_cmp(response, auth.response) + + +class HTTPTokenAuth(HTTPAuth): + def __init__(self, scheme='Bearer', realm=None, header=None): + super(HTTPTokenAuth, self).__init__(scheme, realm, header) + + self.verify_token_callback = None + + def verify_token(self, f): + self.verify_token_callback = f + return f + + def authenticate(self, auth, stored_password): + if auth: + token = auth['token'] + else: + token = "" + if self.verify_token_callback: + return self.verify_token_callback(token) + + +class MultiAuth(object): + def __init__(self, main_auth, *args): + self.main_auth = main_auth + self.additional_auth = args + + def login_required(self, f=None, role=None, optional=None): + if f is not None and \ + (role is not None or optional is not None): # pragma: no cover + raise ValueError( + 'role and optional are the only supported arguments') + + def login_required_internal(f): + @wraps(f) + def decorated(*args, **kwargs): + selected_auth = None +~~ if 'Authorization' in request.headers: + try: +~~ scheme, creds = request.headers[ + 'Authorization'].split(None, 1) + except ValueError: + pass + else: + for auth in self.additional_auth: + if auth.scheme == scheme: + selected_auth = auth + break + if selected_auth is None: + selected_auth = self.main_auth + return selected_auth.login_required(role=role, + optional=optional + )(f)(*args, **kwargs) + return decorated + + if f: + return login_required_internal(f) + return login_required_internal + + def current_user(self): + if hasattr(g, 'flask_httpauth_user'): # pragma: no cover + return g.flask_httpauth_user + + + +## ... source file continues with no further request examples... + +``` + + +## Example 10 from flask-login +[Flask-Login](https://github.com/maxcountryman/flask-login) +([project documentation](https://flask-login.readthedocs.io/en/latest/) +and [PyPI package](https://pypi.org/project/Flask-Login/)) +is a [Flask](/flask.html) extension that provides user session +management, which handles common tasks such as logging in +and out of a [web application](/web-development.html) and +managing associated user session data. Flask-Login is +open sourced under the +[MIT license](https://github.com/maxcountryman/flask-login/blob/master/LICENSE). + +[**flask-login / flask_login / utils.py**](https://github.com/maxcountryman/flask-login/blob/master/flask_login/./utils.py) + +```python +# utils.py + + +import hmac +from hashlib import sha512 +from functools import wraps +from werkzeug.local import LocalProxy +from werkzeug.security import safe_str_cmp +from werkzeug.urls import url_decode, url_encode + +~~from flask import (_request_ctx_stack, current_app, request, session, url_for, + has_request_context) + +from ._compat import text_type, urlparse, urlunparse +from .config import COOKIE_NAME, EXEMPT_METHODS +from .signals import user_logged_in, user_logged_out, user_login_confirmed + + +current_user = LocalProxy(lambda: _get_user()) + + +def encode_cookie(payload, key=None): + return u'{0}|{1}'.format(payload, _cookie_digest(payload, key=key)) + + +def decode_cookie(cookie, key=None): + try: + payload, digest = cookie.rsplit(u'|', 1) + if hasattr(digest, 'decode'): + digest = digest.decode('ascii') # pragma: no cover + except ValueError: + return + + if safe_str_cmp(_cookie_digest(payload, key=key), digest): + return payload + + +def make_next_param(login_url, current_url): + l_url = urlparse(login_url) + c_url = urlparse(current_url) + + if (not l_url.scheme or l_url.scheme == c_url.scheme) and \ + (not l_url.netloc or l_url.netloc == c_url.netloc): + return urlunparse(('', '', c_url.path, c_url.params, c_url.query, '')) + return current_url + + +def expand_login_view(login_view): + if login_view.startswith(('https://', 'http://', '/')): + return login_view + else: +~~ if request.view_args is None: + return url_for(login_view) + else: + return url_for(login_view, **request.view_args) + + +def login_url(login_view, next_url=None, next_field='next'): + base = expand_login_view(login_view) + + if next_url is None: + return base + + parsed_result = urlparse(base) + md = url_decode(parsed_result.query) + md[next_field] = make_next_param(base, next_url) + netloc = current_app.config.get('FORCE_HOST_FOR_REDIRECTS') or \ + parsed_result.netloc + parsed_result = parsed_result._replace(netloc=netloc, + query=url_encode(md, sort=True)) + return urlunparse(parsed_result) + + +def login_fresh(): + return session.get('_fresh', False) + + + +## ... source file abbreviated to get to request examples ... + + + duration.days * 24 * 3600) * + 10**6) / 10.0**6 + except AttributeError: + raise Exception('duration must be a datetime.timedelta, ' + 'instead got: {0}'.format(duration)) + + current_app.login_manager._update_request_context_with_user(user) + user_logged_in.send(current_app._get_current_object(), user=_get_user()) + return True + + +def logout_user(): + + user = _get_user() + + if '_user_id' in session: + session.pop('_user_id') + + if '_fresh' in session: + session.pop('_fresh') + + if '_id' in session: + session.pop('_id') + + cookie_name = current_app.config.get('REMEMBER_COOKIE_NAME', COOKIE_NAME) +~~ if cookie_name in request.cookies: + session['_remember'] = 'clear' + if '_remember_seconds' in session: + session.pop('_remember_seconds') + + user_logged_out.send(current_app._get_current_object(), user=user) + + current_app.login_manager._update_request_context_with_user() + return True + + +def confirm_login(): + session['_fresh'] = True + session['_id'] = current_app.login_manager._session_identifier_generator() + user_login_confirmed.send(current_app._get_current_object()) + + +def login_required(func): + @wraps(func) + def decorated_view(*args, **kwargs): +~~ if request.method in EXEMPT_METHODS: + return func(*args, **kwargs) + elif current_app.config.get('LOGIN_DISABLED'): + return func(*args, **kwargs) + elif not current_user.is_authenticated: + return current_app.login_manager.unauthorized() + return func(*args, **kwargs) + return decorated_view + + +def fresh_login_required(func): + @wraps(func) + def decorated_view(*args, **kwargs): +~~ if request.method in EXEMPT_METHODS: + return func(*args, **kwargs) + elif current_app.config.get('LOGIN_DISABLED'): + return func(*args, **kwargs) + elif not current_user.is_authenticated: + return current_app.login_manager.unauthorized() + elif not login_fresh(): + return current_app.login_manager.needs_refresh() + return func(*args, **kwargs) + return decorated_view + + +def set_login_view(login_view, blueprint=None): + + num_login_views = len(current_app.login_manager.blueprint_login_views) + if blueprint is not None or num_login_views != 0: + + (current_app.login_manager + .blueprint_login_views[blueprint.name]) = login_view + + if (current_app.login_manager.login_view is not None and + None not in current_app.login_manager.blueprint_login_views): + + (current_app.login_manager + .blueprint_login_views[None]) = (current_app.login_manager + .login_view) + + current_app.login_manager.login_view = None + else: + current_app.login_manager.login_view = login_view + + +def _get_user(): + if has_request_context() and not hasattr(_request_ctx_stack.top, 'user'): + current_app.login_manager._load_user() + + return getattr(_request_ctx_stack.top, 'user', None) + + +def _cookie_digest(payload, key=None): + key = _secret_key(key) + + return hmac.new(key, payload.encode('utf-8'), sha512).hexdigest() + + +def _get_remote_addr(): +~~ address = request.headers.get('X-Forwarded-For', request.remote_addr) + if address is not None: + address = address.encode('utf-8').split(b',')[0].strip() + return address + + +def _create_identifier(): +~~ user_agent = request.headers.get('User-Agent') + if user_agent is not None: + user_agent = user_agent.encode('utf-8') + base = '{0}|{1}'.format(_get_remote_addr(), user_agent) + if str is bytes: + base = text_type(base, 'utf-8', errors='replace') # pragma: no cover + h = sha512() + h.update(base.encode('utf8')) + return h.hexdigest() + + +def _user_context_processor(): + return dict(current_user=_get_user()) + + +def _secret_key(key=None): + if key is None: + key = current_app.config['SECRET_KEY'] + + if isinstance(key, text_type): # pragma: no cover + key = key.encode('latin1') # ensure bytes + + return key + + + +## ... source file continues with no further request examples... + +``` + + +## Example 11 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / marshalling.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./marshalling.py) + +```python +# marshalling.py +from __future__ import unicode_literals + +from collections import OrderedDict +from functools import wraps +from six import iteritems + +~~from flask import request, current_app, has_app_context + +from .mask import Mask, apply as apply_mask +from .utils import unpack + + +def make(cls): + if isinstance(cls, type): + return cls() + return cls + + +def marshal(data, fields, envelope=None, skip_none=False, mask=None, ordered=False): + out, has_wildcards = _marshal(data, fields, envelope, skip_none, mask, ordered) + + if has_wildcards: + from .fields import Wildcard + + items = [] + keys = [] + for dkey, val in fields.items(): + key = dkey + if isinstance(val, dict): + value = marshal(data, val, skip_none=skip_none, ordered=ordered) + else: + + +## ... source file abbreviated to get to request examples ... + + + + if envelope: + out = OrderedDict([(envelope, out)]) if ordered else {envelope: out} + + return out, has_wildcards["present"] + + +class marshal_with(object): + + def __init__( + self, fields, envelope=None, skip_none=False, mask=None, ordered=False + ): + self.fields = fields + self.envelope = envelope + self.skip_none = skip_none + self.ordered = ordered + self.mask = Mask(mask, skip=True) + + def __call__(self, f): + @wraps(f) + def wrapper(*args, **kwargs): + resp = f(*args, **kwargs) + mask = self.mask + if has_app_context(): + mask_header = current_app.config["RESTX_MASK_HEADER"] +~~ mask = request.headers.get(mask_header) or mask + if isinstance(resp, tuple): + data, code, headers = unpack(resp) + return ( + marshal( + data, + self.fields, + self.envelope, + self.skip_none, + mask, + self.ordered, + ), + code, + headers, + ) + else: + return marshal( + resp, self.fields, self.envelope, self.skip_none, mask, self.ordered + ) + + return wrapper + + +class marshal_with_field(object): + + + +## ... source file continues with no further request examples... + +``` + + +## Example 12 from Flask-WTF +[Flask-WTF](https://github.com/lepture/flask-wtf) +([project documentation](https://flask-wtf.readthedocs.io/) +and +[PyPI page](https://pypi.org/project/Flask-WTF/)) +provides a bridge between [Flask](/flask.html) and the the +[WTForms](https://wtforms.readthedocs.io/en/2.3.x/) form-handling library. +It makes it easier to use WTForms by reducing boilerplate code and +shorter examples for common form operations as well as common security +practices such as [CSRF](/cross-site-request-forgery-csrf.html). + +[**Flask-WTF / flask_wtf / csrf.py**](https://github.com/lepture/flask-wtf/blob/master/flask_wtf/./csrf.py) + +```python +# csrf.py +import hashlib +import logging +import os +import warnings +from urllib.parse import urlparse +from functools import wraps + +~~from flask import Blueprint, current_app, g, request, session +from itsdangerous import BadData, SignatureExpired, URLSafeTimedSerializer +from werkzeug.exceptions import BadRequest +from werkzeug.security import safe_str_cmp +from wtforms import ValidationError +from wtforms.csrf.core import CSRF + +from ._compat import FlaskWTFDeprecationWarning + +__all__ = ('generate_csrf', 'validate_csrf', 'CSRFProtect') +logger = logging.getLogger(__name__) + + +def generate_csrf(secret_key=None, token_key=None): + + secret_key = _get_config( + secret_key, 'WTF_CSRF_SECRET_KEY', current_app.secret_key, + message='A secret key is required to use CSRF.' + ) + field_name = _get_config( + token_key, 'WTF_CSRF_FIELD_NAME', 'csrf_token', + message='A field name is required to use CSRF.' + ) + + if field_name not in g: + + +## ... source file abbreviated to get to request examples ... + + + app.extensions['csrf'] = self + + app.config.setdefault('WTF_CSRF_ENABLED', True) + app.config.setdefault('WTF_CSRF_CHECK_DEFAULT', True) + app.config['WTF_CSRF_METHODS'] = set(app.config.get( + 'WTF_CSRF_METHODS', ['POST', 'PUT', 'PATCH', 'DELETE'] + )) + app.config.setdefault('WTF_CSRF_FIELD_NAME', 'csrf_token') + app.config.setdefault( + 'WTF_CSRF_HEADERS', ['X-CSRFToken', 'X-CSRF-Token'] + ) + app.config.setdefault('WTF_CSRF_TIME_LIMIT', 3600) + app.config.setdefault('WTF_CSRF_SSL_STRICT', True) + + app.jinja_env.globals['csrf_token'] = generate_csrf + app.context_processor(lambda: {'csrf_token': generate_csrf}) + + @app.before_request + def csrf_protect(): + if not app.config['WTF_CSRF_ENABLED']: + return + + if not app.config['WTF_CSRF_CHECK_DEFAULT']: + return + +~~ if request.method not in app.config['WTF_CSRF_METHODS']: + return + +~~ if not request.endpoint: + return + +~~ if request.blueprint in self._exempt_blueprints: + return + + view = app.view_functions.get(request.endpoint) + dest = f'{view.__module__}.{view.__name__}' + + if dest in self._exempt_views: + return + + self.protect() + + def _get_csrf_token(self): + field_name = current_app.config['WTF_CSRF_FIELD_NAME'] +~~ base_token = request.form.get(field_name) + + if base_token: + return base_token + +~~ for key in request.form: + if key.endswith(field_name): +~~ csrf_token = request.form[key] + + if csrf_token: + return csrf_token + + for header_name in current_app.config['WTF_CSRF_HEADERS']: +~~ csrf_token = request.headers.get(header_name) + + if csrf_token: + return csrf_token + + return None + + def protect(self): +~~ if request.method not in current_app.config['WTF_CSRF_METHODS']: + return + + try: + validate_csrf(self._get_csrf_token()) + except ValidationError as e: + logger.info(e.args[0]) + self._error_response(e.args[0]) + +~~ if request.is_secure and current_app.config['WTF_CSRF_SSL_STRICT']: +~~ if not request.referrer: + self._error_response('The referrer header is missing.') + + good_referrer = f'https://{request.host}/' + + if not same_origin(request.referrer, good_referrer): + self._error_response('The referrer does not match the host.') + + g.csrf_valid = True # mark this request as CSRF valid + + def exempt(self, view): + + if isinstance(view, Blueprint): + self._exempt_blueprints.add(view.name) + return view + + if isinstance(view, str): + view_location = view + else: + view_location = '.'.join((view.__module__, view.__name__)) + + self._exempt_views.add(view_location) + return view + + def _error_response(self, reason): + + +## ... source file continues with no further request examples... + +``` + + +## Example 13 from flaskSaaS +[flaskSaas](https://github.com/alectrocute/flaskSaaS) is a boilerplate +starter project to build a software-as-a-service (SaaS) web application +in [Flask](/flask.html), with [Stripe](/stripe.html) for billing. The +boilerplate relies on many common Flask extensions such as +[Flask-WTF](https://flask-wtf.readthedocs.io/), +[Flask-Login](https://flask-login.readthedocs.io/en/latest/), +[Flask-Admin](https://flask-admin.readthedocs.io/en/latest/), and +many others. The project is provided as open source under the +[MIT license](https://github.com/alectrocute/flaskSaaS/blob/master/LICENSE). + +[**flaskSaaS / app / admin.py**](https://github.com/alectrocute/flaskSaaS/blob/master/app/./admin.py) + +```python +# admin.py +import os.path as op + +~~from flask import request, Response +from werkzeug.exceptions import HTTPException +from flask_admin import Admin +from flask.ext.admin.contrib.sqla import ModelView +from flask.ext.admin.contrib.fileadmin import FileAdmin + +from app import app, db +from app.models import User + + +admin = Admin(app, name='Admin', template_mode='bootstrap3') + +class ModelView(ModelView): + + def is_accessible(self): +~~ auth = request.authorization or request.environ.get('REMOTE_USER') # workaround for Apache + if not auth or (auth.username, auth.password) != app.config['ADMIN_CREDENTIALS']: + raise HTTPException('', Response('You have to an administrator.', 401, + {'WWW-Authenticate': 'Basic realm="Login Required"'} + )) + return True + +admin.add_view(ModelView(User, db.session)) + +path = op.join(op.dirname(__file__), 'static') +admin.add_view(FileAdmin(path, '/static/', name='Static')) + + + +## ... source file continues with no further request examples... + +``` + + +## Example 14 from Flask-Security-Too +[Flask-Security-Too](https://github.com/Flask-Middleware/flask-security/) +([PyPi page](https://pypi.org/project/Flask-Security-Too/) and +[project documentation](https://flask-security-too.readthedocs.io/en/stable/)) +is a maintained fork of the original +[Flask-Security](https://github.com/mattupstate/flask-security) project that +makes it easier to add common security features to [Flask](/flask.html) +web applications. A few of the critical goals of the Flask-Security-Too +project are ensuring JavaScript client-based single-page applications (SPAs) +can work securely with Flask-based backends and that guidance by the +[OWASP](https://owasp.org/) organization is followed by default. + +The Flask-Security-Too project is provided as open source under the +[MIT license](https://github.com/Flask-Middleware/flask-security/blob/master/LICENSE). + +[**Flask-Security-Too / flask_security / forms.py**](https://github.com/Flask-Middleware/flask-security/blob/master/flask_security/./forms.py) + +```python +# forms.py + +import inspect +import typing as t + +~~from flask import Markup, current_app, request +from flask_login import current_user +from flask_wtf import FlaskForm as BaseForm +from werkzeug.local import LocalProxy +from wtforms import ( + BooleanField, + Field, + HiddenField, + PasswordField, + RadioField, + StringField, + SubmitField, + ValidationError, + validators, +) + +try: # pragma: no cover + from wtforms.fields import EmailField +except ImportError: + from wtforms.fields.html5 import EmailField +from wtforms.validators import StopValidation + +from .babel import is_lazy_string, make_lazy_string +from .confirmable import requires_confirmation +from .utils import ( + + +## ... source file abbreviated to get to request examples ... + + + submit = SubmitField(get_form_field_label("register")) + + username: t.ClassVar[Field] + + def to_dict(self, only_user): + + def is_field_and_user_attr(member): + if not isinstance(member, Field): + return False + + if only_user is True: + return hasattr(_datastore.user_model, member.name) + else: + return True + + fields = inspect.getmembers(self, is_field_and_user_attr) + return {key: value.data for key, value in fields} + + +class SendConfirmationForm(Form, UserEmailFormMixin): + + submit = SubmitField(get_form_field_label("send_confirmation")) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) +~~ if request.method == "GET": +~~ self.email.data = request.args.get("email", None) + + def validate(self): + if not super().validate(): + return False + if self.user.confirmed_at is not None: + self.email.errors.append(get_message("ALREADY_CONFIRMED")[0]) + return False + return True + + +class ForgotPasswordForm(Form, UserEmailFormMixin): + + submit = SubmitField(get_form_field_label("recover_password")) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.requires_confirmation = False + + def validate(self): + if not super().validate(): + return False + if not self.user.is_active: + self.email.errors.append(get_message("DISABLED_ACCOUNT")[0]) + return False + + +## ... source file abbreviated to get to request examples ... + + + self.email.errors.append(get_message("DISABLED_ACCOUNT")[0]) + return False + return True + + +login_email_field = EmailField( + get_form_field_label("email"), validators=[email_required] +) + +login_string_field = StringField( + get_form_field_label("email"), validators=[email_required] +) + + +class LoginForm(Form, NextFormMixin): + + password = PasswordField( + get_form_field_label("password"), validators=[password_required] + ) + remember = BooleanField(get_form_field_label("remember_me")) + submit = SubmitField(get_form_field_label("login")) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if not self.next.data: +~~ self.next.data = request.args.get("next", "") + self.remember.default = cv("DEFAULT_REMEMBER_ME") + if ( + current_app.extensions["security"].recoverable + and not self.password.description + ): + html = Markup( + '{message}'.format( + url=url_for_security("forgot_password"), + message=get_message("FORGOT_PASSWORD")[0], + ) + ) + self.password.description = html + self.requires_confirmation = False + + def validate(self): + if not super().validate(): + return False + + self.user = find_user(self.email.data) + + if self.user is None: + self.email.errors.append(get_message("USER_DOES_NOT_EXIST")[0]) + hash_password(self.password.data) + return False + + +## ... source file abbreviated to get to request examples ... + + + +class RegisterForm(ConfirmRegisterForm, NextFormMixin): + + password_confirm = PasswordField( + get_form_field_label("retype_password"), + validators=[ + EqualTo("password", message="RETYPE_PASSWORD_MISMATCH"), + validators.Optional(), + ], + ) + + def validate(self): + if not super().validate(): + return False + if not cv("UNIFIED_SIGNIN"): + if not self.password_confirm.data or not self.password_confirm.data.strip(): + self.password_confirm.errors.append( + get_message("PASSWORD_NOT_PROVIDED")[0] + ) + return False + return True + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if not self.next.data: +~~ self.next.data = request.args.get("next", "") + + +class ResetPasswordForm(Form, NewPasswordFormMixin, PasswordConfirmFormMixin): + + submit = SubmitField(get_form_field_label("reset_password")) + + def validate(self): + if not super().validate(): + return False + + pbad, self.password.data = _security._password_util.validate( + self.password.data, False, user=current_user + ) + if pbad: + self.password.errors.extend(pbad) + return False + return True + + +class ChangePasswordForm(Form, PasswordFormMixin): + + new_password = PasswordField( + get_form_field_label("new_password"), validators=[password_required] + ) + + +## ... source file continues with no further request examples... + +``` + + +## Example 15 from Flask-SocketIO +[Flask-SocketIO](https://github.com/miguelgrinberg/Flask-SocketIO) +([PyPI package information](https://pypi.org/project/Flask-SocketIO/), +[official tutorial](https://blog.miguelgrinberg.com/post/easy-websockets-with-flask-and-gevent) +and +[project documentation](https://flask-socketio.readthedocs.io/en/latest/)) +is a code library by [Miguel Grinberg](https://blog.miguelgrinberg.com/index) +that provides Socket.IO integration for [Flask](/flask.html) applications. +This extension makes it easier to add bi-directional communications on the +web via the [WebSockets](/websockets.html) protocol. + +The Flask-SocketIO project is open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/LICENSE). + +[**Flask-SocketIO / test_socketio.py**](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/././test_socketio.py) + +```python +# test_socketio.py +import json +import unittest +import coverage + +cov = coverage.coverage(branch=True) +cov.start() + +~~from flask import Flask, session, request, json as flask_json +from flask_socketio import SocketIO, send, emit, join_room, leave_room, \ + Namespace, disconnect + +app = Flask(__name__) +app.config['SECRET_KEY'] = 'secret' +socketio = SocketIO(app) +disconnected = None + + +@socketio.on('connect') +def on_connect(): +~~ if request.args.get('fail'): + return False + send('connected') + send(json.dumps(request.args.to_dict(flat=False))) +~~ send(json.dumps({h: request.headers[h] for h in request.headers.keys() + if h not in ['Host', 'Content-Type', 'Content-Length']})) + + +@socketio.on('disconnect') +def on_disconnect(): + global disconnected + disconnected = '/' + + +@socketio.event(namespace='/test') +def connect(): + send('connected-test') + send(json.dumps(request.args.to_dict(flat=False))) +~~ send(json.dumps({h: request.headers[h] for h in request.headers.keys() + if h not in ['Host', 'Content-Type', 'Content-Length']})) + + +@socketio.on('disconnect', namespace='/test') +def on_disconnect_test(): + global disconnected + disconnected = '/test' + + +@socketio.event +def message(message): + send(message) + if message == 'test session': + session['a'] = 'b' + if message not in "test noackargs": + return message + + +@socketio.on('json') +def on_json(data): + send(data, json=True, broadcast=True) + if not data.get('noackargs'): + return data + + +@socketio.on('message', namespace='/test') +def on_message_test(message): + send(message) + + +@socketio.on('json', namespace='/test') +def on_json_test(data): + send(data, json=True, namespace='/test') + + +@socketio.on('my custom event') +def on_custom_event(data): + emit('my custom response', data) + if not data.get('noackargs'): + return data + + +@socketio.on('other custom event') +@socketio.on('and another custom event') +def get_request_event(data): + global request_event_data +~~ request_event_data = request.event + emit('my custom response', data) + + +def get_request_event2(data): + global request_event_data +~~ request_event_data = request.event + emit('my custom response', data) + + +socketio.on_event('yet another custom event', get_request_event2) + + +@socketio.on('my custom namespace event', namespace='/test') +def on_custom_event_test(data): + emit('my custom namespace response', data, namespace='/test') + + +def on_custom_event_test2(data): + emit('my custom namespace response', data, namespace='/test') + + +socketio.on_event('yet another custom namespace event', on_custom_event_test2, + namespace='/test') + + +@socketio.on('my custom broadcast event') +def on_custom_event_broadcast(data): + emit('my custom response', data, broadcast=True) + + + + +## ... source file abbreviated to get to request examples ... + + +@socketio.on("error testing", namespace='/test') +def raise_error_namespace(data): + raise AssertionError() + + +@socketio.on_error_default +def error_handler_default(value): + if isinstance(value, AssertionError): + global error_testing_default + error_testing_default = True + else: + raise value + return 'error/default' + + +@socketio.on("error testing", namespace='/unused_namespace') +def raise_error_default(data): + raise AssertionError() + + +class MyNamespace(Namespace): + def on_connect(self): + send('connected-ns') + send(json.dumps(request.args.to_dict(flat=False))) + send(json.dumps( +~~ {h: request.headers[h] for h in request.headers.keys() + if h not in ['Host', 'Content-Type', 'Content-Length']})) + + def on_disconnect(self): + global disconnected + disconnected = '/ns' + + def on_message(self, message): + send(message) + if message == 'test session': + session['a'] = 'b' + if message not in "test noackargs": + return message + + def on_json(self, data): + send(data, json=True, broadcast=True) + if not data.get('noackargs'): + return data + + def on_exit(self, data): + disconnect() + + def on_my_custom_event(self, data): + emit('my custom response', data) + if not data.get('noackargs'): + return data + + def on_other_custom_event(self, data): + global request_event_data +~~ request_event_data = request.event + emit('my custom response', data) + + +socketio.on_namespace(MyNamespace('/ns')) + + +@app.route('/session') +def session_route(): + session['foo'] = 'bar' + return '' + + +class TestSocketIO(unittest.TestCase): + @classmethod + def setUpClass(cls): + pass + + @classmethod + def tearDownClass(cls): + cov.stop() + cov.report(include='flask_socketio/*', show_missing=True) + + def setUp(self): + pass + + +## ... source file continues with no further request examples... + +``` + + +## Example 16 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / translation_utils.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/./translation_utils.py) + +```python +# translation_utils.py + + +import os +~~from flask import request + +_translations_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translations') + +try: + from flask_babelex import Domain + + domain_translations = Domain(_translations_dir, domain='flask_user') +except ImportError: + domain_translations = None + +def gettext(string, **variables): + return domain_translations.gettext(string, **variables) if domain_translations else string % variables + +def lazy_gettext(string, **variables): + return domain_translations.lazy_gettext(string, **variables) if domain_translations else string % variables + +def get_language_codes(): + language_codes = [] + for folder in os.listdir(_translations_dir): + locale_dir = os.path.join(_translations_dir, folder, 'LC_MESSAGES') + if not os.path.isdir(locale_dir): + continue + language_codes.append(folder) + return language_codes + +def init_translations(babel): + if babel: + babel._default_domain = domain_translations + + if babel.locale_selector_func is None: + def get_locale(): + available_language_codes = get_language_codes() +~~ language_code = request.accept_languages.best_match(available_language_codes) + return language_code + + babel.locale_selector_func = get_locale + + + +## ... source file continues with no further request examples... + +``` + + +## Example 17 from Flask-VueJs-Template +[Flask-VueJs-Template](https://github.com/gtalarico/flask-vuejs-template) +([demo site](https://flask-vuejs-template.herokuapp.com/)) +is a minimal [Flask](/flask.html) boilerplate starter project that +combines Flask, [Vue.js](https://www.fullstackpython.com/vuejs.html), +and [Flask-RESTPlus](https://flask-restplus.readthedocs.io/en/stable/). +The project provides some sensible defaults that are easy to continue +building on, and the source code is open source under the +[MIT license](https://github.com/gtalarico/flask-vuejs-template/blob/master/LICENSE.md). + +[**Flask-VueJs-Template / app / api / security.py**](https://github.com/gtalarico/flask-vuejs-template/blob/master/app/api/security.py) + +```python +# security.py +from functools import wraps +~~from flask import request +from flask_restplus import abort + + +def require_auth(func): + @wraps(func) + def wrapper(*args, **kwargs): +~~ if request.headers.get('authorization'): + return func(*args, **kwargs) + else: + return abort(401) + return wrapper + + + +## ... source file continues with no further request examples... + +``` + + +## Example 18 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / core / auth.py**](https://github.com/indico/indico/blob/master/indico/core/auth.py) + +```python +# auth.py + +import functools + +~~from flask import current_app, request +from flask_multipass import InvalidCredentials, Multipass, NoSuchUser +from werkzeug.local import LocalProxy + +from indico.core.config import config +from indico.core.limiter import make_rate_limiter +from indico.core.logger import Logger + + +logger = Logger.get('auth') +login_rate_limiter = LocalProxy(functools.cache(lambda: make_rate_limiter('login', config.FAILED_LOGIN_RATE_LIMIT))) + + +class IndicoMultipass(Multipass): + @property + def default_local_auth_provider(self): + return next((p for p in self.auth_providers.values() if not p.is_external and p.settings.get('default')), + None) + + @property + def sync_provider(self): + return next((p for p in self.identity_providers.values() if p.settings.get('synced_fields')), None) + + @property + def synced_fields(self): + + +## ... source file abbreviated to get to request examples ... + + + + def _check_default_provider(self): + sync_providers = [p for p in self.identity_providers.values() if p.settings.get('synced_fields')] + if len(sync_providers) > 1: + raise ValueError('There can only be one sync provider.') + auth_providers = list(self.auth_providers.values()) + external_providers = [p for p in auth_providers if p.is_external] + local_providers = [p for p in auth_providers if not p.is_external] + if any(p.settings.get('default') for p in external_providers): + raise ValueError('The default provider cannot be external') + if all(p.is_external for p in auth_providers): + return + default_providers = [p for p in auth_providers if p.settings.get('default')] + if len(default_providers) > 1: + raise ValueError('There can only be one default auth provider') + elif not default_providers: + if len(local_providers) == 1: + local_providers[0].settings['default'] = True + else: + raise ValueError('There is no default auth provider') + + def handle_auth_error(self, exc, redirect_to_login=False): + if isinstance(exc, (NoSuchUser, InvalidCredentials)): + login_rate_limiter.hit() + logger.warning('Invalid credentials (ip=%s, provider=%s): %s', +~~ request.remote_addr, exc.provider.name if exc.provider else None, exc) + else: + exc_str = str(exc) + fn = logger.error + if exc_str.startswith('mismatching_state:'): + fn = logger.debug + fn('Authentication via %s failed: %s (%r)', exc.provider.name if exc.provider else None, exc_str, + exc.details) + return super().handle_auth_error(exc, redirect_to_login=redirect_to_login) + + +multipass = IndicoMultipass() + + + +## ... source file continues with no further request examples... + +``` + + +## Example 19 from keras-flask-deploy-webapp +The +[keras-flask-deploy-webapp](https://github.com/mtobeiyf/keras-flask-deploy-webapp) +project combines the [Flask](/flask.html) [web framework](/web-frameworks.html) +with the [Keras deep learning library](https://keras.io/) to provide +an example image classifier that is easy to [deploy](/deployment.html). +The application can be quckly run in a [Docker](/docker.html) container +on your local development environment. The project is licensed under the +[GNU General Public License v3.0](https://github.com/mtobeiyf/keras-flask-deploy-webapp/blob/master/LICENSE). + +[**keras-flask-deploy-webapp / app.py**](https://github.com/mtobeiyf/keras-flask-deploy-webapp/blob/master/././app.py) + +```python +# app.py +import os +import sys + +~~from flask import Flask, redirect, url_for, request, render_template, Response, jsonify, redirect +from werkzeug.utils import secure_filename +from gevent.pywsgi import WSGIServer + +import tensorflow as tf +from tensorflow import keras + +from tensorflow.keras.applications.imagenet_utils import preprocess_input, decode_predictions +from tensorflow.keras.models import load_model +from tensorflow.keras.preprocessing import image + +import numpy as np +from util import base64_to_pil + + +app = Flask(__name__) + + + +from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2 +model = MobileNetV2(weights='imagenet') + +print('Model loaded. Check http://127.0.0.1:5000/') + + +MODEL_PATH = 'models/your_model.h5' + + + +def model_predict(img, model): + img = img.resize((224, 224)) + + x = image.img_to_array(img) + x = np.expand_dims(x, axis=0) + + x = preprocess_input(x, mode='tf') + + preds = model.predict(x) + return preds + + +@app.route('/', methods=['GET']) +def index(): + return render_template('index.html') + + +@app.route('/predict', methods=['GET', 'POST']) +def predict(): +~~ if request.method == 'POST': + img = base64_to_pil(request.json) + + + preds = model_predict(img, model) + + pred_proba = "{:.3f}".format(np.amax(preds)) # Max probability + pred_class = decode_predictions(preds, top=1) # ImageNet Decode + + result = str(pred_class[0][0][1]) # Convert to string + result = result.replace('_', ' ').capitalize() + + return jsonify(result=result, probability=pred_proba) + + return None + + +if __name__ == '__main__': + + http_server = WSGIServer(('0.0.0.0', 5000), app) + http_server.serve_forever() + + + +## ... source file continues with no further request examples... + +``` + + +## Example 20 from newspie +[NewsPie](https://github.com/skamieniarz/newspie) is a minimalistic news +aggregator created with [Flask](/flask.html) and the +[News API](https://newsapi.org/). + +NewsPie is provided as open source under the +[MIT license](https://github.com/skamieniarz/newspie/blob/master/LICENSE). + +[**newspie / news.py**](https://github.com/skamieniarz/newspie/blob/master/././news.py) + +```python +# news.py +import configparser +import json +import logging +import os +from typing import Union + +import requests +import requests_cache +from dateutil import parser +~~from flask import (Flask, make_response, redirect, render_template, request, + url_for) + +CONFIG = configparser.ConfigParser() +CONFIG.read('config.ini') +API_KEY = os.environ.get('NEWS_API_KEY') +TOP_HEADLINES = CONFIG['ENDPOINTS']['TOP_HEADLINES'] +EVERYTHING = CONFIG['ENDPOINTS']['EVERYTHING'] +PAGE_SIZE = int(CONFIG['VARIOUS']['PAGE_SIZE']) + +CATEGORIES = ('general', 'sports', 'business', 'entertainment', 'health', + 'science', 'technology') +with open('data/countries.json') as json_file: + COUNTRIES = json.load(json_file) + +logging.basicConfig(level=logging.DEBUG) +requests_cache.install_cache(cache_name='news_cache', + backend='sqlite', + expire_after=300) + +APP = Flask(__name__) +SESSION = requests.Session() +SESSION.headers.update({'Authorization': API_KEY}) + + +@APP.route('/', methods=['GET', 'POST']) +def root(): + return redirect(url_for('category', category='general', page=1)) + + +@APP.errorhandler(404) +def page_not_found(error): + return redirect(url_for('category', category='general', page=1)) + + +@APP.route('/category/', methods=['GET', 'POST']) +def category(category): +~~ page = request.args.get('page', default=1, type=int) + if page < 1: + return redirect(url_for('category', category=category, page=1)) +~~ if request.method == 'POST' and category in CATEGORIES: + return do_post(page, category) + if category in CATEGORIES: + params = {'page': page, 'category': category, 'pageSize': PAGE_SIZE} + country = get_cookie('country') + if country is not None: + params.update({'country': country}) + response = SESSION.get(TOP_HEADLINES, params=params) + if response.status_code == 200: + pages = count_pages(response.json()) + if page > pages: + page = pages + return redirect( + url_for('category', category=category, page=page)) + articles = parse_articles(response.json()) + return render(articles, page, pages, country, category) + elif response.status_code == 401: + return render_template(CONFIG['VARIOUS']['401_TEMPLATE']) + return redirect(url_for('category', category='general', page=page)) + + +@APP.route('/search/', methods=['GET', 'POST']) +def search(query: str): +~~ page = request.args.get('page', default=1, type=int) + if page < 1: + return redirect(url_for('search', query=query, page=1)) + params = { + 'qInTitle': query, + 'sortBy': 'relevancy', + 'page': page, + 'pageSize': PAGE_SIZE + } +~~ if request.method == 'POST': + return do_post(page, category='search', current_query=query) + response = SESSION.get(EVERYTHING, params=params) + pages = count_pages(response.json()) + if page > pages: + page = pages + return redirect(url_for('search', query=query, page=page)) + articles = parse_articles(response.json()) + return render(articles, + page, + pages, + country=get_cookie('country'), + category='search') + + +def do_post(page, category='general', current_query=None): +~~ new_query = request.form.get('search_query') +~~ country = request.form.get('country') +~~ next_page = request.form.get('next_page') +~~ previous_page = request.form.get('previous_page') + if new_query is not None and new_query != '': + return redirect(url_for('search', query=new_query, page=1)) + if country is not None and country != get_cookie('country'): + response = make_response( + redirect(url_for('category', category=category, page=1))) + response.set_cookie('country', country) + return response + if next_page is not None: + page = int(next_page) + 1 + elif previous_page is not None: + page = int(previous_page) - 1 + if category == 'search': + return redirect(url_for('search', query=current_query, page=page)) + return redirect(url_for('category', category=category, page=page)) + + +def parse_articles(response: dict) -> list: + parsed_articles = [] + if response.get('status') == 'ok': + for article in response.get('articles'): + parsed_articles.append({ + 'published_at': + parser.isoparse(article['publishedAt'] + ).strftime('%Y-%m-%d %H:%M'), + + +## ... source file abbreviated to get to request examples ... + + + 'source': + article['source']['name'] + }) + return parsed_articles + + +def count_pages(response: dict) -> int: + if response.get('status') == 'ok': + return (-(-response.get('totalResults', 0) // PAGE_SIZE)) + return 0 + + +def render(articles, page, pages, country, category): + pages = pages if pages <= 12 else 12 + return render_template(CONFIG['VARIOUS']['TEMPLATE'], + articles=articles, + categories=CATEGORIES, + category=category, + countries=COUNTRIES, + country=country, + page=page, + pages=pages) + + +def get_cookie(key: str) -> Union[str, None]: +~~ return request.cookies.get(key) + + +if __name__ == '__main__': + APP.run() + + + +## ... source file continues with no further request examples... + +``` + + +## Example 21 from sandman2 +[sandman2](https://github.com/jeffknupp/sandman2) +([project documentation](https://sandman2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/sandman2/)) +is a code library for automatically generating +[RESTful APIs](/application-programming-interfaces.html) from +existing database schemas. This approach is handy for solving +straightforward situations where you want to put an abstraction +layer between one or more applications and your +[relational database](/databases.html) to prevent or reduce +direct database access. + +The sandman2 project is provided under the +[Apache License 2.0](https://github.com/jeffknupp/sandman2/blob/master/LICENSE). + +[**sandman2 / sandman2 / service.py**](https://github.com/jeffknupp/sandman2/blob/master/sandman2/./service.py) + +```python +# service.py + +~~from flask import request, make_response +import flask +from flask.views import MethodView +from sqlalchemy import asc, desc + +from sandman2.exception import NotFoundException, BadRequestException +from sandman2.model import db +from sandman2.decorators import etag, validate_fields + + +def add_link_headers(response, links): + link_string = '<{}>; rel=self'.format(links['self']) + for link in links.values(): + link_string += ', <{}>; rel=related'.format(link) + response.headers['Link'] = link_string + return response + + +def jsonify(resource): + + response = flask.jsonify(resource.to_dict()) + response = add_link_headers(response, resource.links()) + return response + + +def is_valid_method(model, resource=None): + validation_function_name = 'is_valid_{}'.format( +~~ request.method.lower()) + if hasattr(model, validation_function_name): + return getattr(model, validation_function_name)(request, resource) + +class Service(MethodView): + + + __model__ = None + + __json_collection_name__ = 'resources' + + def delete(self, resource_id): + resource = self._resource(resource_id) + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + db.session().delete(resource) + db.session().commit() + return self._no_content_response() + + @etag + def get(self, resource_id=None): +~~ if request.path.endswith('meta'): + return self._meta() + + if resource_id is None: + error_message = is_valid_method(self.__model__) + if error_message: + raise BadRequestException(error_message) + +~~ if 'export' in request.args: + return self._export(self._all_resources()) + + return flask.jsonify({ + self.__json_collection_name__: self._all_resources() + }) + else: + resource = self._resource(resource_id) + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + return jsonify(resource) + + def patch(self, resource_id): + resource = self._resource(resource_id) + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) +~~ if not request.json: + raise BadRequestException('No JSON data received') + resource.update(request.json) + db.session().merge(resource) + db.session().commit() + return jsonify(resource) + + @validate_fields + def post(self): + resource = self.__model__.query.filter_by(**request.json).first() + if resource: + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + return self._no_content_response() + + resource = self.__model__(**request.json) # pylint: disable=not-callable + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + db.session().add(resource) + db.session().commit() + return self._created_response(resource) + + def put(self, resource_id): + + +## ... source file abbreviated to get to request examples ... + + + raise BadRequestException(error_message) + resource.update(request.json) + db.session().merge(resource) + db.session().commit() + return jsonify(resource) + + resource = self.__model__(**request.json) # pylint: disable=not-callable + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + db.session().add(resource) + db.session().commit() + return self._created_response(resource) + + def _meta(self): + return flask.jsonify(self.__model__.description()) + + def _resource(self, resource_id): + resource = self.__model__.query.get(resource_id) + if not resource: + raise NotFoundException() + return resource + + def _all_resources(self): + queryset = self.__model__.query +~~ args = {k: v for (k, v) in request.args.items() if k not in ('page', 'export')} + limit = None + if args: + filters = [] + order = [] + for key, value in args.items(): + if value.startswith('%'): + filters.append(getattr(self.__model__, key).like(str(value), escape='/')) + elif key == 'sort': + direction = desc if value.startswith('-') else asc + order.append(direction(getattr(self.__model__, value.lstrip('-')))) + elif key == 'limit': + limit = int(value) + elif hasattr(self.__model__, key): + filters.append(getattr(self.__model__, key) == value) + else: + raise BadRequestException('Invalid field [{}]'.format(key)) + queryset = queryset.filter(*filters).order_by(*order) +~~ if 'page' in request.args: + resources = queryset.paginate(page=int(request.args['page']), per_page=limit).items + else: + queryset = queryset.limit(limit) + resources = queryset.all() + return [r.to_dict() for r in resources] + + def _export(self, collection): + fieldnames = collection[0].keys() + faux_csv = ','.join(fieldnames) + '\r\n' + for resource in collection: + faux_csv += ','.join((str(x) for x in resource.values())) + '\r\n' + response = make_response(faux_csv) + response.mimetype = 'text/csv' + return response + + + @staticmethod + def _no_content_response(): + response = make_response() + response.status_code = 204 + return response + + @staticmethod + def _created_response(resource): + + +## ... source file continues with no further request examples... + +``` + + +## Example 22 from Science Flask +[Science Flask](https://github.com/danielhomola/science_flask) +is a [Flask](/flask.html)-powered web application for online +scientific research tools. The project was built as a template +for any scientist or groups of scientists to use when working +together without having to really understand how the application +is built. The application includes an academic registration +process (only valid academic email addresses can be used), an +admin panel, logging, and analysis forms. + +[@danielhomola](https://github.com/danielhomola) is the +primary creator of Science Flask and the project is open +source under the +[GNU General Public License](https://github.com/danielhomola/science_flask/blob/master/LICENSE). + +[**Science Flask / frontend / __init__.py**](https://github.com/danielhomola/science_flask/blob/master/./frontend/__init__.py) + +```python +# __init__.py +import os +~~from flask import Flask, url_for, redirect, request, abort +from flask_mail import Mail +from flask_sqlalchemy import SQLAlchemy +from flask_login import LoginManager +from flask_security import Security, SQLAlchemyUserDatastore, signals, \ + current_user +import flask_admin +from flask_admin.contrib import sqla +from flask_admin import helpers as admin_helpers +from flask_wtf.csrf import CSRFProtect +from celery import Celery + + +appdir = os.path.abspath(os.path.dirname(__file__)) +ROOTDIR = os.path.abspath(os.path.join(appdir, os.pardir)) +user_data_folder = os.path.join(ROOTDIR, 'userData') + +app = Flask(__name__, instance_path=user_data_folder) + +app.config.from_pyfile('config.py') + +db = SQLAlchemy(app) + +mail = Mail(app) + + + +## ... source file abbreviated to get to request examples ... + + + +class MyModelView(sqla.ModelView): + + def __init__(self, model, session, name=None, category=None, endpoint=None, + url=None, **kwargs): + for k, v in kwargs.items(): + setattr(self, k, v) + + super(MyModelView, self).__init__(model, session, name=name, + category=category, endpoint=endpoint, + url=url) + + def is_accessible(self): + if not current_user.is_active or not current_user.is_authenticated: + return False + + if current_user.has_role('superuser'): + return True + return False + + def _handle_view(self, name, **kwargs): + if not self.is_accessible(): + if current_user.is_authenticated: + abort(403) + else: +~~ return redirect(url_for('security.login', next=request.url)) + +admin = flask_admin.Admin( + app, + 'Admin panel', + base_template='admin_base.html', + template_mode='bootstrap3', +) + +from .models import Studies, Analyses +admin.add_view(MyModelView(Role, db.session)) +cols = [c for c in User.__table__.columns] +admin.add_view(MyModelView(User, db.session, column_list=cols)) +cols = [c for c in Studies.__table__.columns] +admin.add_view(MyModelView(Studies, db.session, column_list=cols)) +cols = [c for c in Analyses.__table__.columns] +admin.add_view(MyModelView(Analyses, db.session, column_list=cols)) + +@security.context_processor +def security_context_processor(): + return dict( + admin_base_template=admin.base_template, + admin_view=admin.index_view, + h=admin_helpers, + get_url=url_for + + +## ... source file continues with no further request examples... + +``` + + +## Example 23 from tedivms-flask +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + +[**tedivms-flask / app / utils / api.py**](https://github.com/tedivm/tedivms-flask/blob/master/app/utils/api.py) + +```python +# api.py +from app.models import user_models as users +from functools import wraps +~~from flask import request, abort, current_app + + +def is_authorized_api_user(roles=False): +~~ if 'API_ID' not in request.headers: + return False +~~ if 'API_KEY' not in request.headers: + return False +~~ api_key = users.ApiKey.query.filter(users.ApiKey.id==request.headers['API_ID']).first() + if not api_key: + return False + if not current_app.user_manager.verify_password(request.headers['API_KEY'], api_key.hash): + return False + if not roles: + return True + if api_key.user.has_role('admin'): + return True + for role in roles: + if api_key.user.has_role(role): + return True + return False + + +def roles_accepted_api(*role_names): + def wrapper(view_function): + @wraps(view_function) + def decorated_view_function(*args, **kwargs): + if not is_authorized_api_user(role_names): + return abort(403) + return view_function(*args, **kwargs) + return decorated_view_function + return wrapper + + + +## ... source file continues with no further request examples... + +``` + + +## Example 24 from trape +[trape](https://github.com/jofpin/trape) is a research tool for tracking +people's activities that are logged digitally. The tool uses +[Flask](/flask.html) to create a web front end to view aggregated data +on an individual the application is set to track. The source code is +provided as open source under the MIT license, according to the +[README](https://github.com/jofpin/trape/blob/master/README.md). + +[**trape / core / user.py**](https://github.com/jofpin/trape/blob/master/./core/user.py) + +```python +# user.py +import time +from core.dependence import urllib2 +~~from flask import Flask, render_template, session, request, json, Response +from core.user_objects import * +import core.stats +from core.utils import utils +from core.db import Database +import os +import sys +import platform +import urllib +import requests +from multiprocessing import Process + +trape = core.stats.trape +app = core.stats.app + +db = Database() + +class victim_server(object): + @app.route("/" + trape.victim_path) + def homeVictim(): + r = requests.get(trape.url_to_clone, headers=victim_headers2(request.user_agent)) + if (trape.type_lure == 'local'): + html = assignScripts(victim_inject_code(render_template("/" + trape.url_to_clone), 'payload', '/', trape.gmaps, trape.ipinfo)) + else: + html = assignScripts(victim_inject_code(r.content, 'payload', trape.url_to_clone, trape.gmaps, trape.ipinfo)) + return html + + @app.route("/register", methods=["POST"]) + def register(): +~~ vId = request.form['vId'] + if vId == '': + vId = utils.generateToken(5) + +~~ victimConnect = victim(vId, request.environ['REMOTE_ADDR'], request.user_agent.platform, request.user_agent.browser, request.user_agent.version, utils.portScanner(request.environ['REMOTE_ADDR']), request.form['cpu'], time.strftime("%Y-%m-%d - %H:%M:%S")) +~~ victimGeo = victim_geo(vId, request.form['city'], request.form['country_code2'], request.form['country_name'], request.form['ip'], request.form['latitude'], request.form['longitude'], request.form['isp'], request.form['country_code3'], request.form['state_prov'], '', request.form['zipcode'], request.form['organization'], str(request.user_agent), '') + +~~ vRA = request.environ['REMOTE_ADDR'] + + gHA = Process(target=getHostsAlive, args=(vRA, vId,)) + gHA.start() + + utils.Go(utils.Color['white'] + "[" + utils.Color['blueBold'] + "*" + utils.Color['white'] + "]" + " A " + utils.Color['whiteBold'] + "user" + utils.Color['white'] + " has been connected from " + utils.Color['blue'] + victimGeo.ip + utils.Color['white'] + ' with the following identifier: ' + utils.Color['green'] + vId + utils.Color['white']) + cant = int(db.sentences_victim('count_times', vId, 3, 0)) + + db.sentences_victim('insert_click', [vId, trape.url_to_clone, time.strftime("%Y-%m-%d - %H:%M:%S")], 2) + db.sentences_victim('delete_networks', [vId], 2) + + if cant > 0: + utils.Go(utils.Color['white'] + "[" + utils.Color['blueBold'] + "*" + utils.Color['white'] + "]" + " " + "It\'s the " + str(cant + 1) + " time for " + utils.Color['green'] + str(vId) + utils.Color['white'] + "@" + utils.Color['blue'] + victimGeo.ip + utils.Color['white']) + db.sentences_victim('update_victim', [victimConnect, vId, time.time()], 2) + db.sentences_victim('update_victim_geo', [victimGeo, vId], 2) + else: + utils.Go(utils.Color['white'] + "[" + utils.Color['blueBold'] + "*" + utils.Color['white'] + "]" + " " + "It\'s the first time for " + utils.Color['green'] + str(vId) + utils.Color['white'] + "@" + utils.Color['blue'] + victimGeo.ip + utils.Color['white']) + db.sentences_victim('insert_victim', [victimConnect, vId, time.time()], 2) + db.sentences_victim('insert_victim_data', [vId], 2) + db.sentences_victim('insert_victim_battery', [vId], 2) + db.sentences_victim('insert_victim_geo', [victimGeo, vId], 2) + return json.dumps({'status' : 'OK', 'vId' : vId}) + + @app.route("/nr", methods=["POST"]) + def networkRegister(): +~~ vId = request.form['vId'] +~~ vIp = request.form['ip'] +~~ vnetwork = request.form['red'] + if vId == '': + vId = utils.generateToken(5) + + cant = int(db.sentences_victim('count_victim_network', [vId, vnetwork], 3, 0)) + + if cant > 0: + db.sentences_victim('update_network', [vId, vnetwork, time.strftime("%Y-%m-%d - %H:%M:%S")], 2) + else: +~~ db.sentences_victim('insert_networks', [vId, vIp, request.environ['REMOTE_ADDR'], vnetwork, time.strftime("%Y-%m-%d - %H:%M:%S")], 2) + utils.Go(utils.Color['white'] + "[" + utils.Color['greenBold'] + "+" + utils.Color['white'] + "]" + utils.Color['whiteBold'] + " " + vnetwork + utils.Color['white'] + " session detected from " + utils.Color['blue'] + vIp + utils.Color['white'] + ' ' + "with ID: " + utils.Color['green'] + vId + utils.Color['white']) + return json.dumps({'status' : 'OK', 'vId' : vId}) + + @app.route("/lr", methods=["POST"]) + def locationRegister(): +~~ vId = request.form['vId'] +~~ lat = request.form['lat'] +~~ lon = request.form['lon'] + + db.sentences_victim('location_victim', [vId, lat, lon], 2) + return json.dumps({'status' : 'OK', 'vId' : vId}) + + @app.route("/lc", methods=["POST"]) + def connectionRegister(): +~~ vId = request.form['vId'] +~~ con = request.form['con'] +~~ host = request.form['host'] + + db.sentences_victim('connection_victim', [vId, con, host], 2) + return json.dumps({'status' : 'OK', 'vId' : vId}) + + @app.route("/bs", methods=["POST"]) + def batteryStatusRegister(): +~~ vId = request.form['id'] +~~ b_data = request.form['d'] +~~ b_type = request.form['t'] + + db.sentences_victim('update_battery', [vId, b_data, b_type], 2) + return json.dumps({'status' : 'OK', 'vId' : vId}) + + @app.route("/nm", methods=["POST"]) + def navigationMode(): +~~ vId = request.form['id'] +~~ b_data = request.form['d'] +~~ b_data_2 = request.form['dn'] + + db.sentences_victim('update_navigationmode', [vId, b_data, b_data_2], 2) + return json.dumps({'status' : 'OK', 'vId' : vId}) + + @app.route("/rv") + def redirectVictim(): +~~ url = request.args.get('url') + if url[0:4] != 'http': + url = 'http://' + url + opener = urllib.request.build_opener() + headers = victim_headers(request.user_agent) + opener.addheaders = headers + html = assignScripts(victim_inject_code(opener.open(url).read(), 'vscript', url, trape.gmaps, trape.ipinfo)) + return html + + @app.route("/regv", methods=["POST"]) + def registerRequest(): +~~ vrequest = victim_request(request.form['vId'], request.form['site'], request.form['fid'], request.form['name'], request.form['value'], request.form['sId']) + db.sentences_victim('insert_requests', [vrequest, time.strftime("%Y-%m-%d - %H:%M:%S")], 2) + utils.Go(utils.Color['white'] + "[" + utils.Color['greenBold'] + "=" + utils.Color['white'] + "]" + " " + 'Receiving data from: ' + utils.Color['green'] + vrequest.id + utils.Color['white'] + ' ' + 'on' + ' ' + utils.Color['blue'] + vrequest.site + utils.Color['white'] + '\t\n' + vrequest.fid + '\t' + vrequest.name + ':\t' + vrequest.value) + return json.dumps({'status' : 'OK', 'vId' : vrequest.id}) + + @app.route("/tping", methods=["POST"]) + def receivePiregisterGPUng(): +~~ vrequest = request.form['id'] + db.sentences_victim('report_online', [vrequest], 2) + db.sentences_victim('update_lastping', [vrequest, time.strftime("%Y-%m-%d - %H:%M:%S")], 2) + return json.dumps({'status' : 'OK', 'vId' : vrequest}) + + @app.route("/cIp", methods=["POST"]) + def changeLocalIp(): +~~ vrequest = request.form['id'] +~~ vIp = request.form['ip'] + db.sentences_victim('update_localIp', [vrequest, vIp], 2) + return json.dumps({'status' : 'OK', 'vId' : vrequest}) + + @app.route("/gGpu", methods=["POST"]) + def setGpuInfo(): +~~ vId = request.form['vId'] +~~ vData = request.form['data'] + db.sentences_victim('update_gpu', [vId, vData], 2) + return json.dumps({'status' : 'OK', 'vId' : vId}) + + +def getHostsAlive(ip, vId): + hDB = Database() + try: + hDB.sentences_victim('delete_hostalive', vId, 2) + split_ip = ip.split('.') + net = split_ip[0] + '.' + split_ip[1] + '.' + split_ip[2] + '.' + if ip != '127.0.0.1': + if (platform.system()=='Windows'): + ping = 'ping -n 1 -w 5' + else: + ping = 'ping -c 1 -t 3' + for sub_net in range(1, 255): + address = net + str(sub_net) + response = os.popen(ping + ' ' + address) + for line in response.readlines(): + if ('time=' in line.lower()): + lPos = line.find('time=') + tmpLine = line[lPos+5:lPos+15] + lPos = tmpLine.find('ms') + tmpLine = tmpLine[0:lPos+2] + + +## ... source file continues with no further request examples... + +``` + diff --git a/content/pages/examples/flask/flask-globals-session.markdown b/content/pages/examples/flask/flask-globals-session.markdown new file mode 100644 index 000000000..baf253747 --- /dev/null +++ b/content/pages/examples/flask/flask-globals-session.markdown @@ -0,0 +1,1570 @@ +title: flask.globals session Example Code +category: page +slug: flask-globals-session-examples +sortorder: 500021017 +toc: False +sidebartitle: flask.globals session +meta: Python example code that shows how to use the session callable from the flask.globals module of the Flask project. + + +[session](https://github.com/pallets/flask/blob/master/src/flask/globals.py) +is function in the [Flask](/flask.html) `flask.globals` module and is an +instance of +[LocalProxy](https://github.com/pallets/werkzeug/blob/master/src/werkzeug/local.py) +from the [Werkzeug](https://werkzeug.palletsprojects.com/en/1.0.x/) library. +`session` stores data about the user session for the current request and it +can be used to access session data. + +Note that `session` is usually imported directly from `flask` instead of +from `flask.globals`, even though it is defined within the `globals` module. +It's the same function that is imported, but it's less characters to type +when you leave off the `.globals` part. + +current_app, +g, +and request +are several other callables with code examples from the same `flask.globals` package. + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / CTFd / auth.py**](https://github.com/CTFd/CTFd/blob/master/./CTFd/auth.py) + +```python +# auth.py +import base64 + +import requests +from flask import Blueprint, abort +from flask import current_app as app +~~from flask import redirect, render_template, request, session, url_for +from itsdangerous.exc import BadSignature, BadTimeSignature, SignatureExpired + +from CTFd.cache import clear_team_session, clear_user_session +from CTFd.models import Teams, UserFieldEntries, UserFields, Users, db +from CTFd.utils import config, email, get_app_config, get_config +from CTFd.utils import user as current_user +from CTFd.utils import validators +from CTFd.utils.config import is_teams_mode +from CTFd.utils.config.integrations import mlc_registration +from CTFd.utils.config.visibility import registration_visible +from CTFd.utils.crypto import verify_password +from CTFd.utils.decorators import ratelimit +from CTFd.utils.decorators.visibility import check_registration_visibility +from CTFd.utils.helpers import error_for, get_errors, markup +from CTFd.utils.logging import log +from CTFd.utils.modes import TEAMS_MODE +from CTFd.utils.security.auth import login_user, logout_user +from CTFd.utils.security.signing import unserialize +from CTFd.utils.validators import ValidationError + +auth = Blueprint("auth", __name__) + + +@auth.route("/confirm", methods=["POST", "GET"]) + + +## ... source file abbreviated to get to session examples ... + + + else: + return render_template("register.html", errors=errors) + + +@auth.route("/login", methods=["POST", "GET"]) +@ratelimit(method="POST", limit=10, interval=5) +def login(): + errors = get_errors() + if request.method == "POST": + name = request.form["name"] + + if validators.validate_email(name) is True: + user = Users.query.filter_by(email=name).first() + else: + user = Users.query.filter_by(name=name).first() + + if user: + if user.password is None: + errors.append( + "Your account was registered with a 3rd party authentication provider. " + "Please try logging in with a configured authentication provider." + ) + return render_template("login.html", errors=errors) + + if user and verify_password(request.form["password"], user.password): +~~ session.regenerate() + + login_user(user) + log("logins", "[{date}] {ip} - {name} logged in", name=user.name) + + db.session.close() + if request.args.get("next") and validators.is_safe_url( + request.args.get("next") + ): + return redirect(request.args.get("next")) + return redirect(url_for("challenges.listing")) + + else: + log( + "logins", + "[{date}] {ip} - submitted invalid password for {name}", + name=user.name, + ) + errors.append("Your username or password is incorrect") + db.session.close() + return render_template("login.html", errors=errors) + else: + log("logins", "[{date}] {ip} - submitted invalid account information") + errors.append("Your username or password is incorrect") + db.session.close() + + +## ... source file continues with no further session examples... + +``` + + +## Example 2 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / security / registerviews.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/security/registerviews.py) + +```python +# registerviews.py +__author__ = "Daniel Gaspar" + +import logging + +~~from flask import flash, redirect, request, session, url_for +from flask_babel import lazy_gettext + +from .forms import LoginForm_oid, RegisterUserDBForm, RegisterUserOIDForm +from .. import const as c +from .._compat import as_unicode +from ..validators import Unique +from ..views import expose, PublicFormView + +log = logging.getLogger(__name__) + + +def get_first_last_name(fullname): + names = fullname.split() + if len(names) > 1: + return names[0], " ".join(names[1:]) + elif names: + return names[0], "" + + +class BaseRegisterUser(PublicFormView): + + route_base = "/register" + email_template = "appbuilder/general/security/register_mail.html" + email_subject = lazy_gettext("Account activation") + + +## ... source file abbreviated to get to session examples ... + + + username=form.username.data, + first_name=form.first_name.data, + last_name=form.last_name.data, + email=form.email.data, + password=form.password.data, + ) + + +class RegisterUserOIDView(BaseRegisterUser): + + route_base = "/register" + + form = RegisterUserOIDForm + default_view = "form_oid_post" + + @expose("/formoidone", methods=["GET", "POST"]) + def form_oid_post(self, flag=True): + if flag: + self.oid_login_handler(self.form_oid_post, self.appbuilder.sm.oid) + form = LoginForm_oid() + if form.validate_on_submit(): + session["remember_me"] = form.remember_me.data + return self.appbuilder.sm.oid.try_login( + form.openid.data, ask_for=["email", "fullname"] + ) +~~ resp = session.pop("oid_resp", None) + if resp: + self._init_vars() + form = self.form.refresh() + self.form_get(form) + form.username.data = resp.email + first_name, last_name = get_first_last_name(resp.fullname) + form.first_name.data = first_name + form.last_name.data = last_name + form.email.data = resp.email + widgets = self._get_edit_widget(form=form) + return self.render_template( + self.form_template, + title=self.form_title, + widgets=widgets, + form_action="form", + appbuilder=self.appbuilder, + ) + else: + flash(as_unicode(self.error_message), "warning") + return redirect(self.get_redirect()) + + def oid_login_handler(self, f, oid): + from flask_openid import OpenIDResponse, SessionWrapper + from openid.consumer.consumer import CANCEL, Consumer, SUCCESS + + +## ... source file continues with no further session examples... + +``` + + +## Example 3 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / utils / helpers.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/utils/helpers.py) + +```python +# helpers.py +import ast +import itertools +import logging +import operator +import os +import re +import time +import warnings +from datetime import datetime, timedelta +from email import message_from_string +from functools import wraps + +import pkg_resources +import requests +import unidecode +from babel.core import get_locale_identifier +from babel.dates import format_date as babel_format_date +from babel.dates import format_datetime as babel_format_datetime +from babel.dates import format_timedelta as babel_format_timedelta +from babel.dates import format_time as babel_format_time +~~from flask import current_app, flash, g, redirect, request, session, url_for +from flask_allows import Permission +from flask_babelplus import lazy_gettext as _ +from flask_login import current_user +from flask_themes2 import get_themes_list, render_theme_template +from jinja2 import Markup +from PIL import ImageFile +from pytz import UTC +from werkzeug.local import LocalProxy +from werkzeug.utils import ImportStringError, import_string + +from flaskbb.extensions import babel, redis_store +from flaskbb.utils.http import is_safe_url +from flaskbb.utils.settings import flaskbb_config + + +logger = logging.getLogger(__name__) + +_punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+') + + +def to_bytes(text, encoding="utf-8"): + if isinstance(text, str): + text = text.encode(encoding) + return text + + +## ... source file abbreviated to get to session examples ... + + + result.append(word) + return str(delim.join(result)) + + +def redirect_url(endpoint, use_referrer=True): + targets = [endpoint] + allowed_hosts = current_app.config["ALLOWED_HOSTS"] + if use_referrer: + targets.insert(0, request.referrer) + for target in targets: + if target and is_safe_url(target, allowed_hosts): + return target + + +def redirect_or_next(endpoint, use_referrer=True): + return redirect( + redirect_url(request.args.get("next"), use_referrer) + or redirect_url(endpoint, use_referrer) + ) + + +def render_template(template, **context): # pragma: no cover + if current_user.is_authenticated and current_user.theme: + theme = current_user.theme + else: +~~ theme = session.get("theme", flaskbb_config["DEFAULT_THEME"]) + return render_theme_template(theme, template, **context) + + +def do_topic_action(topics, user, action, reverse): # noqa: C901 + if not topics: + return False + + from flaskbb.utils.requirements import ( + IsAtleastModeratorInForum, + CanDeleteTopic, + Has, + ) + + if not Permission(IsAtleastModeratorInForum(forum=topics[0].forum)): + flash( + _("You do not have the permissions to execute this action."), + "danger", + ) + return False + + modified_topics = 0 + if action not in {"delete", "hide", "unhide"}: + for topic in topics: + if getattr(topic, action) and not reverse: + + +## ... source file continues with no further session examples... + +``` + + +## Example 4 from flaskex +[Flaskex](https://github.com/anfederico/Flaskex) is a working example +[Flask](/flask.html) web application intended as a base to build your +own applications upon. The application comes with pre-built sign up, log in +and related screens, as well as a database backend. Flaskex is provided +as open source under the +[MIT license](https://github.com/anfederico/Flaskex/blob/master/LICENSE.txt). + +[**flaskex / app.py**](https://github.com/anfederico/Flaskex/blob/master/././app.py) + +```python +# app.py + +from scripts import tabledef +from scripts import forms +from scripts import helpers +~~from flask import Flask, redirect, url_for, render_template, request, session +import json +import sys +import os + +app = Flask(__name__) +app.secret_key = os.urandom(12) # Generic key for dev purposes only + + +@app.route('/', methods=['GET', 'POST']) +def login(): +~~ if not session.get('logged_in'): + form = forms.LoginForm(request.form) + if request.method == 'POST': + username = request.form['username'].lower() + password = request.form['password'] + if form.validate(): + if helpers.credentials_valid(username, password): + session['logged_in'] = True + session['username'] = username + return json.dumps({'status': 'Login successful'}) + return json.dumps({'status': 'Invalid user/pass'}) + return json.dumps({'status': 'Both fields required'}) + return render_template('login.html', form=form) + user = helpers.get_user() + return render_template('home.html', user=user) + + +@app.route("/logout") +def logout(): + session['logged_in'] = False + return redirect(url_for('login')) + + +@app.route('/signup', methods=['GET', 'POST']) +def signup(): +~~ if not session.get('logged_in'): + form = forms.LoginForm(request.form) + if request.method == 'POST': + username = request.form['username'].lower() + password = helpers.hash_password(request.form['password']) + email = request.form['email'] + if form.validate(): + if not helpers.username_taken(username): + helpers.add_user(username, password, email) + session['logged_in'] = True + session['username'] = username + return json.dumps({'status': 'Signup successful'}) + return json.dumps({'status': 'Username taken'}) + return json.dumps({'status': 'User/Pass required'}) + return render_template('login.html', form=form) + return redirect(url_for('login')) + + +@app.route('/settings', methods=['GET', 'POST']) +def settings(): +~~ if session.get('logged_in'): + if request.method == 'POST': + password = request.form['password'] + if password != "": + password = helpers.hash_password(password) + email = request.form['email'] + helpers.change_user(password=password, email=email) + return json.dumps({'status': 'Saved'}) + user = helpers.get_user() + return render_template('settings.html', user=user) + return redirect(url_for('login')) + + +if __name__ == "__main__": + app.run(debug=True, use_reloader=True, host="0.0.0.0") + + + +## ... source file continues with no further session examples... + +``` + + +## Example 5 from Flask-HTTPAuth +[Flask-HTTPAuth](https://github.com/miguelgrinberg/Flask-HTTPAuth) +([documentation](https://flask-httpauth.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/Flask-HTTPAuth/)) +is a [Flask](/flask.html) framework extension that creates +Basic and Digest HTTP authentication for routes. This project +is primarily built and maintained by +[Miguel Grinberg](https://blog.miguelgrinberg.com/). It is provided +as open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/LICENSE). + +[**Flask-HTTPAuth / flask_httpauth.py**](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/././flask_httpauth.py) + +```python +# flask_httpauth.py + +from base64 import b64decode +from functools import wraps +from hashlib import md5 +from random import Random, SystemRandom +~~from flask import request, make_response, session, g, Response +from werkzeug.datastructures import Authorization +from werkzeug.security import safe_str_cmp + +__version__ = '4.2.1dev' + + +class HTTPAuth(object): + def __init__(self, scheme=None, realm=None, header=None): + self.scheme = scheme + self.realm = realm or "Authentication Required" + self.header = header + self.get_password_callback = None + self.get_user_roles_callback = None + self.auth_error_callback = None + + def default_get_password(username): + return None + + def default_auth_error(status): + return "Unauthorized Access", status + + self.get_password(default_get_password) + self.error_handler(default_auth_error) + + + +## ... source file abbreviated to get to session examples ... + + + + +class HTTPDigestAuth(HTTPAuth): + def __init__(self, scheme=None, realm=None, use_ha1_pw=False): + super(HTTPDigestAuth, self).__init__(scheme or 'Digest', realm) + self.use_ha1_pw = use_ha1_pw + self.random = SystemRandom() + try: + self.random.random() + except NotImplementedError: # pragma: no cover + self.random = Random() + + self.generate_nonce_callback = None + self.verify_nonce_callback = None + self.generate_opaque_callback = None + self.verify_opaque_callback = None + + def _generate_random(): + return md5(str(self.random.random()).encode('utf-8')).hexdigest() + + def default_generate_nonce(): + session["auth_nonce"] = _generate_random() + return session["auth_nonce"] + + def default_verify_nonce(nonce): +~~ session_nonce = session.get("auth_nonce") + if nonce is None or session_nonce is None: + return False + return safe_str_cmp(nonce, session_nonce) + + def default_generate_opaque(): + session["auth_opaque"] = _generate_random() + return session["auth_opaque"] + + def default_verify_opaque(opaque): +~~ session_opaque = session.get("auth_opaque") + if opaque is None or session_opaque is None: # pragma: no cover + return False + return safe_str_cmp(opaque, session_opaque) + + self.generate_nonce(default_generate_nonce) + self.generate_opaque(default_generate_opaque) + self.verify_nonce(default_verify_nonce) + self.verify_opaque(default_verify_opaque) + + def generate_nonce(self, f): + self.generate_nonce_callback = f + return f + + def verify_nonce(self, f): + self.verify_nonce_callback = f + return f + + def generate_opaque(self, f): + self.generate_opaque_callback = f + return f + + def verify_opaque(self, f): + self.verify_opaque_callback = f + return f + + +## ... source file continues with no further session examples... + +``` + + +## Example 6 from flask-login +[Flask-Login](https://github.com/maxcountryman/flask-login) +([project documentation](https://flask-login.readthedocs.io/en/latest/) +and [PyPI package](https://pypi.org/project/Flask-Login/)) +is a [Flask](/flask.html) extension that provides user session +management, which handles common tasks such as logging in +and out of a [web application](/web-development.html) and +managing associated user session data. Flask-Login is +open sourced under the +[MIT license](https://github.com/maxcountryman/flask-login/blob/master/LICENSE). + +[**flask-login / flask_login / utils.py**](https://github.com/maxcountryman/flask-login/blob/master/flask_login/./utils.py) + +```python +# utils.py + + +import hmac +from hashlib import sha512 +from functools import wraps +from werkzeug.local import LocalProxy +from werkzeug.security import safe_str_cmp +from werkzeug.urls import url_decode, url_encode + +~~from flask import (_request_ctx_stack, current_app, request, session, url_for, + has_request_context) + +from ._compat import text_type, urlparse, urlunparse +from .config import COOKIE_NAME, EXEMPT_METHODS +from .signals import user_logged_in, user_logged_out, user_login_confirmed + + +current_user = LocalProxy(lambda: _get_user()) + + +def encode_cookie(payload, key=None): + return u'{0}|{1}'.format(payload, _cookie_digest(payload, key=key)) + + +def decode_cookie(cookie, key=None): + try: + payload, digest = cookie.rsplit(u'|', 1) + if hasattr(digest, 'decode'): + digest = digest.decode('ascii') # pragma: no cover + except ValueError: + return + + if safe_str_cmp(_cookie_digest(payload, key=key), digest): + return payload + + +## ... source file abbreviated to get to session examples ... + + + return login_view + else: + if request.view_args is None: + return url_for(login_view) + else: + return url_for(login_view, **request.view_args) + + +def login_url(login_view, next_url=None, next_field='next'): + base = expand_login_view(login_view) + + if next_url is None: + return base + + parsed_result = urlparse(base) + md = url_decode(parsed_result.query) + md[next_field] = make_next_param(base, next_url) + netloc = current_app.config.get('FORCE_HOST_FOR_REDIRECTS') or \ + parsed_result.netloc + parsed_result = parsed_result._replace(netloc=netloc, + query=url_encode(md, sort=True)) + return urlunparse(parsed_result) + + +def login_fresh(): +~~ return session.get('_fresh', False) + + +def login_user(user, remember=False, duration=None, force=False, fresh=True): + if not force and not user.is_active: + return False + + user_id = getattr(user, current_app.login_manager.id_attribute)() + session['_user_id'] = user_id + session['_fresh'] = fresh + session['_id'] = current_app.login_manager._session_identifier_generator() + + if remember: + session['_remember'] = 'set' + if duration is not None: + try: + session['_remember_seconds'] = (duration.microseconds + + (duration.seconds + + duration.days * 24 * 3600) * + 10**6) / 10.0**6 + except AttributeError: + raise Exception('duration must be a datetime.timedelta, ' + 'instead got: {0}'.format(duration)) + + current_app.login_manager._update_request_context_with_user(user) + user_logged_in.send(current_app._get_current_object(), user=_get_user()) + return True + + +def logout_user(): + + user = _get_user() + +~~ if '_user_id' in session: +~~ session.pop('_user_id') + +~~ if '_fresh' in session: +~~ session.pop('_fresh') + +~~ if '_id' in session: +~~ session.pop('_id') + + cookie_name = current_app.config.get('REMEMBER_COOKIE_NAME', COOKIE_NAME) + if cookie_name in request.cookies: + session['_remember'] = 'clear' +~~ if '_remember_seconds' in session: +~~ session.pop('_remember_seconds') + + user_logged_out.send(current_app._get_current_object(), user=user) + + current_app.login_manager._update_request_context_with_user() + return True + + +def confirm_login(): + session['_fresh'] = True + session['_id'] = current_app.login_manager._session_identifier_generator() + user_login_confirmed.send(current_app._get_current_object()) + + +def login_required(func): + @wraps(func) + def decorated_view(*args, **kwargs): + if request.method in EXEMPT_METHODS: + return func(*args, **kwargs) + elif current_app.config.get('LOGIN_DISABLED'): + return func(*args, **kwargs) + elif not current_user.is_authenticated: + return current_app.login_manager.unauthorized() + return func(*args, **kwargs) + return decorated_view + + +## ... source file continues with no further session examples... + +``` + + +## Example 7 from Flask-WTF +[Flask-WTF](https://github.com/lepture/flask-wtf) +([project documentation](https://flask-wtf.readthedocs.io/) +and +[PyPI page](https://pypi.org/project/Flask-WTF/)) +provides a bridge between [Flask](/flask.html) and the the +[WTForms](https://wtforms.readthedocs.io/en/2.3.x/) form-handling library. +It makes it easier to use WTForms by reducing boilerplate code and +shorter examples for common form operations as well as common security +practices such as [CSRF](/cross-site-request-forgery-csrf.html). + +[**Flask-WTF / flask_wtf / csrf.py**](https://github.com/lepture/flask-wtf/blob/master/flask_wtf/./csrf.py) + +```python +# csrf.py +import hashlib +import logging +import os +import warnings +from urllib.parse import urlparse +from functools import wraps + +~~from flask import Blueprint, current_app, g, request, session +from itsdangerous import BadData, SignatureExpired, URLSafeTimedSerializer +from werkzeug.exceptions import BadRequest +from werkzeug.security import safe_str_cmp +from wtforms import ValidationError +from wtforms.csrf.core import CSRF + +from ._compat import FlaskWTFDeprecationWarning + +__all__ = ('generate_csrf', 'validate_csrf', 'CSRFProtect') +logger = logging.getLogger(__name__) + + +def generate_csrf(secret_key=None, token_key=None): + + secret_key = _get_config( + secret_key, 'WTF_CSRF_SECRET_KEY', current_app.secret_key, + message='A secret key is required to use CSRF.' + ) + field_name = _get_config( + token_key, 'WTF_CSRF_FIELD_NAME', 'csrf_token', + message='A field name is required to use CSRF.' + ) + + if field_name not in g: + s = URLSafeTimedSerializer(secret_key, salt='wtf-csrf-token') + +~~ if field_name not in session: + session[field_name] = hashlib.sha1(os.urandom(64)).hexdigest() + + try: + token = s.dumps(session[field_name]) + except TypeError: + session[field_name] = hashlib.sha1(os.urandom(64)).hexdigest() + token = s.dumps(session[field_name]) + + setattr(g, field_name, token) + + return g.get(field_name) + + +def validate_csrf(data, secret_key=None, time_limit=None, token_key=None): + + secret_key = _get_config( + secret_key, 'WTF_CSRF_SECRET_KEY', current_app.secret_key, + message='A secret key is required to use CSRF.' + ) + field_name = _get_config( + token_key, 'WTF_CSRF_FIELD_NAME', 'csrf_token', + message='A field name is required to use CSRF.' + ) + time_limit = _get_config( + time_limit, 'WTF_CSRF_TIME_LIMIT', 3600, required=False + ) + + if not data: + raise ValidationError('The CSRF token is missing.') + +~~ if field_name not in session: + raise ValidationError('The CSRF session token is missing.') + + s = URLSafeTimedSerializer(secret_key, salt='wtf-csrf-token') + + try: + token = s.loads(data, max_age=time_limit) + except SignatureExpired: + raise ValidationError('The CSRF token has expired.') + except BadData: + raise ValidationError('The CSRF token is invalid.') + + if not safe_str_cmp(session[field_name], token): + raise ValidationError('The CSRF tokens do not match.') + + +def _get_config( + value, config_name, default=None, + required=True, message='CSRF is not configured.' +): + + if value is None: + value = current_app.config.get(config_name, default) + + if required and value is None: + + +## ... source file continues with no further session examples... + +``` + + +## Example 8 from flaskSaaS +[flaskSaas](https://github.com/alectrocute/flaskSaaS) is a boilerplate +starter project to build a software-as-a-service (SaaS) web application +in [Flask](/flask.html), with [Stripe](/stripe.html) for billing. The +boilerplate relies on many common Flask extensions such as +[Flask-WTF](https://flask-wtf.readthedocs.io/), +[Flask-Login](https://flask-login.readthedocs.io/en/latest/), +[Flask-Admin](https://flask-admin.readthedocs.io/en/latest/), and +many others. The project is provided as open source under the +[MIT license](https://github.com/alectrocute/flaskSaaS/blob/master/LICENSE). + +[**flaskSaaS / app / logger_setup.py**](https://github.com/alectrocute/flaskSaaS/blob/master/app/./logger_setup.py) + +```python +# logger_setup.py + +import datetime as dt +import logging +from logging.handlers import RotatingFileHandler +import pytz + +~~from flask import request, session +from structlog import wrap_logger +from structlog.processors import JSONRenderer + +from app import app + +app.logger.setLevel(app.config['LOG_LEVEL']) + +app.logger.removeHandler(app.logger.handlers[0]) + +TZ = pytz.timezone(app.config['TIMEZONE']) + + +def add_fields(_, level, event_dict): + now = dt.datetime.now() + event_dict['timestamp'] = TZ.localize(now, True).astimezone(pytz.utc).isoformat() + event_dict['level'] = level + + if session: +~~ event_dict['session_id'] = session.get('session_id') + + if request: + try: + event_dict['ip_address'] = request.headers['X-Forwarded-For'].split(',')[0].strip() + except: + event_dict['ip_address'] = 'unknown' + + return event_dict + + +if app.config.get('LOG_FILENAME'): + file_handler = RotatingFileHandler(filename=app.config['LOG_FILENAME'], + maxBytes=app.config['LOG_MAXBYTES'], + backupCount=app.config['LOG_BACKUPS'], + mode='a', + encoding='utf-8') + file_handler.setLevel(logging.DEBUG) + app.logger.addHandler(file_handler) + +logger = wrap_logger( + app.logger, + processors=[ + add_fields, + JSONRenderer(indent=None) + + +## ... source file continues with no further session examples... + +``` + + +## Example 9 from Flask-Security-Too +[Flask-Security-Too](https://github.com/Flask-Middleware/flask-security/) +([PyPi page](https://pypi.org/project/Flask-Security-Too/) and +[project documentation](https://flask-security-too.readthedocs.io/en/stable/)) +is a maintained fork of the original +[Flask-Security](https://github.com/mattupstate/flask-security) project that +makes it easier to add common security features to [Flask](/flask.html) +web applications. A few of the critical goals of the Flask-Security-Too +project are ensuring JavaScript client-based single-page applications (SPAs) +can work securely with Flask-based backends and that guidance by the +[OWASP](https://owasp.org/) organization is followed by default. + +The Flask-Security-Too project is provided as open source under the +[MIT license](https://github.com/Flask-Middleware/flask-security/blob/master/LICENSE). + +[**Flask-Security-Too / flask_security / twofactor.py**](https://github.com/Flask-Middleware/flask-security/blob/master/flask_security/./twofactor.py) + +```python +# twofactor.py + +import typing as t + +~~from flask import current_app as app, redirect, request, session +from werkzeug.datastructures import MultiDict + +from .proxies import _security, _datastore +from .utils import ( + SmsSenderFactory, + base_render_json, + check_and_get_token_status, + config_value, + do_flash, + get_within_delta, + login_user, + json_error_response, + send_mail, + url_for_security, +) +from .signals import ( + tf_code_confirmed, + tf_disabled, + tf_security_token_sent, + tf_profile_changed, +) + +if t.TYPE_CHECKING: # pragma: no cover + from flask import Response + + +def tf_clean_session(): + if config_value("TWO_FACTOR"): + for k in [ + "tf_state", + "tf_user_id", + "tf_primary_method", + "tf_remember_login", + "tf_totp_secret", + ]: +~~ session.pop(k, None) + + +def tf_send_security_token(user, method, totp_secret, phone_number): + token_to_be_sent = _security._totp_factory.generate_totp_password(totp_secret) + if method == "email" or method == "mail": + send_mail( + config_value("EMAIL_SUBJECT_TWO_FACTOR"), + user.email, + "two_factor_instructions", + user=user, + token=token_to_be_sent, + username=user.calc_username(), + ) + elif method == "sms": + msg = "Use this code to log in: %s" % token_to_be_sent + from_number = config_value("SMS_SERVICE_CONFIG")["PHONE_NUMBER"] + to_number = phone_number + sms_sender = SmsSenderFactory.createSender(config_value("SMS_SERVICE")) + sms_sender.send_sms(from_number=from_number, to_number=to_number, msg=msg) + + elif method == "google_authenticator" or method == "authenticator": + pass + tf_security_token_sent.send( + app._get_current_object(), + + +## ... source file continues with no further session examples... + +``` + + +## Example 10 from Flask-SocketIO +[Flask-SocketIO](https://github.com/miguelgrinberg/Flask-SocketIO) +([PyPI package information](https://pypi.org/project/Flask-SocketIO/), +[official tutorial](https://blog.miguelgrinberg.com/post/easy-websockets-with-flask-and-gevent) +and +[project documentation](https://flask-socketio.readthedocs.io/en/latest/)) +is a code library by [Miguel Grinberg](https://blog.miguelgrinberg.com/index) +that provides Socket.IO integration for [Flask](/flask.html) applications. +This extension makes it easier to add bi-directional communications on the +web via the [WebSockets](/websockets.html) protocol. + +The Flask-SocketIO project is open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/LICENSE). + +[**Flask-SocketIO / example / sessions.py**](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/./example/sessions.py) + +```python +# sessions.py +~~from flask import Flask, render_template, session, request, jsonify +from flask_login import LoginManager, UserMixin, current_user, login_user, \ + logout_user +from flask_session import Session +from flask_socketio import SocketIO, emit + +app = Flask(__name__) +app.config['SECRET_KEY'] = 'top-secret!' +app.config['SESSION_TYPE'] = 'filesystem' +login = LoginManager(app) +Session(app) +socketio = SocketIO(app, manage_session=False) + + +class User(UserMixin, object): + def __init__(self, id=None): + self.id = id + + +@login.user_loader +def load_user(id): + return User(id) + + +@app.route('/') +def index(): + return render_template('sessions.html') + + +@app.route('/session', methods=['GET', 'POST']) +def session_access(): + if request.method == 'GET': + return jsonify({ +~~ 'session': session.get('value', ''), + 'user': current_user.id + if current_user.is_authenticated else 'anonymous' + }) + data = request.get_json() + if 'session' in data: + session['value'] = data['session'] + elif 'user' in data: + if data['user']: + login_user(User(data['user'])) + else: + logout_user() + return '', 204 + + +@socketio.on('get-session') +def get_session(): + emit('refresh-session', { +~~ 'session': session.get('value', ''), + 'user': current_user.id + if current_user.is_authenticated else 'anonymous' + }) + + +@socketio.on('set-session') +def set_session(data): + if 'session' in data: + session['value'] = data['session'] + elif 'user' in data: + if data['user'] is not None: + login_user(User(data['user'])) + else: + logout_user() + + +if __name__ == '__main__': + socketio.run(app) + + + +## ... source file continues with no further session examples... + +``` + + +## Example 11 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / user_manager.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/./user_manager.py) + +```python +# user_manager.py + + +import datetime + +~~from flask import abort, Blueprint, current_app, Flask, session +from flask_login import LoginManager +from wtforms import ValidationError + +from . import ConfigError +from . import forms +from .db_manager import DBManager +from .email_manager import EmailManager +from .password_manager import PasswordManager +from .token_manager import TokenManager +from .translation_utils import lazy_gettext as _ # map _() to lazy_gettext() +from .user_manager__settings import UserManager__Settings +from .user_manager__utils import UserManager__Utils +from .user_manager__views import UserManager__Views + + +class UserManager(UserManager__Settings, UserManager__Utils, UserManager__Views): + + def __init__(self, app, db, UserClass, **kwargs): + + self.app = app + if app: + self.init_app(app, db, UserClass, **kwargs) + + def init_app( + + +## ... source file abbreviated to get to session examples ... + + + if attrib_name[0:5] == 'USER_': + default_value = getattr(UserManager, attrib_name) + setattr(self, attrib_name, app.config.get(attrib_name, default_value)) + + if not self.USER_EMAIL_SENDER_EMAIL: + default_sender = app.config.get('DEFAULT_MAIL_SENDER', None) + default_sender = app.config.get('MAIL_DEFAULT_SENDER', default_sender) + if default_sender: + if default_sender[-1:] == '>': + start = default_sender.rfind('<') + if start >= 1: + self.USER_EMAIL_SENDER_EMAIL = default_sender[start + 1:-1] + if not self.USER_EMAIL_SENDER_NAME: + self.USER_EMAIL_SENDER_NAME = default_sender[0:start].strip(' "') + else: + self.USER_EMAIL_SENDER_EMAIL = default_sender + + if not self.USER_EMAIL_SENDER_NAME: + self.USER_EMAIL_SENDER_NAME = self.USER_APP_NAME + + if self.USER_USER_SESSION_EXPIRATION: + app.permanent_session_lifetime = datetime.timedelta(seconds=self.USER_USER_SESSION_EXPIRATION) + + @app.before_request + def advance_session_timeout(): +~~ session.permanent = True # Timeout after app.permanent_session_lifetime period +~~ session.modified = True # Advance session timeout each time a user visits a page + + self.login_manager = LoginManager(app) + self.login_manager.login_view = 'user.login' + + @self.login_manager.user_loader + def load_user_by_user_token(user_token): + user = self.db_manager.UserClass.get_user_by_token(user_token) + return user + + self.babel = app.extensions.get('babel', None) + from .translation_utils import init_translations + init_translations(self.babel) + + if not hasattr(app.jinja_env, 'install_gettext_callables'): + app.jinja_env.add_extension('jinja2.ext.i18n') + app.jinja_env.install_null_translations() + + def flask_user_context_processor(): + def call_or_get(function_or_property): + return function_or_property() if callable(function_or_property) else function_or_property + + return dict( + user_manager=current_app.user_manager, + call_or_get=call_or_get, + + +## ... source file continues with no further session examples... + +``` + + +## Example 12 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / util / i18n.py**](https://github.com/indico/indico/blob/master/indico/util/i18n.py) + +```python +# i18n.py + +import ast +import re +from collections import Counter +from contextlib import contextmanager + +from babel import negotiate_locale +from babel.core import LOCALE_ALIASES, Locale +from babel.messages.pofile import read_po +from babel.support import NullTranslations +~~from flask import current_app, g, has_app_context, has_request_context, request, session +from flask_babel import Babel, Domain, get_domain +from flask_pluginengine import current_plugin +from speaklater import is_lazy_string, make_lazy_string +from werkzeug.utils import cached_property + +from indico.core.config import config +from indico.util.caching import memoize_request + + +LOCALE_ALIASES = dict(LOCALE_ALIASES, en='en_GB') +RE_TR_FUNCTION = re.compile(r'''_\("([^"]*)"\)|_\('([^']*)'\)''', re.DOTALL | re.MULTILINE) + +babel = Babel() +_use_context = object() + + +def get_translation_domain(plugin_name=_use_context): + if plugin_name is None: + return get_domain() + else: + plugin = None + if has_app_context(): + from indico.core.plugins import plugin_engine + plugin = plugin_engine.get_plugin(plugin_name) if plugin_name is not _use_context else current_plugin + + +## ... source file abbreviated to get to session examples ... + + + + def weekday(self, daynum, short=True): + return self.days['format']['abbreviated' if short else 'wide'][daynum] + + @cached_property + def time_formats(self): + formats = super().time_formats + for k, v in formats.items(): + v.format = v.format.replace(':%(ss)s', '') + return formats + + +def _remove_locale_script(locale): + parts = locale.split('_') # e.g. `en_GB` or `zh_Hans_CN` + return f'{parts[0]}_{parts[-1]}' + + +@babel.localeselector +def set_best_lang(check_session=True): + from indico.core.config import config + + if not has_request_context(): + return 'en_GB' if current_app.config['TESTING'] else config.DEFAULT_LOCALE + elif 'lang' in g: + return g.lang +~~ elif check_session and session.lang is not None: +~~ return session.lang + + all_locales = {_remove_locale_script(loc).lower(): loc for loc in get_all_locales()} + + preferred = [x.replace('-', '_') for x in request.accept_languages.values()] + resolved_lang = negotiate_locale(preferred, list(all_locales), aliases=LOCALE_ALIASES) + + if not resolved_lang: + if current_app.config['TESTING']: + return 'en_GB' + + resolved_lang = config.DEFAULT_LOCALE + + try: + resolved_lang = all_locales[resolved_lang.lower()] + except KeyError: + return 'en_GB' + + resolved_lang = re.sub(r'^([a-zA-Z]+)_([a-zA-Z]+)$', + lambda m: f'{m.group(1).lower()}_{m.group(2).upper()}', + resolved_lang) + + g.lang = resolved_lang + return resolved_lang + + +@memoize_request +def get_current_locale(): + return IndicoLocale.parse(set_best_lang()) + + +def get_all_locales(): + if babel.app is None: + return {} + else: + missing = object() + languages = {str(t): config.CUSTOM_LANGUAGES.get(str(t), (t.language_name.title(), t.territory_name)) + for t in babel.list_translations() + if config.CUSTOM_LANGUAGES.get(str(t), missing) is not None} + counts = Counter(x[0] for x in languages.values()) + return {code: (name, territory, counts[name] > 1) for code, (name, territory) in languages.items()} + + +def set_session_lang(lang): +~~ session.lang = lang + + +@contextmanager +def session_language(lang): +~~ old_lang = session.lang + + set_session_lang(lang) + yield + set_session_lang(old_lang) + + +def parse_locale(locale): + return IndicoLocale.parse(locale) + + +def extract_node(node, keywords, commentTags, options, parents=[None]): + if isinstance(node, ast.Str) and isinstance(parents[-1], (ast.Assign, ast.Call)): + matches = RE_TR_FUNCTION.findall(node.s) + for m in matches: + line = m[0] or m[1] + yield (node.lineno, '', line.split('\n'), ['old style recursive strings']) + else: + for cnode in ast.iter_child_nodes(node): + yield from extract_node(cnode, keywords, commentTags, options, parents=(parents + [node])) + + +def po_to_json(po_file, locale=None, domain=None): + with open(po_file, 'rb') as f: + po_data = read_po(f, locale=locale, domain=domain) + + +## ... source file continues with no further session examples... + +``` + + +## Example 13 from tedivms-flask +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + +[**tedivms-flask / app / __init__.py**](https://github.com/tedivm/tedivms-flask/blob/master/app/./__init__.py) + +```python +# __init__.py +import boto3 +from celery import Celery +from datetime import datetime +import os +import requests +import yaml + +from flask import Flask, render_template +~~from flask import session as current_session +from flask_mail import Mail +from flask_migrate import Migrate, MigrateCommand +from flask.sessions import SessionInterface +from flask_sqlalchemy import SQLAlchemy +from flask_user import user_logged_out +from flask_wtf.csrf import CSRFProtect + +from beaker.cache import CacheManager +from beaker.util import parse_cache_config_options +from beaker.middleware import SessionMiddleware + +db = SQLAlchemy() +csrf_protect = CSRFProtect() +mail = Mail() +migrate = Migrate() + + +def get_config(): + app = Flask(__name__) + + app.config.from_object('app.settings') + if 'APPLICATION_SETTINGS' in os.environ: + app.config.from_envvar(os.environ['APPLICATION_SETTINGS']) + if 'AWS_SECRETS_MANAGER_CONFIG' in os.environ: + + +## ... source file abbreviated to get to session examples ... + + + if 'CACHE_TYPE' not in app.config or not app.config['CACHE_TYPE']: + app.config['CACHE_TYPE'] = 'file' + + if app.config['CACHE_TYPE'] == 'file': + if 'CACHE_ROOT' not in app.config or not app.config['CACHE_ROOT']: + app.config['CACHE_ROOT'] = '/tmp/%s' % __name__ + + session_opts['session.type'] = app.config['CACHE_TYPE'] + + if 'CACHE_ROOT' in app.config and app.config['CACHE_ROOT']: + session_opts['session.data_dir'] = app.config['CACHE_ROOT'] + '/session' + + if 'CACHE_URL' in app.config and app.config['CACHE_URL']: + session_opts['session.url'] = app.config['CACHE_URL'] + + session_opts['session.auto'] = app.config.get('SESSION_AUTO', True) + session_opts['session.cookie_expires'] = app.config.get('SESSION_COOKIE_EXPIRES', 86400) + session_opts['session.secret'] = app.secret_key + + class BeakerSessionInterface(SessionInterface): + def open_session(self, app, request): + session = request.environ['beaker.session'] + return session + + def save_session(self, app, session, response): +~~ session.save() + + app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts) + app.session_interface = BeakerSessionInterface() + + @user_logged_out.connect_via(app) + def clear_session(sender, user, **extra): + current_session.clear() + + +def init_celery_service(app): + celery.conf.update(app.config) + + +def init_error_handlers(app): + + def show_error(status, message='An unknown error has occured.'): + return render_template('pages/errors.html', error_code=status, message=message), status + + @app.errorhandler(401) + def error_unauthorized(e): + return show_error(401, 'Unauthorized') + + @app.errorhandler(403) + def error_forbidden(e): + + +## ... source file continues with no further session examples... + +``` + + +## Example 14 from trape +[trape](https://github.com/jofpin/trape) is a research tool for tracking +people's activities that are logged digitally. The tool uses +[Flask](/flask.html) to create a web front end to view aggregated data +on an individual the application is set to track. The source code is +provided as open source under the MIT license, according to the +[README](https://github.com/jofpin/trape/blob/master/README.md). + +[**trape / core / sockets.py**](https://github.com/jofpin/trape/blob/master/./core/sockets.py) + +```python +# sockets.py +from socket import gethostname, gethostbyname +from threading import Lock +~~from flask import Flask, render_template, session, request, json +from flask_socketio import SocketIO, emit, join_room, rooms, disconnect +import core.stats +import core.user +from core.user_objects import attacks_hook_message +from core.utils import utils +from core.db import Database +import sys + +trape = core.stats.trape +app = core.stats.app + +db = Database() + +async_mode = None +socketio = SocketIO(app, async_mode=async_mode) +thread = None +thread_lock = Lock() + +db.sentences_victim('clean_online', None, 2) + +def background_thread(): + count = 0 + +@socketio.on("join", namespace="/trape") +def join(message): + try: + join_room(message['room']) +~~ session['receive_count'] = session.get('receive_count', 0) + 1 + except Exception as error: + pass + +@socketio.on("my_room_event", namespace="/trape") +def send_room_message(message): + try: +~~ session['receive_count'] = session.get('receive_count', 0) + 1 + hookAction = attacks_hook_message(message['data']['type']) + utils.Go(utils.Color['white'] + "[" + utils.Color['blueBold'] + "@" + utils.Color['white'] + "]" + " " + hookAction + utils.Color['blue'] + message['data']['message'] + utils.Color['white'] + ' in ' + utils.Color['green'] + message['room'] + utils.Color['white']) + emit('my_response', {'data': message['data'], 'count': session['receive_count']},room = message['room']) + except Exception as error: + pass + +@socketio.on("disconnect_request", namespace="/trape") +def disconnect_request(d): + try: +~~ session['receive_count'] = session.get('receive_count', 0) + 1 + emit('my_response', {'data': 'Disconnected!', 'count': session['receive_count']}) + utils.Go(utils.Color['white'] + "[" + utils.Color['redBold'] + "-" + utils.Color['white'] + "]" + utils.Color['red'] + " " + "A victim has closed her connection with the following id:" + " " + utils.Color['green'] + d['vId'] + utils.Color['white']) + db.sentences_victim('disconnect_victim', d['vId'], 2) + except Exception as error: + pass + +@socketio.on("error", namespace="/trape") +def socket_def_error(d): + pass + +@socketio.on_error("/trape") +def error_handler(e): + pass + +@app.route("/" + trape.home_path) +def home(): + gMaps_free_api_key = 'AIzaSyBUPHAjZl3n8Eza66ka6B78iVyPteC5MgM' + if (trape.gmaps != ''): + gMaps_free_api_key = trape.gmaps + + shorten_api = 'AIzaSyCPzcppCT27KTHnxAIQvYhtvB_l8sKGYBs' + + html = trape.injectCSS_Paths(render_template("home.html", async_mode=socketio.async_mode).replace('[OWN_API_KEY_HERE]', gMaps_free_api_key).replace('[LIBS_SRC]', trape.JSFiles[1]['src']).replace('[TRAPE_SRC]', trape.JSFiles[4]['src'])) + return html + + +## ... source file continues with no further session examples... + +``` + diff --git a/content/pages/examples/flask/flask-helpers-flash.markdown b/content/pages/examples/flask/flask-helpers-flash.markdown new file mode 100644 index 000000000..346bb3f6b --- /dev/null +++ b/content/pages/examples/flask/flask-helpers-flash.markdown @@ -0,0 +1,1642 @@ +title: flask.helpers flash Example Code +category: page +slug: flask-helpers-flash-examples +sortorder: 500021018 +toc: False +sidebartitle: flask.helpers flash +meta: Python example code that shows how to use the flash callable from the flask.helpers module of the Flask project. + + +[flash](https://github.com/pallets/flask/blob/master/src/flask/helpers.py) +is a function within the `flask.helpers` module of the [Flask](/flask.html) +framework. `flash` passes a string message to the *next* request. The +following request can access it in a template by using the +`get_flashed_messages` function. + +`flash` can also be imported directly from the `flask` module instead +of `flask.helpers` so you will often see that shortcut in example code. + +get_root_path, +make_response, +safe_join, +send_file, +and url_for +are several other callables with code examples from the same `flask.helpers` package. + +## Example 1 from Braintree Flask app +[Braintree's Flask example payments app](https://github.com/braintree/braintree_flask_example) +demonstrates how to incorporate this payment provider's +[API](/application-programming-interfaces.html) into your +[Flask](/flask.html) [web application](/web-development.html). +The code is open sourced under the +[MIT license](https://github.com/braintree/braintree_flask_example/blob/master/LICENSE). + +[**Braintree Flask app / app.py**](https://github.com/braintree/braintree_flask_example/blob/master/././app.py) + +```python +# app.py +~~from flask import Flask, redirect, url_for, render_template, request, flash + +import os +from os.path import join, dirname +from dotenv import load_dotenv +import braintree +from gateway import generate_client_token, transact, find_transaction + +load_dotenv() + +app = Flask(__name__) +app.secret_key = os.environ.get('APP_SECRET_KEY') + +PORT = int(os.environ.get('PORT', 4567)) + +TRANSACTION_SUCCESS_STATUSES = [ + braintree.Transaction.Status.Authorized, + braintree.Transaction.Status.Authorizing, + braintree.Transaction.Status.Settled, + braintree.Transaction.Status.SettlementConfirmed, + braintree.Transaction.Status.SettlementPending, + braintree.Transaction.Status.Settling, + braintree.Transaction.Status.SubmittedForSettlement +] + + + +## ... source file abbreviated to get to flash examples ... + + + 'icon': 'success', + 'message': 'Your test transaction has been successfully processed. See the Braintree API response and try again.' + } + else: + result = { + 'header': 'Transaction Failed', + 'icon': 'fail', + 'message': 'Your test transaction has a status of ' + transaction.status + '. See the Braintree API response and try again.' + } + + return render_template('checkouts/show.html', transaction=transaction, result=result) + +@app.route('/checkouts', methods=['POST']) +def create_checkout(): + result = transact({ + 'amount': request.form['amount'], + 'payment_method_nonce': request.form['payment_method_nonce'], + 'options': { + "submit_for_settlement": True + } + }) + + if result.is_success or result.transaction: + return redirect(url_for('show_checkout',transaction_id=result.transaction.id)) + else: +~~ for x in result.errors.deep_errors: flash('Error: %s: %s' % (x.code, x.message)) + return redirect(url_for('new_checkout')) + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=PORT, debug=True) + + + +## ... source file continues with no further flash examples... + +``` + + +## Example 2 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / security / registerviews.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/security/registerviews.py) + +```python +# registerviews.py +__author__ = "Daniel Gaspar" + +import logging + +~~from flask import flash, redirect, request, session, url_for +from flask_babel import lazy_gettext + +from .forms import LoginForm_oid, RegisterUserDBForm, RegisterUserOIDForm +from .. import const as c +from .._compat import as_unicode +from ..validators import Unique +from ..views import expose, PublicFormView + +log = logging.getLogger(__name__) + + +def get_first_last_name(fullname): + names = fullname.split() + if len(names) > 1: + return names[0], " ".join(names[1:]) + elif names: + return names[0], "" + + +class BaseRegisterUser(PublicFormView): + + route_base = "/register" + email_template = "appbuilder/general/security/register_mail.html" + email_subject = lazy_gettext("Account activation") + + +## ... source file abbreviated to get to flash examples ... + + + ".activation", + _external=True, + activation_hash=register_user.registration_hash, + ) + msg.html = self.render_template( + self.email_template, + url=url, + username=register_user.username, + first_name=register_user.first_name, + last_name=register_user.last_name, + ) + msg.recipients = [register_user.email] + try: + mail.send(msg) + except Exception as e: + log.error("Send email exception: {0}".format(str(e))) + return False + return True + + def add_registration(self, username, first_name, last_name, email, password=""): + register_user = self.appbuilder.sm.add_register_user( + username, first_name, last_name, email, password + ) + if register_user: + if self.send_email(register_user): +~~ flash(as_unicode(self.message), "info") + return register_user + else: +~~ flash(as_unicode(self.error_message), "danger") + self.appbuilder.sm.del_register_user(register_user) + return None + + @expose("/activation/") + def activation(self, activation_hash): + reg = self.appbuilder.sm.find_register_user(activation_hash) + if not reg: + log.error(c.LOGMSG_ERR_SEC_NO_REGISTER_HASH.format(activation_hash)) +~~ flash(as_unicode(self.false_error_message), "danger") + return redirect(self.appbuilder.get_url_for_index) + if not self.appbuilder.sm.add_user( + username=reg.username, + email=reg.email, + first_name=reg.first_name, + last_name=reg.last_name, + role=self.appbuilder.sm.find_role( + self.appbuilder.sm.auth_user_registration_role + ), + hashed_password=reg.password, + ): +~~ flash(as_unicode(self.error_message), "danger") + return redirect(self.appbuilder.get_url_for_index) + else: + self.appbuilder.sm.del_register_user(reg) + return self.render_template( + self.activation_template, + username=reg.username, + first_name=reg.first_name, + last_name=reg.last_name, + appbuilder=self.appbuilder, + ) + + def add_form_unique_validations(self, form): + datamodel_user = self.appbuilder.sm.get_user_datamodel + datamodel_register_user = self.appbuilder.sm.get_register_user_datamodel + if len(form.username.validators) == 1: + form.username.validators.append(Unique(datamodel_user, "username")) + form.username.validators.append(Unique(datamodel_register_user, "username")) + if len(form.email.validators) == 2: + form.email.validators.append(Unique(datamodel_user, "email")) + form.email.validators.append(Unique(datamodel_register_user, "email")) + + +class RegisterUserDBView(BaseRegisterUser): + + + +## ... source file abbreviated to get to flash examples ... + + + form = LoginForm_oid() + if form.validate_on_submit(): + session["remember_me"] = form.remember_me.data + return self.appbuilder.sm.oid.try_login( + form.openid.data, ask_for=["email", "fullname"] + ) + resp = session.pop("oid_resp", None) + if resp: + self._init_vars() + form = self.form.refresh() + self.form_get(form) + form.username.data = resp.email + first_name, last_name = get_first_last_name(resp.fullname) + form.first_name.data = first_name + form.last_name.data = last_name + form.email.data = resp.email + widgets = self._get_edit_widget(form=form) + return self.render_template( + self.form_template, + title=self.form_title, + widgets=widgets, + form_action="form", + appbuilder=self.appbuilder, + ) + else: +~~ flash(as_unicode(self.error_message), "warning") + return redirect(self.get_redirect()) + + def oid_login_handler(self, f, oid): + from flask_openid import OpenIDResponse, SessionWrapper + from openid.consumer.consumer import CANCEL, Consumer, SUCCESS + + if request.args.get("openid_complete") != u"yes": + return f(False) + consumer = Consumer(SessionWrapper(self), oid.store_factory()) + openid_response = consumer.complete( + request.args.to_dict(), oid.get_current_url() + ) + if openid_response.status == SUCCESS: + return self.after_login(OpenIDResponse(openid_response, [])) + elif openid_response.status == CANCEL: + oid.signal_error(u"The request was cancelled") + return redirect(oid.get_current_url()) + oid.signal_error(u"OpenID authentication error") + return redirect(oid.get_current_url()) + + def after_login(self, resp): + session["oid_resp"] = resp + + def form_get(self, form): + + +## ... source file continues with no further flash examples... + +``` + + +## Example 3 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / auth / plugins.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/auth/plugins.py) + +```python +# plugins.py +~~from flask import flash, redirect, url_for +from flask_login import current_user, logout_user + +from . import impl +from ..core.auth.authentication import ForceLogout +from ..extensions import db +from ..user.models import User +from ..utils.settings import flaskbb_config +from .services.authentication import ( + BlockUnactivatedUser, + ClearFailedLogins, + DefaultFlaskBBAuthProvider, + MarkFailedLogin, +) +from .services.factories import account_activator_factory +from .services.reauthentication import ( + ClearFailedLoginsOnReauth, + DefaultFlaskBBReauthProvider, + MarkFailedReauth, +) +from .services.registration import ( + AutoActivateUserPostProcessor, + AutologinPostProcessor, + EmailUniquenessValidator, + SendActivationPostProcessor, + + +## ... source file abbreviated to get to flash examples ... + + + + +@impl(trylast=True) +def flaskbb_reauth_attempt(user, secret): + return DefaultFlaskBBReauthProvider().reauthenticate(user, secret) + + +@impl +def flaskbb_reauth_failed(user): + MarkFailedReauth().handle_reauth_failure(user) + + +@impl +def flaskbb_post_reauth(user): + ClearFailedLoginsOnReauth().handle_post_reauth(user) + + +@impl +def flaskbb_errorhandlers(app): + + @app.errorhandler(ForceLogout) + def handle_force_logout(error): + if current_user: + logout_user() + if error.reason: +~~ flash(error.reason, "danger") + return redirect(url_for("forum.index")) + + +@impl +def flaskbb_gather_registration_validators(): + blacklist = [ + w.strip() for w in flaskbb_config["AUTH_USERNAME_BLACKLIST"].split(",") + ] + + requirements = UsernameRequirements( + min=flaskbb_config["AUTH_USERNAME_MIN_LENGTH"], + max=flaskbb_config["AUTH_USERNAME_MAX_LENGTH"], + blacklist=blacklist, + ) + + return [ + EmailUniquenessValidator(User), + UsernameUniquenessValidator(User), + UsernameValidator(requirements), + ] + + +@impl +def flaskbb_registration_post_processor(user): + + +## ... source file continues with no further flash examples... + +``` + + +## Example 4 from flask-bones +[flask-bones](https://github.com/cburmeister/flask-bones) +([demo](http://flask-bones.herokuapp.com/)) +is large scale [Flask](/flask.html) example application built +with [Blueprints](https://flask.palletsprojects.com/en/1.1.x/blueprints/) +([example Blueprint code](/flask-blueprints-blueprint-examples.html)). +This project is provided as open source under the +[MIT license](https://github.com/cburmeister/flask-bones/blob/master/LICENSE). + +[**flask-bones / app / user / views.py**](https://github.com/cburmeister/flask-bones/blob/master/app/user/views.py) + +```python +# views.py +~~from flask import request, redirect, url_for, render_template, flash, g +from flask_babel import gettext +from flask_login import login_required +from app.user.models import User +from .forms import EditUserForm + +from ..user import user + + +@user.route('/list', methods=['GET', 'POST']) +@login_required +def list(): + + from app.database import DataTable + datatable = DataTable( + model=User, + columns=[User.remote_addr], + sortable=[User.username, User.email, User.created_ts], + searchable=[User.username, User.email], + filterable=[User.active], + limits=[25, 50, 100], + request=request + ) + + if g.pjax: + return render_template('users.html', datatable=datatable) + + return render_template('list.html', datatable=datatable) + + +@user.route('/edit/', methods=['GET', 'POST']) +@login_required +def edit(id): + user = User.query.filter_by(id=id).first_or_404() + form = EditUserForm(obj=user) + if form.validate_on_submit(): + form.populate_obj(user) + user.update() +~~ flash( + gettext('User {username} edited'.format(username=user.username)), + 'success' + ) + return render_template('edit.html', form=form, user=user) + + +@user.route('/delete/', methods=['GET']) +@login_required +def delete(id): + user = User.query.filter_by(id=id).first_or_404() + user.delete() +~~ flash( + gettext('User {username} deleted').format(username=user.username), + 'success' + ) + return redirect(url_for('.list')) + + + +## ... source file continues with no further flash examples... + +``` + + +## Example 5 from flask-bookshelf +[flask-bookshelf](https://github.com/damyanbogoev/flask-bookshelf) is the +example [Flask](/flask.html) application that developers create when +going through +[this Flask series of blog posts](https://damyanon.net/tags/flask-series/). + +[**flask-bookshelf / bookshelf / admin / controllers.py**](https://github.com/damyanbogoev/flask-bookshelf/blob/master/bookshelf/admin/controllers.py) + +```python +# controllers.py +from sqlalchemy import exc +~~from flask import Blueprint, render_template, flash +from flask import current_app, redirect, request, url_for +from flask_security.decorators import roles_required +from bookshelf.admin.forms.author_forms import CreateAuthorForm +from bookshelf.cache import cache +from bookshelf.data.models import Author, db + + +admin = Blueprint("admin", __name__, template_folder="templates") + + +@admin.route("/") +@roles_required("admin") +def index(): + return render_template("admin_index.htm") + + +@admin.route("/author/create", methods=["GET", "POST"]) +@roles_required("admin") +def create_author(): + form = CreateAuthorForm(request.form) + if request.method == "POST" and form.validate(): + names = form.names.data + current_app.logger.info("Adding a new author %s.", (names)) + author = Author(names) + + try: + db.session.add(author) + db.session.commit() + cache.clear() +~~ flash("Author successfully created.") + except exc.SQLAlchemyError as e: +~~ flash("Author was not created.") + current_app.logger.error(e) + + return redirect(url_for("admin.create_author")) + + return redirect(url_for("main.display_authors")) + + return render_template("create_author.htm", form=form) + + + +## ... source file continues with no further flash examples... + +``` + + +## Example 6 from flask_jsondash +[Flask JSONDash](https://github.com/christabor/flask_jsondash) is a +configurable web application built in Flask that creates charts and +dashboards from arbitrary API endpoints. Everything for the web app +is configured in JSON. The code is provided as open source under the +[MIT license](https://github.com/christabor/flask_jsondash/blob/master/LICENSE). + +[**flask_jsondash / flask_jsondash / charts_builder.py**](https://github.com/christabor/flask_jsondash/blob/master/flask_jsondash/./charts_builder.py) + +```python +# charts_builder.py + + +import json +import os +import uuid +from datetime import datetime as dt + +import jinja2 +~~from flask import (Blueprint, current_app, flash, redirect, render_template, + request, send_from_directory, url_for) + +from flask_jsondash import static, templates + +from flask_jsondash import db +from flask_jsondash import settings +from flask_jsondash.utils import setting +from flask_jsondash.utils import adapter +from flask_jsondash import utils +from flask_jsondash.schema import ( + validate_raw_json, InvalidSchemaError, +) + +TEMPLATE_DIR = os.path.dirname(templates.__file__) +STATIC_DIR = os.path.dirname(static.__file__) + +REQUIRED_STATIC_FAMILES = ['D3'] + +charts = Blueprint( + 'jsondash', + __name__, + template_folder=TEMPLATE_DIR, + static_url_path=STATIC_DIR, + static_folder=STATIC_DIR, + + +## ... source file abbreviated to get to flash examples ... + + + pagination = utils.paginator(count=len(views), + page=page, per_page=per_page) + opts.update(limit=pagination.limit, skip=pagination.skip) + views = views[pagination.skip:pagination.next] + else: + pagination = None + categorized = utils.categorize_views(views) + kwargs = dict( + total=len(views), + views=categorized, + view=None, + paginator=pagination, + creating=True, + can_edit_global=auth(authtype='edit_global'), + total_modules=sum([ + len(view.get('modules', [])) for view in views + if isinstance(view, dict) + ]), + ) + return render_template('pages/charts_index.html', **kwargs) + + +@charts.route('/charts/', methods=['GET']) +def view(c_id): + if not auth(authtype='view', view_id=c_id): +~~ flash('You do not have access to view this dashboard.', 'error') + return redirect(url_for('jsondash.dashboard')) + viewjson = adapter.read(c_id=c_id) + if not viewjson: +~~ flash('Could not find view: {}'.format(c_id), 'error') + return redirect(url_for('jsondash.dashboard')) + if '_id' in viewjson: + viewjson.pop('_id') + if 'modules' not in viewjson: +~~ flash('Invalid configuration - missing modules.', 'error') + return redirect(url_for('jsondash.dashboard')) + active_charts = [v.get('family') for v in viewjson['modules'] + if v.get('family') is not None] + if metadata(key='username') == viewjson.get('created_by'): + can_edit = True + else: + can_edit = auth(authtype='edit_others', view_id=c_id) + layout_type = viewjson.get('layout', 'freeform') + kwargs = dict( + id=c_id, + view=viewjson, + categories=get_categories(), + num_rows=( + None if layout_type == 'freeform' else utils.get_num_rows(viewjson) + ), + modules=utils.sort_modules(viewjson), + assets=get_active_assets(active_charts), + can_edit=can_edit, + can_edit_global=auth(authtype='edit_global'), + is_global=utils.is_global_dashboard(viewjson), + ) + return render_template('pages/chart_detail.html', **kwargs) + + +@charts.route('/charts//delete', methods=['POST']) +def delete(c_id): + dash_url = url_for('jsondash.dashboard') + if not auth(authtype='delete'): +~~ flash('You do not have access to delete dashboards.', 'error') + return redirect(dash_url) + adapter.delete(c_id) +~~ flash('Deleted dashboard "{}"'.format(c_id)) + return redirect(dash_url) + + +@charts.route('/charts//update', methods=['POST']) +def update(c_id): + if not auth(authtype='update'): +~~ flash('You do not have access to update dashboards.', 'error') + return redirect(url_for('jsondash.dashboard')) + viewjson = adapter.read(c_id=c_id) + if not viewjson: +~~ flash('Could not find view: {}'.format(c_id), 'error') + return redirect(url_for('jsondash.dashboard')) + form_data = request.form + view_url = url_for('jsondash.view', c_id=c_id) + edit_raw = 'edit-raw' in request.form + now = str(dt.now()) + if edit_raw: + try: + conf = form_data.get('config') + data = validate_raw_json(conf, date=now, id=c_id) + data = db.reformat_data(data, c_id) + except InvalidSchemaError as e: +~~ flash(str(e), 'error') + return redirect(view_url) + except (TypeError, ValueError) as e: +~~ flash('Invalid JSON config. "{}"'.format(e), 'error') + return redirect(view_url) + else: + modules = db.format_charts(form_data) + layout = form_data['mode'] + if layout == 'grid' and modules and modules[0].get('row') is None: +~~ flash('Cannot use grid layout without ' + 'specifying row(s)! Edit JSON manually ' + 'to override this.', 'error') + return redirect(view_url) + category = form_data.get('category', '') + category_override = form_data.get('category_new', '') + category = category_override if category_override != '' else category + data = dict( + category=category if category != '' else 'uncategorized', + name=form_data['name'], + layout=layout, + modules=modules, + id=c_id, + date=now, + ) + data.update(**metadata(exclude=['created_by'])) + data.update(**check_global()) + if edit_raw: + adapter.update(c_id, data=data, fmt_charts=False) + else: + adapter.update(c_id, data=data) +~~ flash('Updated view "{}"'.format(c_id)) + return redirect(view_url) + + +def check_global(): + global_enabled = setting('JSONDASH_GLOBALDASH') + global_flag = request.form.get('is_global') is not None + can_make_global = auth(authtype='edit_global') + if all([global_flag, global_enabled, can_make_global]): + return dict(created_by=setting('JSONDASH_GLOBAL_USER')) + return dict() + + +@charts.route('/charts/create', methods=['POST']) +def create(): + if not auth(authtype='create'): +~~ flash('You do not have access to create dashboards.', 'error') + return redirect(url_for('jsondash.dashboard')) + data = request.form + new_id = str(uuid.uuid1()) + d = dict( + name=data['name'], + modules=db.format_charts(data), + date=str(dt.now()), + id=new_id, + layout=data.get('mode', 'grid'), + ) + d.update(**metadata()) + d.update(**check_global()) + adapter.create(data=d) +~~ flash('Created new dashboard "{}"'.format(data['name'])) + return redirect(url_for('jsondash.view', c_id=new_id)) + + +@charts.route('/charts//clone', methods=['POST']) +def clone(c_id): + if not auth(authtype='clone'): +~~ flash('You do not have access to clone dashboards.', 'error') + return redirect(url_for('jsondash.dashboard')) + viewjson = adapter.read(c_id=c_id) + if not viewjson: +~~ flash('Could not find view: {}'.format(c_id), 'error') + return redirect(url_for('jsondash.dashboard')) + newname = 'Clone of {}'.format(viewjson['name']) + data = dict( + name=newname, + modules=viewjson['modules'], + date=str(dt.now()), + id=str(uuid.uuid1()), + layout=viewjson['layout'], + ) + data.update(**metadata()) + adapter.create(data=data) +~~ flash('Created new dashboard clone "{}"'.format(newname)) + return redirect(url_for('jsondash.view', c_id=data['id'])) + + + +## ... source file continues with no further flash examples... + +``` + + +## Example 7 from flask-login +[Flask-Login](https://github.com/maxcountryman/flask-login) +([project documentation](https://flask-login.readthedocs.io/en/latest/) +and [PyPI package](https://pypi.org/project/Flask-Login/)) +is a [Flask](/flask.html) extension that provides user session +management, which handles common tasks such as logging in +and out of a [web application](/web-development.html) and +managing associated user session data. Flask-Login is +open sourced under the +[MIT license](https://github.com/maxcountryman/flask-login/blob/master/LICENSE). + +[**flask-login / flask_login / login_manager.py**](https://github.com/maxcountryman/flask-login/blob/master/flask_login/./login_manager.py) + +```python +# login_manager.py + + +import warnings +from datetime import datetime, timedelta + +~~from flask import (_request_ctx_stack, abort, current_app, flash, redirect, + has_app_context, request, session) + +from ._compat import text_type +from .config import (COOKIE_NAME, COOKIE_DURATION, COOKIE_SECURE, + COOKIE_HTTPONLY, COOKIE_SAMESITE, LOGIN_MESSAGE, + LOGIN_MESSAGE_CATEGORY, REFRESH_MESSAGE, + REFRESH_MESSAGE_CATEGORY, ID_ATTRIBUTE, + AUTH_HEADER_NAME, SESSION_KEYS, USE_SESSION_FOR_NEXT) +from .mixins import AnonymousUserMixin +from .signals import (user_loaded_from_cookie, user_loaded_from_header, + user_loaded_from_request, user_unauthorized, + user_needs_refresh, user_accessed, session_protected) +from .utils import (login_url as make_login_url, _create_identifier, + _user_context_processor, encode_cookie, decode_cookie, + make_next_param, expand_login_view) + + +class LoginManager(object): + def __init__(self, app=None, add_context_processor=True): + self.anonymous_user = AnonymousUserMixin + + self.login_view = None + + self.blueprint_login_views = {} + + +## ... source file abbreviated to get to flash examples ... + + + self.init_app(app, add_context_processor) + + def init_app(self, app, add_context_processor=True): + app.login_manager = self + app.after_request(self._update_remember_cookie) + + if add_context_processor: + app.context_processor(_user_context_processor) + + def unauthorized(self): + user_unauthorized.send(current_app._get_current_object()) + + if self.unauthorized_callback: + return self.unauthorized_callback() + + if request.blueprint in self.blueprint_login_views: + login_view = self.blueprint_login_views[request.blueprint] + else: + login_view = self.login_view + + if not login_view: + abort(401) + + if self.login_message: + if self.localize_callback is not None: +~~ flash(self.localize_callback(self.login_message), + category=self.login_message_category) + else: +~~ flash(self.login_message, category=self.login_message_category) + + config = current_app.config + if config.get('USE_SESSION_FOR_NEXT', USE_SESSION_FOR_NEXT): + login_url = expand_login_view(login_view) + session['_id'] = self._session_identifier_generator() + session['next'] = make_next_param(login_url, request.url) + redirect_url = make_login_url(login_view) + else: + redirect_url = make_login_url(login_view, next_url=request.url) + + return redirect(redirect_url) + + def user_loader(self, callback): + self._user_callback = callback + return self.user_callback + + @property + def user_callback(self): + return self._user_callback + + def request_loader(self, callback): + self._request_callback = callback + return self.request_callback + + @property + def request_callback(self): + return self._request_callback + + def unauthorized_handler(self, callback): + self.unauthorized_callback = callback + return callback + + def needs_refresh_handler(self, callback): + self.needs_refresh_callback = callback + return callback + + def needs_refresh(self): + user_needs_refresh.send(current_app._get_current_object()) + + if self.needs_refresh_callback: + return self.needs_refresh_callback() + + if not self.refresh_view: + abort(401) + + if self.needs_refresh_message: + if self.localize_callback is not None: +~~ flash(self.localize_callback(self.needs_refresh_message), + category=self.needs_refresh_message_category) + else: +~~ flash(self.needs_refresh_message, + category=self.needs_refresh_message_category) + + config = current_app.config + if config.get('USE_SESSION_FOR_NEXT', USE_SESSION_FOR_NEXT): + login_url = expand_login_view(self.refresh_view) + session['_id'] = self._session_identifier_generator() + session['next'] = make_next_param(login_url, request.url) + redirect_url = make_login_url(self.refresh_view) + else: + login_url = self.refresh_view + redirect_url = make_login_url(login_url, next_url=request.url) + + return redirect(redirect_url) + + def header_loader(self, callback): + print('LoginManager.header_loader is deprecated. Use ' + + 'LoginManager.request_loader instead.') + self._header_callback = callback + return callback + + def _update_request_context_with_user(self, user=None): + + ctx = _request_ctx_stack.top + ctx.user = self.anonymous_user() if user is None else user + + +## ... source file continues with no further flash examples... + +``` + + +## Example 8 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / user_manager__views.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/./user_manager__views.py) + +```python +# user_manager__views.py + + +from datetime import datetime +try: + from urllib.parse import quote, unquote # Python 3 +except ImportError: + from urllib import quote, unquote # Python 2 + +~~from flask import current_app, flash, redirect, render_template, request, url_for +from flask_login import current_user, login_user, logout_user + +from .decorators import login_required +from . import signals +from .translation_utils import gettext as _ # map _() to gettext() + + +class UserManager__Views(object): + + + @login_required + def change_password_view(self): + + form = self.ChangePasswordFormClass(request.form) + + if request.method == 'POST': + if not form.validate(): +~~ flash(_('There was an error changing your password.'), 'error') + return redirect(url_for('user.change_password')) + + new_password = form.new_password.data + password_hash = self.hash_password(new_password) + + current_user.password = password_hash + self.db_manager.save_object(current_user) + self.db_manager.commit() + + if self.USER_ENABLE_EMAIL and self.USER_SEND_PASSWORD_CHANGED_EMAIL: + self.email_manager.send_password_changed_email(current_user) + + signals.user_changed_password.send(current_app._get_current_object(), user=current_user) + +~~ flash(_('Your password has been changed successfully.'), 'success') + + safe_next_url = self._get_safe_next_url('next', self.USER_AFTER_CHANGE_PASSWORD_ENDPOINT) + return redirect(safe_next_url) + + self.prepare_domain_translations() + return render_template(self.USER_CHANGE_PASSWORD_TEMPLATE, form=form) + + + @login_required + def change_username_view(self): + + form = self.ChangeUsernameFormClass(request.form) + + if request.method == 'POST' and form.validate(): + + new_username = form.new_username.data + current_user.username=new_username + self.db_manager.save_object(current_user) + self.db_manager.commit() + + if self.USER_ENABLE_EMAIL and self.USER_SEND_USERNAME_CHANGED_EMAIL: + self.email_manager.send_username_changed_email(current_user) + + signals.user_changed_username.send(current_app._get_current_object(), user=current_user) + +~~ flash(_("Your username has been changed to '%(username)s'.", username=new_username), 'success') + + safe_next_url = self._get_safe_next_url('next', self.USER_AFTER_CHANGE_USERNAME_ENDPOINT) + return redirect(safe_next_url) + + self.prepare_domain_translations() + return render_template(self.USER_CHANGE_USERNAME_TEMPLATE, form=form) + + + def confirm_email_view(self, token): + data_items = self.token_manager.verify_token( + token, + self.USER_CONFIRM_EMAIL_EXPIRATION) + + user = None + user_email = None + if data_items: + user, user_email = self.db_manager.get_user_and_user_email_by_id(data_items[0]) + + if not user or not user_email: +~~ flash(_('Invalid confirmation token.'), 'error') + return redirect(url_for('user.login')) + + user_email.email_confirmed_at=datetime.utcnow() + self.db_manager.save_user_and_user_email(user, user_email) + self.db_manager.commit() + + signals.user_confirmed_email.send(current_app._get_current_object(), user=user) + +~~ flash(_('Your email has been confirmed.'), 'success') + + safe_next_url = self._get_safe_next_url('next', self.USER_AFTER_CONFIRM_ENDPOINT) + if self.USER_AUTO_LOGIN_AFTER_CONFIRM: + return self._do_login_user(user, safe_next_url) # auto-login + else: + return redirect(url_for('user.login') + '?next=' + quote(safe_next_url)) # redirect to login page + + + @login_required + def edit_user_profile_view(self): + form = self.EditUserProfileFormClass(request.form, obj=current_user) + + if request.method == 'POST' and form.validate(): + form.populate_obj(current_user) + + self.db_manager.save_object(current_user) + self.db_manager.commit() + + return redirect(self._endpoint_url(self.USER_AFTER_EDIT_USER_PROFILE_ENDPOINT)) + + self.prepare_domain_translations() + return render_template(self.USER_EDIT_USER_PROFILE_TEMPLATE, form=form) + + @login_required + + +## ... source file abbreviated to get to flash examples ... + + + user_email.is_primary=True + self.db_manager.save_object(user_email) + self.db_manager.commit() + + elif action == 'confirm': + self._send_confirm_email_email(user_email.user, user_email) + else: + return self.unauthorized_view() + + return redirect(url_for('user.manage_emails')) + + + def forgot_password_view(self): + + form = self.ForgotPasswordFormClass(request.form) + + if request.method == 'POST' and form.validate(): + email = form.email.data + user, user_email = self.db_manager.get_user_and_user_email_by_email(email) + + if user and user_email: + self.email_manager.send_reset_password_email(user, user_email) + + signals.user_forgot_password.send(current_app._get_current_object(), user=user) + +~~ flash(_( + "A reset password email has been sent to '%(email)s'. Open that email and follow the instructions to reset your password.", + email=email), 'success') + + return redirect(self._endpoint_url(self.USER_AFTER_FORGOT_PASSWORD_ENDPOINT)) + + self.prepare_domain_translations() + return render_template(self.USER_FORGOT_PASSWORD_TEMPLATE, form=form) + + @login_required + def manage_emails_view(self): + + user_emails = self.db_manager.find_user_emails(user=current_user) + form = self.AddEmailFormClass() + + if request.method == "POST" and form.validate(): + new_email = form.email.data + user_email = self.db_manager.add_user_email(user=current_user, email=new_email) + self.db_manager.save_object(user_email) + self.db_manager.commit() + return redirect(url_for('user.manage_emails')) + + self.prepare_domain_translations() + return render_template(self.USER_MANAGE_EMAILS_TEMPLATE, + user_emails=user_emails, + form=form, + ) + + @login_required + def invite_user_view(self): + + invite_user_form = self.InviteUserFormClass(request.form) + + if request.method == 'POST' and invite_user_form.validate(): + email = invite_user_form.email.data + user, user_email = self.db_manager.get_user_and_user_email_by_email(email) + if user: +~~ flash("User with that email has already registered", "error") + return redirect(url_for('user.invite_user')) + + user_invitation = self.db_manager.add_user_invitation( + email=email, + invited_by_user_id=current_user.id) + self.db_manager.commit() + + try: + self.email_manager.send_invite_user_email(current_user, user_invitation) + except Exception as e: + self.db_manager.delete_object(user_invitation) + self.db_manager.commit() + raise + + signals \ + .user_sent_invitation \ + .send(current_app._get_current_object(), user_invitation=user_invitation, + form=invite_user_form) + +~~ flash(_('Invitation has been sent.'), 'success') + + safe_next_url = self._get_safe_next_url('next', self.USER_AFTER_INVITE_ENDPOINT) + return redirect(safe_next_url) + + self.prepare_domain_translations() + return render_template(self.USER_INVITE_USER_TEMPLATE, form=invite_user_form) + + + def login_view(self): + + + safe_next_url = self._get_safe_next_url('next', self.USER_AFTER_LOGIN_ENDPOINT) + safe_reg_next = self._get_safe_next_url('reg_next', self.USER_AFTER_REGISTER_ENDPOINT) + + if self.call_or_get(current_user.is_authenticated) and self.USER_AUTO_LOGIN_AT_LOGIN: + return redirect(safe_next_url) + + login_form = self.LoginFormClass(request.form) # for login.html + register_form = self.RegisterFormClass() # for login_or_register.html + if request.method != 'POST': + login_form.next.data = register_form.next.data = safe_next_url + login_form.reg_next.data = register_form.reg_next.data = safe_reg_next + + if request.method == 'POST' and login_form.validate(): + + +## ... source file abbreviated to get to flash examples ... + + + if self.USER_ENABLE_USERNAME: + user = self.db_manager.find_user_by_username(login_form.username.data) + + if not user and self.USER_ENABLE_EMAIL: + user, user_email = self.db_manager.get_user_and_user_email_by_email(login_form.username.data) + else: + user, user_email = self.db_manager.get_user_and_user_email_by_email(login_form.email.data) + + if user: + safe_next_url = self.make_safe_url(login_form.next.data) + return self._do_login_user(user, safe_next_url, login_form.remember_me.data) + + self.prepare_domain_translations() + template_filename = self.USER_LOGIN_AUTH0_TEMPLATE if self.USER_ENABLE_AUTH0 else self.USER_LOGIN_TEMPLATE + return render_template(template_filename, + form=login_form, + login_form=login_form, + register_form=register_form) + + def logout_view(self): + + signals.user_logged_out.send(current_app._get_current_object(), user=current_user) + + logout_user() + +~~ flash(_('You have signed out successfully.'), 'success') + + safe_next_url = self._get_safe_next_url('next', self.USER_AFTER_LOGOUT_ENDPOINT) + return redirect(safe_next_url) + + def register_view(self): + + safe_next_url = self._get_safe_next_url('next', self.USER_AFTER_LOGIN_ENDPOINT) + safe_reg_next_url = self._get_safe_next_url('reg_next', self.USER_AFTER_REGISTER_ENDPOINT) + + login_form = self.LoginFormClass() # for login_or_register.html + register_form = self.RegisterFormClass(request.form) # for register.html + + invite_token = request.values.get("token") + + if self.USER_REQUIRE_INVITATION and not invite_token: +~~ flash("Registration is invite only", "error") + return redirect(url_for('user.login')) + + user_invitation = None + if invite_token and self.db_manager.UserInvitationClass: + data_items = self.token_manager.verify_token(invite_token, self.USER_INVITE_EXPIRATION) + if data_items: + user_invitation_id = data_items[0] + user_invitation = self.db_manager.get_user_invitation_by_id(user_invitation_id) + + if not user_invitation: +~~ flash("Invalid invitation token", "error") + return redirect(url_for('user.login')) + + register_form.invite_token.data = invite_token + + if request.method != 'POST': + login_form.next.data = register_form.next.data = safe_next_url + login_form.reg_next.data = register_form.reg_next.data = safe_reg_next_url + if user_invitation: + register_form.email.data = user_invitation.email + + if request.method == 'POST' and register_form.validate(): + user = self.db_manager.add_user() + register_form.populate_obj(user) + user_email = self.db_manager.add_user_email(user=user, is_primary=True) + register_form.populate_obj(user_email) + + user.password = self.hash_password(user.password) + + request_email_confirmation = self.USER_ENABLE_CONFIRM_EMAIL + if user_invitation: + if user_invitation.email.lower() == register_form.email.data.lower(): + user_email.email_confirmed_at=datetime.utcnow() + request_email_confirmation = False + + + +## ... source file abbreviated to get to flash examples ... + + + + self.prepare_domain_translations() + return render_template(self.USER_RESEND_CONFIRM_EMAIL_TEMPLATE, form=form) + + + def reset_password_view(self, token): + + if self.call_or_get(current_user.is_authenticated): + logout_user() + + data_items = self.token_manager.verify_token( + token, + self.USER_RESET_PASSWORD_EXPIRATION) + + user = None + if data_items: + user_id = data_items[0] + user = self.db_manager.get_user_by_id(user_id) + + user_or_user_email_object = self.db_manager.get_primary_user_email_object(user) + user_or_user_email_object.email_confirmed_at = datetime.utcnow() + self.db_manager.save_object(user_or_user_email_object) + self.db_manager.commit() + + if not user: +~~ flash(_('Your reset password token is invalid.'), 'error') + return redirect(self._endpoint_url('user.login')) + + + form = self.ResetPasswordFormClass(request.form) + + if request.method == 'POST' and form.validate(): + password_hash = self.hash_password(form.new_password.data) + user.password=password_hash + self.db_manager.save_object(user) + self.db_manager.commit() + + if self.USER_ENABLE_EMAIL and self.USER_SEND_PASSWORD_CHANGED_EMAIL: + self.email_manager.send_password_changed_email(user) + + signals.user_reset_password.send(current_app._get_current_object(), user=user) + +~~ flash(_("Your password has been reset successfully."), 'success') + + safe_next_url = self._get_safe_next_url('next', self.USER_AFTER_RESET_PASSWORD_ENDPOINT) + if self.USER_AUTO_LOGIN_AFTER_RESET_PASSWORD: + return self._do_login_user(user, safe_next_url) # auto-login + else: + return redirect(url_for('user.login') + '?next=' + quote(safe_next_url)) # redirect to login page + + self.prepare_domain_translations() + return render_template(self.USER_RESET_PASSWORD_TEMPLATE, form=form) + + def unauthenticated_view(self): + url = request.url +~~ flash(_("You must be signed in to access '%(url)s'.", url=url), 'error') + + safe_next_url = self.make_safe_url(url) + return redirect(self._endpoint_url(self.USER_UNAUTHENTICATED_ENDPOINT)+'?next='+quote(safe_next_url)) + + + def unauthorized_view(self): + url = request.script_root + request.path +~~ flash(_("You do not have permission to access '%(url)s'.", url=url), 'error') + + return redirect(self._endpoint_url(self.USER_UNAUTHORIZED_ENDPOINT)) + + + + def _send_registered_email(self, user, user_email, request_email_confirmation): + um = current_app.user_manager + + if self.USER_ENABLE_EMAIL and self.USER_SEND_REGISTERED_EMAIL: + + self.email_manager.send_registered_email(user, user_email, request_email_confirmation) + + if request_email_confirmation: + email = user_email.email if user_email else user.email +~~ flash(_('A confirmation email has been sent to %(email)s with instructions to complete your registration.', email=email), 'success') + else: +~~ flash(_('You have registered successfully.'), 'success') + + + def _send_confirm_email_email(self, user, user_email): + + if self.USER_ENABLE_EMAIL and self.USER_ENABLE_CONFIRM_EMAIL: + self.email_manager.send_confirm_email_email(user, user_email) + + email = user_email.email if user_email else user.email +~~ flash(_('A confirmation email has been sent to %(email)s with instructions to complete your registration.', email=email), 'success') + + + def _do_login_user(self, user, safe_next_url, remember_me=False): + if not user: return self.unauthenticated() + + if not user.active: +~~ flash(_('Your account has not been enabled.'), 'error') + return redirect(url_for('user.login')) + + if self.USER_ENABLE_EMAIL \ + and self.USER_ENABLE_CONFIRM_EMAIL \ + and not current_app.user_manager.USER_ALLOW_LOGIN_WITHOUT_CONFIRMED_EMAIL \ + and not self.db_manager.user_has_confirmed_email(user): + url = url_for('user.resend_email_confirmation') +~~ flash(_('Your email address has not yet been confirmed. Check your email Inbox and Spam folders for the confirmation email or Re-send confirmation email.', url=url), 'error') + return redirect(url_for('user.login')) + + login_user(user, remember=remember_me) + + signals.user_logged_in.send(current_app._get_current_object(), user=user) + +~~ flash(_('You have signed in successfully.'), 'success') + + return redirect(safe_next_url) + + + def _get_safe_next_url(self, param_name, default_endpoint): + + if param_name in request.args: + safe_next_url = current_app.user_manager.make_safe_url(unquote(request.args[param_name])) + + else: + safe_next_url = self._endpoint_url(default_endpoint) + + return safe_next_url + + + def _endpoint_url(self, endpoint): + return url_for(endpoint) if endpoint else '/' + + + +## ... source file continues with no further flash examples... + +``` + + +## Example 9 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / util / roles.py**](https://github.com/indico/indico/blob/master/indico/util/roles.py) + +```python +# roles.py + +import csv + +~~from flask import flash, session + +from indico.core.errors import UserValueError +from indico.modules.events.roles.forms import ImportMembersCSVForm +from indico.modules.users import User +from indico.util.i18n import _, ngettext +from indico.util.spreadsheets import csv_text_io_wrapper +from indico.util.string import validate_email +from indico.web.flask.templating import get_template_module +from indico.web.util import jsonify_data, jsonify_template + + +class ImportRoleMembersMixin: + + logger = None + + def import_members_from_csv(self, f): + with csv_text_io_wrapper(f) as ftxt: + reader = csv.reader(ftxt.read().splitlines()) + + emails = set() + for num_row, row in enumerate(reader, 1): + if len(row) != 1: + raise UserValueError(_('Row {}: malformed CSV data').format(num_row)) + email = row[0].strip().lower() + + +## ... source file abbreviated to get to flash examples ... + + + raise UserValueError(_('Row {row}: invalid email address: {email}').format(row=num_row, email=email)) + if email in emails: + raise UserValueError(_('Row {}: email address is not unique').format(num_row)) + emails.add(email) + + users = set(User.query.filter(-User.is_deleted, User.all_emails.in_(emails))) + users_emails = {user.email for user in users} + unknown_emails = emails - users_emails + new_members = users - self.role.members + return new_members, users, unknown_emails + + def _process(self): + form = ImportMembersCSVForm() + + if form.validate_on_submit(): + new_members, users, unknown_emails = self.import_members_from_csv(form.source_file.data) + if form.remove_existing.data: + deleted_members = self.role.members - users + for member in deleted_members: + self.logger.info(f'User {member} removed from role {self.role} by {session.user}') + self.role.members = users + else: + self.role.members |= users + for user in new_members: + self.logger.info(f'User {user} added to role {self.role} by {session.user}') +~~ flash(ngettext('{} member has been imported.', + '{} members have been imported.', + len(users)).format(len(users)), 'success') + if unknown_emails: +~~ flash(ngettext('There is no user with this email address: {}', + 'There are no users with these email addresses: {}', + len(unknown_emails)).format(', '.join(unknown_emails)), 'warning') + tpl = get_template_module('events/roles/_roles.html') + return jsonify_data(html=tpl.render_role(self.role, collapsed=False, email_button=False)) + return jsonify_template('events/roles/import_members.html', form=form, role=self.role) + + + +## ... source file continues with no further flash examples... + +``` + + +## Example 10 from tedivms-flask +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + +[**tedivms-flask / app / views / misc_views.py**](https://github.com/tedivm/tedivms-flask/blob/master/app/views/misc_views.py) + +```python +# misc_views.py + +from flask import Blueprint, redirect, render_template, current_app, abort +~~from flask import request, url_for, flash, send_from_directory, jsonify, render_template_string +from flask_user import current_user, login_required, roles_accepted + +from app import db +from app.models.user_models import UserProfileForm, User, UsersRoles, Role +from app.utils.forms import ConfirmationForm +import uuid, json, os +import datetime + +main_blueprint = Blueprint('main', __name__, template_folder='templates') + +@main_blueprint.route('/') +def member_page(): + if not current_user.is_authenticated: + return redirect(url_for('user.login')) + return render_template('pages/member_base.html') + +@main_blueprint.route('/admin') +@roles_accepted('admin') +def admin_page(): + return redirect(url_for('main.user_admin_page')) + +@main_blueprint.route('/users') +@roles_accepted('admin') +def user_admin_page(): + + +## ... source file abbreviated to get to flash examples ... + + + + form = UserProfileForm() + roles = Role.query.all() + form.roles.choices = [(x.id,x.name) for x in roles] + + if form.validate(): + user = User.query.filter(User.email == request.form['email']).first() + if not user: + user = User(email=form.email.data, + first_name=form.first_name.data, + last_name=form.last_name.data, + password=current_app.user_manager.hash_password(form.password.data), + active=True, + email_confirmed_at=datetime.datetime.utcnow()) + db.session.add(user) + db.session.commit() + allowed_roles = form.roles.data + for role in roles: + if role.id not in allowed_roles: + if role in user.roles: + user.roles.remove(role) + else: + if role not in user.roles: + user.roles.append(role) + db.session.commit() +~~ flash('You successfully created the new user.', 'success') + return redirect(url_for('main.user_admin_page')) +~~ flash('A user with that email address already exists', 'error') + return render_template('pages/admin/create_user.html', form=form) + + +@main_blueprint.route('/users//delete', methods=['GET', 'POST']) +@roles_accepted('admin') +def delete_user_page(user_id): + if current_app.config.get('USER_LDAP', False): + abort(400) + form = ConfirmationForm() + user = User.query.filter(User.id == user_id).first() + if not user: + abort(404) + if form.validate(): + db.session.query(UsersRoles).filter_by(user_id = user_id).delete() + db.session.query(User).filter_by(id = user_id).delete() + db.session.commit() +~~ flash('You successfully deleted your user!', 'success') + return redirect(url_for('main.user_admin_page')) + return render_template('pages/admin/delete_user.html', form=form) + + +@main_blueprint.route('/users//edit', methods=['GET', 'POST']) +@roles_accepted('admin') +def edit_user_page(user_id): + if current_app.config.get('USER_LDAP', False): + abort(400) + + user = User.query.filter(User.id == user_id).first() + if not user: + abort(404) + + form = UserProfileForm(obj=user) + roles = Role.query.all() + form.roles.choices = [(x.id,x.name) for x in roles] + + if form.validate(): + if 'password' in request.form and len(request.form['password']) >= 8: + user.password = current_app.user_manager.hash_password(request.form['password']) + user.email = form.email.data + user.first_name = form.first_name.data + user.last_name = form.last_name.data + user.active = form.active.data + + allowed_roles = form.roles.data + for role in roles: + if role.id not in allowed_roles: + if role in user.roles: + user.roles.remove(role) + else: + if role not in user.roles: + user.roles.append(role) + + db.session.commit() +~~ flash('You successfully edited the user.', 'success') + return redirect(url_for('main.user_admin_page')) + + form.roles.data = [role.id for role in user.roles] + return render_template('pages/admin/edit_user.html', form=form) + +@main_blueprint.route('/pages/profile', methods=['GET', 'POST']) +@login_required +def user_profile_page(): + if current_app.config.get('USER_LDAP', False): + abort(400) + + form = UserProfileForm(request.form, obj=current_user) + + if request.method == 'POST' and form.validate(): + form.populate_obj(current_user) + + db.session.commit() + + return redirect(url_for('main.user_profile_page')) + + return render_template('pages/user_profile_page.html', + current_user=current_user, + form=form) + + + +## ... source file continues with no further flash examples... + +``` + diff --git a/content/pages/examples/flask/flask-helpers-get-root-path.markdown b/content/pages/examples/flask/flask-helpers-get-root-path.markdown new file mode 100644 index 000000000..3b75f3a3e --- /dev/null +++ b/content/pages/examples/flask/flask-helpers-get-root-path.markdown @@ -0,0 +1,184 @@ +title: flask.helpers get_root_path Example Code +category: page +slug: flask-helpers-get-root-path-examples +sortorder: 500021019 +toc: False +sidebartitle: flask.helpers get_root_path +meta: Python example code that shows how to use the get_root_path callable from the flask.helpers module of the Flask project. + + +[get_root_path](https://github.com/pallets/flask/blob/master/src/flask/helpers.py) +is a function within the `flask.helpers` module of the [Flask](/flask.html) +framework. `get_root_path` returns the filesystem path to a package +or the current working directly if the path cannot be found. + +flash, +make_response, +safe_join, +send_file, +and url_for +are several other callables with code examples from the same `flask.helpers` package. + +## Example 1 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / cli / setup.py**](https://github.com/indico/indico/blob/master/indico/cli/setup.py) + +```python +# setup.py + +import os +import re +import shutil +import socket +import subprocess +import sys +from operator import attrgetter +from pathlib import Path +from smtplib import SMTP + +import click +from click import wrap_text +~~from flask.helpers import get_root_path +from packaging.specifiers import SpecifierSet +from packaging.version import Version +from pkg_resources import iter_entry_points +from prompt_toolkit import prompt +from prompt_toolkit.completion import PathCompleter, WordCompleter +from prompt_toolkit.styles import Style +from pytz import all_timezones, common_timezones +from redis import RedisError, StrictRedis +from sqlalchemy import create_engine +from sqlalchemy.exc import OperationalError +from sqlalchemy.pool import NullPool +from terminaltables import AsciiTable +from werkzeug.urls import url_parse + +import indico +from indico.core.db.sqlalchemy.util.models import import_all_models +from indico.util.console import cformat +from indico.util.string import validate_email + + +def _echo(msg=''): + click.echo(msg, err=True) + + + + +## ... source file abbreviated to get to get_root_path examples ... + + + +def _prompt_abort(): + _confirm('Continue anyway?', abort=True) + + +def _copy(src, dst, force=False): + if not force and os.path.exists(dst): + _echo(cformat('%{yellow!}{}%{reset}%{yellow} already exists; not copying %{yellow!}{}') + .format(dst, src)) + return + _echo(cformat('%{green}Copying %{green!}{}%{reset}%{green} -> %{green!}{}').format(src, dst)) + shutil.copy(src, dst) + + +def _link(src, dst): + _echo(cformat('%{cyan}Linking %{cyan!}{}%{reset}%{cyan} -> %{cyan!}{}').format(dst, src)) + if os.path.exists(dst) or os.path.islink(dst): + os.unlink(dst) + os.symlink(src, dst) + + +def _get_dirs(target_dir): + if not os.path.isdir(target_dir): + _echo(cformat('%{red}Directory not found:%{red!} {}').format(target_dir)) + sys.exit(1) +~~ return get_root_path('indico'), os.path.abspath(target_dir) + + +PROMPT_TOOLKIT_STYLE = Style.from_dict({ + 'help': '#aaaaaa', + 'prompt': '#5f87ff', + 'default': '#dfafff', + 'bracket': '#ffffff', + 'colon': '#ffffff', + '': '#aaffaa', # user input +}) + + +def _prompt(message, default='', path=False, list_=None, required=True, validate=None, allow_invalid=False, + password=False, help=None): + def _get_prompt_tokens(): + rv = [ + ('class:prompt', message), + ('class:colon', ': '), + ] + if first and help: + rv.insert(0, ('class:help', wrap_text(help) + '\n')) + return rv + + completer = None + + +## ... source file abbreviated to get to get_root_path examples ... + + + 'SMTP_USE_CELERY = False' + ] + + if not self.system_notices: + config_data += [ + '', + '# Disable system notices', + 'SYSTEM_NOTICES_URL = None' + ] + + config = '\n'.join(x for x in config_data if x is not None) + + if dev: + if not os.path.exists(self.data_root_path): + os.mkdir(self.data_root_path) + + _echo() + for path in self._missing_dirs: + _echo(cformat('%{magenta}Creating %{magenta!}{}%{reset}%{magenta}').format(path)) + os.mkdir(path) + + _echo(cformat('%{magenta}Creating %{magenta!}{}%{reset}%{magenta}').format(self.config_path)) + with open(self.config_path, 'w') as f: + f.write(config + '\n') + +~~ package_root = get_root_path('indico') + _copy(os.path.normpath(os.path.join(package_root, 'logging.yaml.sample')), + os.path.join(self.config_dir_path, 'logging.yaml')) + + if not dev: + _link(os.path.join(package_root, 'web', 'static'), os.path.join(self.data_root_path, 'web', 'static')) + _copy(os.path.join(package_root, 'web', 'indico.wsgi'), + os.path.join(self.data_root_path, 'web', 'indico.wsgi'), + force=True) + + if create_config_link: + _link(self.config_path, config_link_path) + + _echo() + _echo(cformat('%{green}Indico has been configured successfully!')) + if not dev and not create_config_link: + _echo(cformat('Run %{green!}export INDICO_CONFIG={}%{reset} to use your config file') + .format(self.config_path)) + + _echo(cformat('You can now run %{green!}indico db prepare%{reset} to initialize your Indico database')) + + + +## ... source file continues with no further get_root_path examples... + +``` + diff --git a/content/pages/examples/flask/flask-helpers-make-response.markdown b/content/pages/examples/flask/flask-helpers-make-response.markdown new file mode 100644 index 000000000..877d38532 --- /dev/null +++ b/content/pages/examples/flask/flask-helpers-make-response.markdown @@ -0,0 +1,640 @@ +title: flask.helpers make_response Example Code +category: page +slug: flask-helpers-make-response-examples +sortorder: 500021020 +toc: False +sidebartitle: flask.helpers make_response +meta: Python example code that shows how to use the make_response callable from the flask.helpers module of the Flask project. + + +[make_response](https://github.com/pallets/flask/blob/master/src/flask/helpers.py) +is a function in the `flask.helpers` module of the [Flask](/flask.html) +[web framework](/web-framework.html). `make_response` is for adding additional +HTTP headers to a response within a view's code. Sometimes views do not return +a response object so it's unclear how to add headers to the response, which +is where `make_response` is particularly useful in solving that specific +problem. + +`make_response` can also be imported directly from the `flask` module +instead of `flask.helpers` so you will typically see that shortcut +in example code. + +flash, +get_root_path, +safe_join, +send_file, +and url_for +are several other callables with code examples from the same `flask.helpers` package. + +## Example 1 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / security / decorators.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/security/decorators.py) + +```python +# decorators.py +import functools +import logging + +~~from flask import current_app, flash, jsonify, make_response, redirect, request, url_for +from flask_jwt_extended import verify_jwt_in_request +from flask_login import current_user + +from .._compat import as_unicode +from ..const import ( + FLAMSG_ERR_SEC_ACCESS_DENIED, + LOGMSG_ERR_SEC_ACCESS_DENIED, + PERMISSION_PREFIX, +) + +log = logging.getLogger(__name__) + + +def protect(allow_browser_login=False): + + def _protect(f): + if hasattr(f, "_permission_name"): + permission_str = f._permission_name + else: + permission_str = f.__name__ + + def wraps(self, *args, **kwargs): + permission_str = "{}{}".format(PERMISSION_PREFIX, f._permission_name) + if self.method_permission_name: + + +## ... source file abbreviated to get to make_response examples ... + + + return functools.update_wrapper(wraps, f) + + +def has_access_api(f): + if hasattr(f, "_permission_name"): + permission_str = f._permission_name + else: + permission_str = f.__name__ + + def wraps(self, *args, **kwargs): + permission_str = "{}{}".format(PERMISSION_PREFIX, f._permission_name) + if self.method_permission_name: + _permission_name = self.method_permission_name.get(f.__name__) + if _permission_name: + permission_str = "{}{}".format(PERMISSION_PREFIX, _permission_name) + if permission_str in self.base_permissions and self.appbuilder.sm.has_access( + permission_str, self.class_permission_name + ): + return f(self, *args, **kwargs) + else: + log.warning( + LOGMSG_ERR_SEC_ACCESS_DENIED.format( + permission_str, self.__class__.__name__ + ) + ) +~~ response = make_response( + jsonify( + {"message": str(FLAMSG_ERR_SEC_ACCESS_DENIED), "severity": "danger"} + ), + 401, + ) + response.headers["Content-Type"] = "application/json" + return response + + f._permission_name = permission_str + return functools.update_wrapper(wraps, f) + + +def permission_name(name): + + def wraps(f): + f._permission_name = name + return f + + return wraps + + + +## ... source file continues with no further make_response examples... + +``` + + +## Example 2 from Flask-HTTPAuth +[Flask-HTTPAuth](https://github.com/miguelgrinberg/Flask-HTTPAuth) +([documentation](https://flask-httpauth.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/Flask-HTTPAuth/)) +is a [Flask](/flask.html) framework extension that creates +Basic and Digest HTTP authentication for routes. This project +is primarily built and maintained by +[Miguel Grinberg](https://blog.miguelgrinberg.com/). It is provided +as open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/LICENSE). + +[**Flask-HTTPAuth / flask_httpauth.py**](https://github.com/miguelgrinberg/Flask-HTTPAuth/blob/master/././flask_httpauth.py) + +```python +# flask_httpauth.py + +from base64 import b64decode +from functools import wraps +from hashlib import md5 +from random import Random, SystemRandom +~~from flask import request, make_response, session, g, Response +from werkzeug.datastructures import Authorization +from werkzeug.security import safe_str_cmp + +__version__ = '4.2.1dev' + + +class HTTPAuth(object): + def __init__(self, scheme=None, realm=None, header=None): + self.scheme = scheme + self.realm = realm or "Authentication Required" + self.header = header + self.get_password_callback = None + self.get_user_roles_callback = None + self.auth_error_callback = None + + def default_get_password(username): + return None + + def default_auth_error(status): + return "Unauthorized Access", status + + self.get_password(default_get_password) + self.error_handler(default_auth_error) + + def get_password(self, f): + self.get_password_callback = f + return f + + def get_user_roles(self, f): + self.get_user_roles_callback = f + return f + + def error_handler(self, f): + @wraps(f) + def decorated(*args, **kwargs): + res = f(*args, **kwargs) + check_status_code = not isinstance(res, (tuple, Response)) +~~ res = make_response(res) + if check_status_code and res.status_code == 200: + res.status_code = 401 + if 'WWW-Authenticate' not in res.headers.keys(): + res.headers['WWW-Authenticate'] = self.authenticate_header() + return res + self.auth_error_callback = decorated + return decorated + + def authenticate_header(self): + return '{0} realm="{1}"'.format(self.scheme, self.realm) + + def get_auth(self): + auth = None + if self.header is None or self.header == 'Authorization': + auth = request.authorization + if auth is None and 'Authorization' in request.headers: + try: + auth_type, token = request.headers['Authorization'].split( + None, 1) + auth = Authorization(auth_type, {'token': token}) + except (ValueError, KeyError): + pass + elif self.header in request.headers: + auth = Authorization(self.scheme, + + +## ... source file continues with no further make_response examples... + +``` + + +## Example 3 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / cors.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./cors.py) + +```python +# cors.py +from __future__ import unicode_literals + +from datetime import timedelta +~~from flask import make_response, request, current_app +from functools import update_wrapper + + +def crossdomain( + origin=None, + methods=None, + headers=None, + expose_headers=None, + max_age=21600, + attach_to_all=True, + automatic_options=True, + credentials=False, +): + if methods is not None: + methods = ", ".join(sorted(x.upper() for x in methods)) + if headers is not None and not isinstance(headers, str): + headers = ", ".join(x.upper() for x in headers) + if expose_headers is not None and not isinstance(expose_headers, str): + expose_headers = ", ".join(x.upper() for x in expose_headers) + if not isinstance(origin, str): + origin = ", ".join(origin) + if isinstance(max_age, timedelta): + max_age = max_age.total_seconds() + + def get_methods(): + if methods is not None: + return methods + + options_resp = current_app.make_default_options_response() + return options_resp.headers["allow"] + + def decorator(f): + def wrapped_function(*args, **kwargs): + if automatic_options and request.method == "OPTIONS": + resp = current_app.make_default_options_response() + else: +~~ resp = make_response(f(*args, **kwargs)) + if not attach_to_all and request.method != "OPTIONS": + return resp + + h = resp.headers + + h["Access-Control-Allow-Origin"] = origin + h["Access-Control-Allow-Methods"] = get_methods() + h["Access-Control-Max-Age"] = str(max_age) + if credentials: + h["Access-Control-Allow-Credentials"] = "true" + if headers is not None: + h["Access-Control-Allow-Headers"] = headers + if expose_headers is not None: + h["Access-Control-Expose-Headers"] = expose_headers + return resp + + f.provide_automatic_options = False + return update_wrapper(wrapped_function, f) + + return decorator + + + +## ... source file continues with no further make_response examples... + +``` + + +## Example 4 from Flask-Security-Too +[Flask-Security-Too](https://github.com/Flask-Middleware/flask-security/) +([PyPi page](https://pypi.org/project/Flask-Security-Too/) and +[project documentation](https://flask-security-too.readthedocs.io/en/stable/)) +is a maintained fork of the original +[Flask-Security](https://github.com/mattupstate/flask-security) project that +makes it easier to add common security features to [Flask](/flask.html) +web applications. A few of the critical goals of the Flask-Security-Too +project are ensuring JavaScript client-based single-page applications (SPAs) +can work securely with Flask-based backends and that guidance by the +[OWASP](https://owasp.org/) organization is followed by default. + +The Flask-Security-Too project is provided as open source under the +[MIT license](https://github.com/Flask-Middleware/flask-security/blob/master/LICENSE). + +[**Flask-Security-Too / flask_security / views.py**](https://github.com/Flask-Middleware/flask-security/blob/master/flask_security/./views.py) + +```python +# views.py + +from functools import partial +import time +import typing as t + +from flask import ( + Blueprint, + after_this_request, + jsonify, + request, + session, +) +from flask_login import current_user +from werkzeug.datastructures import ImmutableMultiDict, MultiDict + +from .changeable import change_user_password +from .confirmable import ( + confirm_email_token_status, + confirm_user, + send_confirmation_instructions, +) +from .decorators import anonymous_user_required, auth_required, unauth_csrf +from .passwordless import login_token_status, send_login_instructions +from .proxies import _security, _datastore +from .quart_compat import get_quart_status +from .unified_signin import ( + us_signin, + us_signin_send_code, + us_setup, + us_setup_validate, + us_verify, + us_verify_link, + us_verify_send_code, +) +from .recoverable import ( + + +## ... source file abbreviated to get to make_response examples ... + + +from .utils import ( + base_render_json, + check_and_update_authn_fresh, + config_value as cv, + do_flash, + get_message, + get_post_login_redirect, + get_post_logout_redirect, + get_post_register_redirect, + get_post_verify_redirect, + get_request_attr, + get_url, + json_error_response, + login_user, + logout_user, + send_mail, + slash_url_suffix, + suppress_form_csrf, + url_for_security, + view_commit, +) + +if get_quart_status(): # pragma: no cover + from quart import make_response, redirect +else: +~~ from flask import make_response, redirect + +if t.TYPE_CHECKING: # pragma: no cover + from flask.typing import ResponseValue + + +def default_render_json(payload, code, headers, user): + if headers is None: + headers = dict() + headers["Content-Type"] = "application/json" + payload = dict(meta=dict(code=code), response=payload) +~~ return make_response(jsonify(payload), code, headers) + + +def _ctx(endpoint): + return _security._run_ctx_processor(endpoint) + + +@unauth_csrf(fall_through=True) +def login() -> "ResponseValue": + + if current_user.is_authenticated and request.method == "POST": + + if _security._want_json(request): + payload = json_error_response( + errors=get_message("ANONYMOUS_USER_REQUIRED")[0] + ) + return _security._render_json(payload, 400, None, None) + else: + return redirect(get_url(cv("POST_LOGIN_VIEW"))) + + form_class = _security.login_form + + if request.is_json: + if request.content_length: + form = form_class(MultiDict(request.get_json()), meta=suppress_form_csrf()) + + +## ... source file continues with no further make_response examples... + +``` + + +## Example 5 from newspie +[NewsPie](https://github.com/skamieniarz/newspie) is a minimalistic news +aggregator created with [Flask](/flask.html) and the +[News API](https://newsapi.org/). + +NewsPie is provided as open source under the +[MIT license](https://github.com/skamieniarz/newspie/blob/master/LICENSE). + +[**newspie / news.py**](https://github.com/skamieniarz/newspie/blob/master/././news.py) + +```python +# news.py +import configparser +import json +import logging +import os +from typing import Union + +import requests +import requests_cache +from dateutil import parser +~~from flask import (Flask, make_response, redirect, render_template, request, + url_for) + +CONFIG = configparser.ConfigParser() +CONFIG.read('config.ini') +API_KEY = os.environ.get('NEWS_API_KEY') +TOP_HEADLINES = CONFIG['ENDPOINTS']['TOP_HEADLINES'] +EVERYTHING = CONFIG['ENDPOINTS']['EVERYTHING'] +PAGE_SIZE = int(CONFIG['VARIOUS']['PAGE_SIZE']) + +CATEGORIES = ('general', 'sports', 'business', 'entertainment', 'health', + 'science', 'technology') +with open('data/countries.json') as json_file: + COUNTRIES = json.load(json_file) + +logging.basicConfig(level=logging.DEBUG) +requests_cache.install_cache(cache_name='news_cache', + backend='sqlite', + expire_after=300) + +APP = Flask(__name__) +SESSION = requests.Session() +SESSION.headers.update({'Authorization': API_KEY}) + + + + +## ... source file abbreviated to get to make_response examples ... + + + 'pageSize': PAGE_SIZE + } + if request.method == 'POST': + return do_post(page, category='search', current_query=query) + response = SESSION.get(EVERYTHING, params=params) + pages = count_pages(response.json()) + if page > pages: + page = pages + return redirect(url_for('search', query=query, page=page)) + articles = parse_articles(response.json()) + return render(articles, + page, + pages, + country=get_cookie('country'), + category='search') + + +def do_post(page, category='general', current_query=None): + new_query = request.form.get('search_query') + country = request.form.get('country') + next_page = request.form.get('next_page') + previous_page = request.form.get('previous_page') + if new_query is not None and new_query != '': + return redirect(url_for('search', query=new_query, page=1)) + if country is not None and country != get_cookie('country'): +~~ response = make_response( + redirect(url_for('category', category=category, page=1))) + response.set_cookie('country', country) + return response + if next_page is not None: + page = int(next_page) + 1 + elif previous_page is not None: + page = int(previous_page) - 1 + if category == 'search': + return redirect(url_for('search', query=current_query, page=page)) + return redirect(url_for('category', category=category, page=page)) + + +def parse_articles(response: dict) -> list: + parsed_articles = [] + if response.get('status') == 'ok': + for article in response.get('articles'): + parsed_articles.append({ + 'published_at': + parser.isoparse(article['publishedAt'] + ).strftime('%Y-%m-%d %H:%M'), + 'title': + article['title'], + 'url': + article['url'], + + +## ... source file continues with no further make_response examples... + +``` + + +## Example 6 from sandman2 +[sandman2](https://github.com/jeffknupp/sandman2) +([project documentation](https://sandman2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/sandman2/)) +is a code library for automatically generating +[RESTful APIs](/application-programming-interfaces.html) from +existing database schemas. This approach is handy for solving +straightforward situations where you want to put an abstraction +layer between one or more applications and your +[relational database](/databases.html) to prevent or reduce +direct database access. + +The sandman2 project is provided under the +[Apache License 2.0](https://github.com/jeffknupp/sandman2/blob/master/LICENSE). + +[**sandman2 / sandman2 / service.py**](https://github.com/jeffknupp/sandman2/blob/master/sandman2/./service.py) + +```python +# service.py + +~~from flask import request, make_response +import flask +from flask.views import MethodView +from sqlalchemy import asc, desc + +from sandman2.exception import NotFoundException, BadRequestException +from sandman2.model import db +from sandman2.decorators import etag, validate_fields + + +def add_link_headers(response, links): + link_string = '<{}>; rel=self'.format(links['self']) + for link in links.values(): + link_string += ', <{}>; rel=related'.format(link) + response.headers['Link'] = link_string + return response + + +def jsonify(resource): + + response = flask.jsonify(resource.to_dict()) + response = add_link_headers(response, resource.links()) + return response + + + + +## ... source file abbreviated to get to make_response examples ... + + + for key, value in args.items(): + if value.startswith('%'): + filters.append(getattr(self.__model__, key).like(str(value), escape='/')) + elif key == 'sort': + direction = desc if value.startswith('-') else asc + order.append(direction(getattr(self.__model__, value.lstrip('-')))) + elif key == 'limit': + limit = int(value) + elif hasattr(self.__model__, key): + filters.append(getattr(self.__model__, key) == value) + else: + raise BadRequestException('Invalid field [{}]'.format(key)) + queryset = queryset.filter(*filters).order_by(*order) + if 'page' in request.args: + resources = queryset.paginate(page=int(request.args['page']), per_page=limit).items + else: + queryset = queryset.limit(limit) + resources = queryset.all() + return [r.to_dict() for r in resources] + + def _export(self, collection): + fieldnames = collection[0].keys() + faux_csv = ','.join(fieldnames) + '\r\n' + for resource in collection: + faux_csv += ','.join((str(x) for x in resource.values())) + '\r\n' +~~ response = make_response(faux_csv) + response.mimetype = 'text/csv' + return response + + + @staticmethod + def _no_content_response(): +~~ response = make_response() + response.status_code = 204 + return response + + @staticmethod + def _created_response(resource): + response = jsonify(resource) + response.status_code = 201 + return response + + + +## ... source file continues with no further make_response examples... + +``` + diff --git a/content/pages/examples/flask/flask-helpers-safe-join.markdown b/content/pages/examples/flask/flask-helpers-safe-join.markdown new file mode 100644 index 000000000..1382094d8 --- /dev/null +++ b/content/pages/examples/flask/flask-helpers-safe-join.markdown @@ -0,0 +1,125 @@ +title: flask.helpers safe_join Example Code +category: page +slug: flask-helpers-safe-join-examples +sortorder: 500021021 +toc: False +sidebartitle: flask.helpers safe_join +meta: Python example code that shows how to use the safe_join callable from the flask.helpers module of the Flask project. + + +`safe_join` is a callable within the `flask.helpers` module of the Flask project. + +flash, +get_root_path, +make_response, +send_file, +and url_for +are several other callables with code examples from the same `flask.helpers` package. + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / CTFd / __init__.py**](https://github.com/CTFd/CTFd/blob/master/./CTFd/__init__.py) + +```python +# __init__.py +import datetime +import os +import sys +import weakref +from distutils.version import StrictVersion + +import jinja2 +from flask import Flask, Request +~~from flask.helpers import safe_join +from flask_migrate import upgrade +from jinja2 import FileSystemLoader +from jinja2.sandbox import SandboxedEnvironment +from werkzeug.middleware.proxy_fix import ProxyFix +from werkzeug.utils import cached_property + +import CTFd.utils.config +from CTFd import utils +from CTFd.constants.themes import ADMIN_THEME, DEFAULT_THEME +from CTFd.plugins import init_plugins +from CTFd.utils.crypto import sha256 +from CTFd.utils.initialization import ( + init_events, + init_logs, + init_request_processors, + init_template_filters, + init_template_globals, +) +from CTFd.utils.migrations import create_database, migrations, stamp_latest_revision +from CTFd.utils.sessions import CachingSessionInterface +from CTFd.utils.updates import update_check + +__version__ = "3.4.0" +__channel__ = "oss" + + +## ... source file abbreviated to get to safe_join examples ... + + + self.cache[cache_key] = template + return template + + +class ThemeLoader(FileSystemLoader): + + DEFAULT_THEMES_PATH = os.path.join(os.path.dirname(__file__), "themes") + _ADMIN_THEME_PREFIX = ADMIN_THEME + "/" + + def __init__( + self, + searchpath=DEFAULT_THEMES_PATH, + theme_name=None, + encoding="utf-8", + followlinks=False, + ): + super(ThemeLoader, self).__init__(searchpath, encoding, followlinks) + self.theme_name = theme_name + + def get_source(self, environment, template): + if template.startswith(self._ADMIN_THEME_PREFIX): + if self.theme_name != ADMIN_THEME: + raise jinja2.TemplateNotFound(template) + template = template[len(self._ADMIN_THEME_PREFIX) :] + theme_name = self.theme_name or str(utils.get_config("ctf_theme")) +~~ template = safe_join(theme_name, "templates", template) + return super(ThemeLoader, self).get_source(environment, template) + + +def confirm_upgrade(): + if sys.stdin.isatty(): + print("/*\\ CTFd has updated and must update the database! /*\\") + print("/*\\ Please backup your database before proceeding! /*\\") + print("/*\\ CTFd maintainers are not responsible for any data loss! /*\\") + if input("Run database migrations (Y/N)").lower().strip() == "y": # nosec B322 + return True + else: + print("/*\\ Ignored database migrations... /*\\") + return False + else: + return True + + +def run_upgrade(): + upgrade() + utils.set_config("ctf_version", __version__) + + +def create_app(config="CTFd.config.Config"): + app = CTFdFlask(__name__) + + +## ... source file continues with no further safe_join examples... + +``` + diff --git a/content/pages/examples/flask/flask-helpers-send-file.markdown b/content/pages/examples/flask/flask-helpers-send-file.markdown new file mode 100644 index 000000000..726a0993c --- /dev/null +++ b/content/pages/examples/flask/flask-helpers-send-file.markdown @@ -0,0 +1,150 @@ +title: flask.helpers send_file Example Code +category: page +slug: flask-helpers-send-file-examples +sortorder: 500021022 +toc: False +sidebartitle: flask.helpers send_file +meta: Python example code that shows how to use the send_file callable from the flask.helpers module of the Flask project. + + +[send_file](https://github.com/pallets/flask/blob/master/src/flask/helpers.py) +is function in the [Flask](/flask.html) `flask.helpers` module. +`send_file` transfers the contents of a file to the client using the most +efficient method available and configured in the Flask settings. It +attempts to guess the correct mimetype to use but it can also be +explicitly configured. + +Note that `send_file` is usually imported directly from `flask` instead of +from `flask.helpers`, even though it is defined within the `helpers` module. +It's the same function that is imported, but it's less characters to type +when you leave off the `.helpers` part. + +flash, +get_root_path, +make_response, +safe_join, +and url_for +are several other callables with code examples from the same `flask.helpers` package. + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / CTFd / views.py**](https://github.com/CTFd/CTFd/blob/master/./CTFd/views.py) + +```python +# views.py +import os + +from flask import Blueprint, abort +from flask import current_app as app +~~from flask import redirect, render_template, request, send_file, session, url_for +from flask.helpers import safe_join +from jinja2.exceptions import TemplateNotFound +from sqlalchemy.exc import IntegrityError + +from CTFd.cache import cache +from CTFd.constants.config import ( + AccountVisibilityTypes, + ChallengeVisibilityTypes, + ConfigTypes, + RegistrationVisibilityTypes, + ScoreVisibilityTypes, +) +from CTFd.constants.themes import DEFAULT_THEME +from CTFd.models import ( + Admins, + Files, + Notifications, + Pages, + Teams, + Users, + UserTokens, + db, +) +from CTFd.utils import config, get_config, set_config + + +## ... source file abbreviated to get to send_file examples ... + + + if team.banned: + abort(403) + else: + pass + + if file_id != f.id: + abort(403) + + except (BadTimeSignature, SignatureExpired, BadSignature): + abort(403) + + uploader = get_uploader() + try: + return uploader.download(f.location) + except IOError: + abort(404) + + +@views.route("/themes//static/") +def themes(theme, path): + for cand_path in ( + safe_join(app.root_path, "themes", cand_theme, "static", path) + for cand_theme in (theme, *config.ctf_theme_candidates()) + ): + if os.path.isfile(cand_path): +~~ return send_file(cand_path) + abort(404) + + + +## ... source file continues with no further send_file examples... + +``` + + +## Example 2 from Flask-VueJs-Template +[Flask-VueJs-Template](https://github.com/gtalarico/flask-vuejs-template) +([demo site](https://flask-vuejs-template.herokuapp.com/)) +is a minimal [Flask](/flask.html) boilerplate starter project that +combines Flask, [Vue.js](https://www.fullstackpython.com/vuejs.html), +and [Flask-RESTPlus](https://flask-restplus.readthedocs.io/en/stable/). +The project provides some sensible defaults that are easy to continue +building on, and the source code is open source under the +[MIT license](https://github.com/gtalarico/flask-vuejs-template/blob/master/LICENSE.md). + +[**Flask-VueJs-Template / app / __init__.py**](https://github.com/gtalarico/flask-vuejs-template/blob/master/app/./__init__.py) + +```python +# __init__.py +import os +~~from flask import Flask, current_app, send_file + +from .api import api_bp +from .client import client_bp + +app = Flask(__name__, static_folder='../dist/static') +app.register_blueprint(api_bp) + +from .config import Config +app.logger.info('>>> {}'.format(Config.FLASK_ENV)) + +@app.route('/') +def index_client(): + dist_dir = current_app.config['DIST_DIR'] + entry = os.path.join(dist_dir, 'index.html') +~~ return send_file(entry) + + + + + +## ... source file continues with no further send_file examples... + +``` + diff --git a/content/pages/examples/flask/flask-helpers-url-for.markdown b/content/pages/examples/flask/flask-helpers-url-for.markdown new file mode 100644 index 000000000..9dab48b41 --- /dev/null +++ b/content/pages/examples/flask/flask-helpers-url-for.markdown @@ -0,0 +1,1450 @@ +title: flask.helpers url_for Example Code +category: page +slug: flask-helpers-url-for-examples +sortorder: 500021023 +toc: False +sidebartitle: flask.helpers url_for +meta: Python example code that shows how to use the url_for callable from the flask.helpers module of the Flask project. + + +[url_for](https://github.com/pallets/flask/blob/master/src/flask/helpers.py) +is function in the [Flask](/flask.html) `flask.helpers` module. +`url_for` generates a URL to an endpoint using the method passed in +as an argument. + +Note that `url_for` is typically imported directly from `flask` instead of +from `flask.helpers`, even though it is defined within the `helpers` module. +It is the same function that is imported, but it's less characters to type +when you leave off the `.helpers` part. + +flash, +get_root_path, +make_response, +safe_join, +and send_file +are several other callables with code examples from the same `flask.helpers` package. + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / tests / test_views.py**](https://github.com/CTFd/CTFd/blob/master/./tests/test_views.py) + +```python +# test_views.py + +import os + +~~from flask import url_for +from freezegun import freeze_time + +from CTFd.cache import clear_pages +from CTFd.utils import set_config +from CTFd.utils.config.pages import get_pages +from CTFd.utils.encoding import hexencode +from tests.helpers import ( + create_ctfd, + destroy_ctfd, + gen_challenge, + gen_file, + gen_page, + login_as_user, + register_user, +) + + +def test_index(): + app = create_ctfd() + with app.app_context(): + with app.test_client() as client: + r = client.get("/") + assert r.status_code == 200 + destroy_ctfd(app) + + +## ... source file abbreviated to get to url_for examples ... + + + register_user(app) + client = login_as_user(app) + r = client.get("/profile") + assert r.status_code == 200 + destroy_ctfd(app) + + +def test_user_can_access_files(): + app = create_ctfd() + with app.app_context(): + from CTFd.utils.uploads import rmdir + + chal = gen_challenge(app.db) + chal_id = chal.id + path = app.config.get("UPLOAD_FOLDER") + + location = os.path.join(path, "test_file_path", "test.txt") + directory = os.path.dirname(location) + model_path = os.path.join("test_file_path", "test.txt") + + try: + os.makedirs(directory) + with open(location, "wb") as obj: + obj.write("testing file load".encode()) + gen_file(app.db, location=model_path, challenge_id=chal_id) +~~ url = url_for("views.files", path=model_path) + + set_config("challenge_visibility", "public") + with app.test_client() as client: + r = client.get(url) + + assert r.status_code == 200 + assert r.get_data(as_text=True) == "testing file load" + + set_config("challenge_visibility", "private") + with app.test_client() as client: + r = client.get(url) + + assert r.status_code == 403 + assert r.get_data(as_text=True) != "testing file load" + + register_user(app) + client = login_as_user(app) + r = client.get(url) + assert r.status_code == 200 + assert r.get_data(as_text=True) == "testing file load" + + with freeze_time("2017-10-5"): + set_config("start", "1507262400") + for v in ("public", "private"): + + +## ... source file abbreviated to get to url_for examples ... + + + finally: + rmdir(directory) + destroy_ctfd(app) + + +def test_user_can_access_files_with_auth_token(): + app = create_ctfd() + with app.app_context(): + from CTFd.utils.uploads import rmdir + + chal = gen_challenge(app.db) + chal_id = chal.id + path = app.config.get("UPLOAD_FOLDER") + + md5hash = hexencode(os.urandom(16)) + + location = os.path.join(path, md5hash, "test.txt") + directory = os.path.dirname(location) + model_path = os.path.join(md5hash, "test.txt") + + try: + os.makedirs(directory) + with open(location, "wb") as obj: + obj.write("testing file load".encode()) + gen_file(app.db, location=model_path, challenge_id=chal_id) +~~ url = url_for("views.files", path=model_path) + + register_user(app) + with login_as_user(app) as client: + req = client.get("/api/v1/challenges/1") + data = req.get_json() + file_url = data["data"]["files"][0] + + with app.test_client() as client: + r = client.get(url) + assert r.status_code == 403 + assert r.get_data(as_text=True) != "testing file load" + + r = client.get( +~~ url_for( + "views.files", + path=model_path, + token="random_token_that_shouldnt_work", + ) + ) + assert r.status_code == 403 + assert r.get_data(as_text=True) != "testing file load" + + r = client.get(file_url) + assert r.status_code == 200 + assert r.get_data(as_text=True) == "testing file load" + + set_config("challenge_visibility", "admins") + r = client.get(file_url) + assert r.status_code == 403 + assert r.get_data(as_text=True) != "testing file load" + set_config("challenge_visibility", "private") + + with freeze_time("2017-10-5"): + set_config("start", "1507262400") + + r = client.get(file_url) + assert r.status_code == 403 + assert r.get_data(as_text=True) != "testing file load" + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 2 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / menu.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/./menu.py) + +```python +# menu.py +from typing import List + +~~from flask import current_app, url_for +from flask_babel import gettext as __ + +from .api import BaseApi, expose +from .basemanager import BaseManager +from .security.decorators import permission_name, protect + + +class MenuItem(object): + def __init__( + self, name, href="", icon="", label="", childs=None, baseview=None, cond=None + ): + self.name = name + self.href = href + self.icon = icon + self.label = label + self.childs = childs or [] + self.baseview = baseview + self.cond = cond + + def should_render(self) -> bool: + return bool(self.cond()) if self.cond is not None else True + + def get_url(self): + if not self.href: + if not self.baseview: + return "" + else: +~~ return url_for(f"{self.baseview.endpoint}.{self.baseview.default_view}") + else: + try: +~~ return url_for(self.href) + except Exception: + return self.href + + def __repr__(self): + return self.name + + +class Menu(object): + def __init__(self, reverse=True, extra_classes=""): + self.menu = [] + if reverse: + extra_classes = extra_classes + "navbar-inverse" + self.extra_classes = extra_classes + + @property + def reverse(self): + return "navbar-inverse" in self.extra_classes + + def get_list(self): + return self.menu + + def get_flat_name_list(self, menu: "Menu" = None, result: List = None) -> List: + menu = menu or self.menu + result = result or [] + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 3 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / markup.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/./markup.py) + +```python +# markup.py +import logging +import re + +import mistune +~~from flask import url_for +from markupsafe import Markup +from pluggy import HookimplMarker +from pygments import highlight +from pygments.formatters import HtmlFormatter +from pygments.lexers import get_lexer_by_name +from pygments.util import ClassNotFound + +impl = HookimplMarker('flaskbb') + +logger = logging.getLogger(__name__) + +_re_user = re.compile(r'@(\w+)', re.I) + + +def userify(match): + value = match.group(1) + user = "@{user}".format( +~~ url=url_for("user.profile", username=value, _external=False), + user=value + ) + return user + + +class FlaskBBRenderer(mistune.Renderer): + + def __init__(self, **kwargs): + super(FlaskBBRenderer, self).__init__(**kwargs) + + def paragraph(self, text): + + text = _re_user.sub(userify, text) + return super(FlaskBBRenderer, self).paragraph(text) + + def block_code(self, code, lang): + if lang: + try: + lexer = get_lexer_by_name(lang, stripall=True) + except ClassNotFound: + lexer = None + else: + lexer = None + if not lexer: + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 4 from flask-base +[flask-base](https://github.com/hack4impact/flask-base) +([project documentation](http://hack4impact.github.io/flask-base/)) +provides boilerplate code for new [Flask](/flask.html) web apps. +The purpose of the boilerplate is to stitch together disparate +libraries that are commonly used in Flask projects, such as +[Redis](/redis.html) for fast caching and transient data storage, +[SendGrid](https://www.twilio.com/sendgrid) for transactional email, +[SQLAlchemy](/sqlalchemy.html) for persistent data storage through a +[relational database](/databases.html) backend, +[Flask-WTF](https://flask-wtf.readthedocs.io/) for form +handling and many others. + +flask-base is provided as open source under the +[MIT license](https://github.com/hack4impact/flask-base/blob/master/LICENSE.md). + +[**flask-base / app / utils.py**](https://github.com/hack4impact/flask-base/blob/master/app/./utils.py) + +```python +# utils.py +~~from flask import url_for +from wtforms.fields import Field +from wtforms.widgets import HiddenInput +from wtforms.compat import text_type + + +def register_template_utils(app): + + @app.template_test() + def equalto(value, other): + return value == other + + @app.template_global() + def is_hidden_field(field): + from wtforms.fields import HiddenField + return isinstance(field, HiddenField) + + app.add_template_global(index_for_role) + + +def index_for_role(role): +~~ return url_for(role.index) + + +class CustomSelectField(Field): + widget = HiddenInput() + + def __init__(self, label='', validators=None, multiple=False, + choices=[], allow_custom=True, **kwargs): + super(CustomSelectField, self).__init__(label, validators, **kwargs) + self.multiple = multiple + self.choices = choices + self.allow_custom = allow_custom + + def _value(self): + return text_type(self.data) if self.data is not None else '' + + def process_formdata(self, valuelist): + if valuelist: + self.data = valuelist[1] + self.raw_data = [valuelist[1]] + else: + self.data = '' + + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 5 from flask-bones +[flask-bones](https://github.com/cburmeister/flask-bones) +([demo](http://flask-bones.herokuapp.com/)) +is large scale [Flask](/flask.html) example application built +with [Blueprints](https://flask.palletsprojects.com/en/1.1.x/blueprints/) +([example Blueprint code](/flask-blueprints-blueprint-examples.html)). +This project is provided as open source under the +[MIT license](https://github.com/cburmeister/flask-bones/blob/master/LICENSE). + +[**flask-bones / app / utils.py**](https://github.com/cburmeister/flask-bones/blob/master/app/./utils.py) + +```python +# utils.py +~~from flask import request, url_for + + +def url_for_other_page(**kwargs): + url_for_args = request.args.copy() + if 'pjax' in url_for_args: + url_for_args.pop('_pjax') + for key, value in kwargs.items(): + url_for_args[key] = value +~~ return url_for(request.endpoint, **url_for_args) + + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 6 from Flask-Bootstrap +[flask-bootstrap](https://github.com/mbr/flask-bootstrap) +([PyPI package information](https://pypi.org/project/Flask-Bootstrap/)) +makes it easier to use the [Bootstrap CSS framework](/bootstrap-css.html) +in your [Flask](/flask.html) applications with less boilerplate +code. The project was primarily created by +[Marc Brinkmann @mbr](https://github.com/mbr) and the source code is +open sourced under the +[Apache 2.0 license](https://github.com/mbr/flask-bootstrap/blob/master/LICENSE). + +[**Flask-Bootstrap / flask_bootstrap / __init__.py**](https://github.com/mbr/flask-bootstrap/blob/master/flask_bootstrap/./__init__.py) + +```python +# __init__.py + +import re + +~~from flask import Blueprint, current_app, url_for + +try: + from wtforms.fields import HiddenField +except ImportError: + + def is_hidden_field_filter(field): + raise RuntimeError('WTForms is not installed.') +else: + + def is_hidden_field_filter(field): + return isinstance(field, HiddenField) + + +from .forms import render_form + +__version__ = '3.3.7.1.dev1' +BOOTSTRAP_VERSION = re.sub(r'^(\d+\.\d+\.\d+).*', r'\1', __version__) +JQUERY_VERSION = '1.12.4' +HTML5SHIV_VERSION = '3.7.3' +RESPONDJS_VERSION = '1.4.2' + + +class CDN(object): + + def get_resource_url(self, filename): + raise NotImplementedError + + +class StaticCDN(object): + + def __init__(self, static_endpoint='static', rev=False): + self.static_endpoint = static_endpoint + self.rev = rev + + def get_resource_url(self, filename): + extra_args = {} + + if self.rev and current_app.config['BOOTSTRAP_QUERYSTRING_REVVING']: + extra_args['bootstrap'] = __version__ + +~~ return url_for(self.static_endpoint, filename=filename, **extra_args) + + +class WebCDN(object): + + def __init__(self, baseurl): + self.baseurl = baseurl + + def get_resource_url(self, filename): + return self.baseurl + filename + + +class ConditionalCDN(object): + + def __init__(self, confvar, primary, fallback): + self.confvar = confvar + self.primary = primary + self.fallback = fallback + + def get_resource_url(self, filename): + if current_app.config[self.confvar]: + return self.primary.get_resource_url(filename) + return self.fallback.get_resource_url(filename) + + + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 7 from flask-debugtoolbar +[Flask Debug-toolbar](https://github.com/flask-debugtoolbar/flask-debugtoolbar) +([documentation](https://flask-debugtoolbar.readthedocs.io/en/latest/) +and +[PyPI page](https://pypi.org/project/Flask-DebugToolbar/)) +is a [Flask](/flask.html) conversion of the popular +[Django Debug Toolbar](https://github.com/jazzband/django-debug-toolbar) +project. This extension creates a sidebar with useful debugging +information when you are running a Flask application in development +mode. The project is provided as open source under +[this license](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/LICENSE). + +[**flask-debugtoolbar / flask_debugtoolbar / toolbar.py**](https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/flask_debugtoolbar/./toolbar.py) + +```python +# toolbar.py +try: + from urllib.parse import unquote +except ImportError: + from urllib import unquote + +~~from flask import url_for, current_app +from werkzeug.utils import import_string + + +class DebugToolbar(object): + + _cached_panel_classes = {} + + def __init__(self, request, jinja_env): + self.jinja_env = jinja_env + self.request = request + self.panels = [] + + self.template_context = { +~~ 'static_path': url_for('_debug_toolbar.static', filename='') + } + + self.create_panels() + + def create_panels(self): + activated = self.request.cookies.get('fldt_active', '') + activated = unquote(activated).split(';') + + for panel_class in self._iter_panels(current_app): + panel_instance = panel_class(jinja_env=self.jinja_env, + context=self.template_context) + + if panel_instance.dom_id() in activated: + panel_instance.is_active = True + + self.panels.append(panel_instance) + + def render_toolbar(self): + context = self.template_context.copy() + context.update({'panels': self.panels}) + + template = self.jinja_env.get_template('base.html') + return template.render(**context) + + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 8 from flask-login +[Flask-Login](https://github.com/maxcountryman/flask-login) +([project documentation](https://flask-login.readthedocs.io/en/latest/) +and [PyPI package](https://pypi.org/project/Flask-Login/)) +is a [Flask](/flask.html) extension that provides user session +management, which handles common tasks such as logging in +and out of a [web application](/web-development.html) and +managing associated user session data. Flask-Login is +open sourced under the +[MIT license](https://github.com/maxcountryman/flask-login/blob/master/LICENSE). + +[**flask-login / flask_login / utils.py**](https://github.com/maxcountryman/flask-login/blob/master/flask_login/./utils.py) + +```python +# utils.py + + +import hmac +from hashlib import sha512 +from functools import wraps +from werkzeug.local import LocalProxy +from werkzeug.security import safe_str_cmp +from werkzeug.urls import url_decode, url_encode + +~~from flask import (_request_ctx_stack, current_app, request, session, url_for, + has_request_context) + +from ._compat import text_type, urlparse, urlunparse +from .config import COOKIE_NAME, EXEMPT_METHODS +from .signals import user_logged_in, user_logged_out, user_login_confirmed + + +current_user = LocalProxy(lambda: _get_user()) + + +def encode_cookie(payload, key=None): + return u'{0}|{1}'.format(payload, _cookie_digest(payload, key=key)) + + +def decode_cookie(cookie, key=None): + try: + payload, digest = cookie.rsplit(u'|', 1) + if hasattr(digest, 'decode'): + digest = digest.decode('ascii') # pragma: no cover + except ValueError: + return + + if safe_str_cmp(_cookie_digest(payload, key=key), digest): + return payload + + +def make_next_param(login_url, current_url): + l_url = urlparse(login_url) + c_url = urlparse(current_url) + + if (not l_url.scheme or l_url.scheme == c_url.scheme) and \ + (not l_url.netloc or l_url.netloc == c_url.netloc): + return urlunparse(('', '', c_url.path, c_url.params, c_url.query, '')) + return current_url + + +def expand_login_view(login_view): + if login_view.startswith(('https://', 'http://', '/')): + return login_view + else: + if request.view_args is None: +~~ return url_for(login_view) + else: +~~ return url_for(login_view, **request.view_args) + + +def login_url(login_view, next_url=None, next_field='next'): + base = expand_login_view(login_view) + + if next_url is None: + return base + + parsed_result = urlparse(base) + md = url_decode(parsed_result.query) + md[next_field] = make_next_param(base, next_url) + netloc = current_app.config.get('FORCE_HOST_FOR_REDIRECTS') or \ + parsed_result.netloc + parsed_result = parsed_result._replace(netloc=netloc, + query=url_encode(md, sort=True)) + return urlunparse(parsed_result) + + +def login_fresh(): + return session.get('_fresh', False) + + +def login_user(user, remember=False, duration=None, force=False, fresh=True): + if not force and not user.is_active: + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 9 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / apidoc.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./apidoc.py) + +```python +# apidoc.py +from __future__ import unicode_literals + +~~from flask import url_for, Blueprint, render_template + + +class Apidoc(Blueprint): + + def __init__(self, *args, **kwargs): + self.registered = False + super(Apidoc, self).__init__(*args, **kwargs) + + def register(self, *args, **kwargs): + super(Apidoc, self).register(*args, **kwargs) + self.registered = True + + +apidoc = Apidoc( + "restx_doc", + __name__, + template_folder="templates", + static_folder="static", + static_url_path="/swaggerui", +) + + +@apidoc.add_app_template_global +def swagger_static(filename): +~~ return url_for("restx_doc.static", filename=filename) + + +def ui_for(api): + return render_template("swagger-ui.html", title=api.title, specs_url=api.specs_url) + + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 10 from flaskSaaS +[flaskSaas](https://github.com/alectrocute/flaskSaaS) is a boilerplate +starter project to build a software-as-a-service (SaaS) web application +in [Flask](/flask.html), with [Stripe](/stripe.html) for billing. The +boilerplate relies on many common Flask extensions such as +[Flask-WTF](https://flask-wtf.readthedocs.io/), +[Flask-Login](https://flask-login.readthedocs.io/en/latest/), +[Flask-Admin](https://flask-admin.readthedocs.io/en/latest/), and +many others. The project is provided as open source under the +[MIT license](https://github.com/alectrocute/flaskSaaS/blob/master/LICENSE). + +[**flaskSaaS / app / views / user.py**](https://github.com/alectrocute/flaskSaaS/blob/master/app/views/user.py) + +```python +# user.py +~~from flask import (Blueprint, render_template, redirect, request, url_for, + abort, flash) +from flask.ext.login import login_user, logout_user, login_required, current_user +from itsdangerous import URLSafeTimedSerializer +from app import app, models, db +from app.forms import user as user_forms +from app.toolbox import email +import stripe +import json +from json import dumps + +stripe_keys = { + 'secret_key': "sk_test_GvpPOs0XFxeP0fQiWMmk6HYe", + 'publishable_key': "pk_test_UU62FhsIB6457uPiUX6mJS5x" +} + +stripe.api_key = stripe_keys['secret_key'] + +ts = URLSafeTimedSerializer(app.config['SECRET_KEY']) + +userbp = Blueprint('userbp', __name__, url_prefix='/user') + + +@userbp.route('/signup', methods=['GET', 'POST']) +def signup(): + form = user_forms.SignUp() + if form.validate_on_submit(): + user = models.User( + first_name=form.first_name.data, + last_name=form.last_name.data, + phone=form.phone.data, + email=form.email.data, + confirmation=False, + password=form.password.data, + ) + db.session.add(user) + db.session.commit() + subject = 'Please confirm your email address.' + token = ts.dumps(user.email, salt='email-confirm-key') +~~ confirmUrl = url_for('userbp.confirm', token=token, _external=True) + html = render_template('email/confirm.html', + confirm_url=confirmUrl) + email.send(user.email, subject, html) + flash('Check your emails to confirm your email address.', 'positive') + return redirect(url_for('index')) + return render_template('user/signup.html', form=form, title='Sign up') + + +@userbp.route('/confirm/', methods=['GET', 'POST']) +def confirm(token): + try: + email = ts.loads(token, salt='email-confirm-key', max_age=86400) + except: + abort(404) + user = models.User.query.filter_by(email=email).first() + user.confirmation = True + db.session.commit() + flash( + 'Your email address has been confirmed, you can sign in.', 'positive') + return redirect(url_for('userbp.signin')) + + +@userbp.route('/signin', methods=['GET', 'POST']) +def signin(): + + +## ... source file abbreviated to get to url_for examples ... + + + return redirect(url_for('userbp.signin')) + return render_template('user/signin.html', form=form, title='Sign in') + + +@userbp.route('/signout') +def signout(): + logout_user() + flash('Succesfully signed out.', 'positive') + return redirect(url_for('index')) + + +@userbp.route('/account') +@login_required +def account(): + return render_template('user/account.html', title='Account') + + +@userbp.route('/forgot', methods=['GET', 'POST']) +def forgot(): + form = user_forms.Forgot() + if form.validate_on_submit(): + user = models.User.query.filter_by(email=form.email.data).first() + if user is not None: + subject = 'Reset your password.' + token = ts.dumps(user.email, salt='password-reset-key') +~~ resetUrl = url_for('userbp.reset', token=token, _external=True) + html = render_template('email/reset.html', reset_url=resetUrl) + email.send(user.email, subject, html) + flash('Check your emails to reset your password.', 'positive') + return redirect(url_for('index')) + else: + flash('Unknown email address.', 'negative') + return redirect(url_for('userbp.forgot')) + return render_template('user/forgot.html', form=form) + + +@userbp.route('/reset/', methods=['GET', 'POST']) +def reset(token): + try: + email = ts.loads(token, salt='password-reset-key', max_age=86400) + except: + abort(404) + form = user_forms.Reset() + if form.validate_on_submit(): + user = models.User.query.filter_by(email=email).first() + if user is not None: + user.password = form.password.data + db.session.commit() + flash('Your password has been reset, you can sign in.', 'positive') + return redirect(url_for('userbp.signin')) + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 11 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / email_manager.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/./email_manager.py) + +```python +# email_manager.py + + +~~from flask import render_template, url_for + +from flask_user import ConfigError + +class EmailManager(object): + + def __init__(self, app): + self.app = app + self.user_manager = app.user_manager + self.sender_name = self.user_manager.USER_EMAIL_SENDER_NAME + self.sender_email = self.user_manager.USER_EMAIL_SENDER_EMAIL + + if not self.sender_email: + raise ConfigError('Config setting USER_EMAIL_SENDER_EMAIL is missing.') + + if '@' not in self.sender_email: + raise ConfigError('Config setting USER_EMAIL_SENDER_EMAIL is not a valid email address.') + + + def send_confirm_email_email(self, user, user_email): + + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_ENABLE_CONFIRM_EMAIL: return + + email = user_email.email if user_email else user.email + + object_id = user_email.id if user_email else user.id + token = self.user_manager.generate_token(object_id) +~~ confirm_email_link = url_for('user.confirm_email', token=token, _external=True) + + self._render_and_send_email( + email, + user, + self.user_manager.USER_CONFIRM_EMAIL_TEMPLATE, + confirm_email_link=confirm_email_link, + ) + + def send_password_changed_email(self, user): + + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_SEND_PASSWORD_CHANGED_EMAIL: return + + user_or_user_email_object = self.user_manager.db_manager.get_primary_user_email_object(user) + email = user_or_user_email_object.email + + self._render_and_send_email( + email, + user, + self.user_manager.USER_PASSWORD_CHANGED_EMAIL_TEMPLATE, + ) + + def send_reset_password_email(self, user, user_email): + + if not self.user_manager.USER_ENABLE_EMAIL: return + assert self.user_manager.USER_ENABLE_FORGOT_PASSWORD + + email = user_email.email if user_email else user.email + + token = self.user_manager.generate_token(user.id) +~~ reset_password_link = url_for('user.reset_password', token=token, _external=True) + + self._render_and_send_email( + email, + user, + self.user_manager.USER_RESET_PASSWORD_EMAIL_TEMPLATE, + reset_password_link=reset_password_link, + ) + + def send_invite_user_email(self, user, user_invitation): + + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_ENABLE_INVITE_USER: return + + invited_by_user = user + + email = user_invitation.email + + user = self.user_manager.db_manager.UserClass(email=email) + + token = self.user_manager.generate_token(user_invitation.id) +~~ accept_invitation_link = url_for('user.register', token=token, _external=True) + + self._render_and_send_email( + email, + user, + self.user_manager.USER_INVITE_USER_EMAIL_TEMPLATE, + accept_invitation_link=accept_invitation_link, + invited_by_user=invited_by_user, + ) + + def send_registered_email(self, user, user_email, request_email_confirmation): + + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_SEND_REGISTERED_EMAIL: return + + email = user_email.email if user_email else user.email + + if request_email_confirmation: + token = self.user_manager.generate_token(user_email.id if user_email else user.id) +~~ confirm_email_link = url_for('user.confirm_email', token=token, _external=True) + else: + confirm_email_link = None + + self._render_and_send_email( + email, + user, + self.user_manager.USER_REGISTERED_EMAIL_TEMPLATE, + confirm_email_link=confirm_email_link, + ) + + def send_username_changed_email(self, user): + + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_SEND_USERNAME_CHANGED_EMAIL: return + + user_or_user_email_object = self.user_manager.db_manager.get_primary_user_email_object(user) + email = user_or_user_email_object.email + + self._render_and_send_email( + email, + user, + self.user_manager.USER_USERNAME_CHANGED_EMAIL_TEMPLATE, + ) + + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 12 from Flasky +[Flasky](https://github.com/miguelgrinberg/flasky) is a wonderful +example application by +[Miguel Grinberg](https://github.com/miguelgrinberg) that he builds +while teaching developers how to use [Flask](/flask.html) in +[his books and videos](https://courses.miguelgrinberg.com/). Flasky +is [open sourced under the MIT license](https://github.com/miguelgrinberg/flasky/blob/master/LICENSE). + +[**Flasky / app / models.py**](https://github.com/miguelgrinberg/flasky/blob/master/./app/models.py) + +```python +# models.py +from datetime import datetime +import hashlib +from werkzeug.security import generate_password_hash, check_password_hash +from itsdangerous import TimedJSONWebSignatureSerializer as Serializer +from markdown import markdown +import bleach +~~from flask import current_app, request, url_for +from flask_login import UserMixin, AnonymousUserMixin +from app.exceptions import ValidationError +from . import db, login_manager + + +class Permission: + FOLLOW = 1 + COMMENT = 2 + WRITE = 4 + MODERATE = 8 + ADMIN = 16 + + +class Role(db.Model): + __tablename__ = 'roles' + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(64), unique=True) + default = db.Column(db.Boolean, default=False, index=True) + permissions = db.Column(db.Integer) + users = db.relationship('User', backref='role', lazy='dynamic') + + def __init__(self, **kwargs): + super(Role, self).__init__(**kwargs) + if self.permissions is None: + + +## ... source file abbreviated to get to url_for examples ... + + + + def unfollow(self, user): + f = self.followed.filter_by(followed_id=user.id).first() + if f: + db.session.delete(f) + + def is_following(self, user): + if user.id is None: + return False + return self.followed.filter_by( + followed_id=user.id).first() is not None + + def is_followed_by(self, user): + if user.id is None: + return False + return self.followers.filter_by( + follower_id=user.id).first() is not None + + @property + def followed_posts(self): + return Post.query.join(Follow, Follow.followed_id == Post.author_id)\ + .filter(Follow.follower_id == self.id) + + def to_json(self): + json_user = { +~~ 'url': url_for('api.get_user', id=self.id), +~~ 'username': self.username, +~~ 'member_since': self.member_since, +~~ 'last_seen': self.last_seen, +~~ 'posts_url': url_for('api.get_user_posts', id=self.id), +~~ 'followed_posts_url': url_for('api.get_user_followed_posts', + id=self.id), + 'post_count': self.posts.count() + } + return json_user + + def generate_auth_token(self, expiration): + s = Serializer(current_app.config['SECRET_KEY'], + expires_in=expiration) + return s.dumps({'id': self.id}).decode('utf-8') + + @staticmethod + def verify_auth_token(token): + s = Serializer(current_app.config['SECRET_KEY']) + try: + data = s.loads(token) + except: + return None + return User.query.get(data['id']) + + def __repr__(self): + return '' % self.username + + +class AnonymousUser(AnonymousUserMixin): + + +## ... source file abbreviated to get to url_for examples ... + + +@login_manager.user_loader +def load_user(user_id): + return User.query.get(int(user_id)) + + +class Post(db.Model): + __tablename__ = 'posts' + id = db.Column(db.Integer, primary_key=True) + body = db.Column(db.Text) + body_html = db.Column(db.Text) + timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) + author_id = db.Column(db.Integer, db.ForeignKey('users.id')) + comments = db.relationship('Comment', backref='post', lazy='dynamic') + + @staticmethod + def on_changed_body(target, value, oldvalue, initiator): + allowed_tags = ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code', + 'em', 'i', 'li', 'ol', 'pre', 'strong', 'ul', + 'h1', 'h2', 'h3', 'p'] + target.body_html = bleach.linkify(bleach.clean( + markdown(value, output_format='html'), + tags=allowed_tags, strip=True)) + + def to_json(self): + json_post = { +~~ 'url': url_for('api.get_post', id=self.id), +~~ 'body': self.body, +~~ 'body_html': self.body_html, +~~ 'timestamp': self.timestamp, +~~ 'author_url': url_for('api.get_user', id=self.author_id), +~~ 'comments_url': url_for('api.get_post_comments', id=self.id), + 'comment_count': self.comments.count() + } + return json_post + + @staticmethod + def from_json(json_post): + body = json_post.get('body') + if body is None or body == '': + raise ValidationError('post does not have a body') + return Post(body=body) + + +db.event.listen(Post.body, 'set', Post.on_changed_body) + + +class Comment(db.Model): + __tablename__ = 'comments' + id = db.Column(db.Integer, primary_key=True) + body = db.Column(db.Text) + body_html = db.Column(db.Text) + timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) + disabled = db.Column(db.Boolean) + author_id = db.Column(db.Integer, db.ForeignKey('users.id')) + post_id = db.Column(db.Integer, db.ForeignKey('posts.id')) + + @staticmethod + def on_changed_body(target, value, oldvalue, initiator): + allowed_tags = ['a', 'abbr', 'acronym', 'b', 'code', 'em', 'i', + 'strong'] + target.body_html = bleach.linkify(bleach.clean( + markdown(value, output_format='html'), + tags=allowed_tags, strip=True)) + + def to_json(self): + json_comment = { +~~ 'url': url_for('api.get_comment', id=self.id), +~~ 'post_url': url_for('api.get_post', id=self.post_id), +~~ 'body': self.body, +~~ 'body_html': self.body_html, +~~ 'timestamp': self.timestamp, +~~ 'author_url': url_for('api.get_user', id=self.author_id), + } + return json_comment + + @staticmethod + def from_json(json_comment): + body = json_comment.get('body') + if body is None or body == '': + raise ValidationError('comment does not have a body') + return Comment(body=body) + + +db.event.listen(Comment.body, 'set', Comment.on_changed_body) + + + +## ... source file continues with no further url_for examples... + +``` + + +## Example 13 from Datadog Flask Example App +The [Datadog Flask example app](https://github.com/DataDog/trace-examples/tree/master/python/flask) +contains many examples of the [Flask](/flask.html) core functions +available to a developer using the [web framework](/web-frameworks.html). + +[**Datadog Flask Example App / python/flask/app / app.py**](https://github.com/DataDog/trace-examples/blob/master/python/flask/app/./app.py) + +```python +# app.py +from ddtrace import patch_all; patch_all(flask=True, requests=True) # noqa + +from ddtrace import tracer + +from flask import Flask, Response +from flask import after_this_request +~~from flask import abort, jsonify, render_template, url_for +from flask.views import View +from werkzeug.routing import Rule + +from flask_caching import Cache +from flask_cors import CORS + +import requests + +from .blueprint import bp +from .exceptions import AppException +from .limiter import limiter +from .signals import connect_signals + +app = Flask(__name__) + +app.register_blueprint(bp) + +connect_signals(app) + +CORS(app) +Cache(app, config=dict(CACHE_TYPE='simple')) +limiter.init_app(app) + + + + +## ... source file abbreviated to get to url_for examples ... + + +@app.after_request +def after_request(response): + print('Hook: after_request') + return response + + +@app.teardown_request +def teardown_request(response): + print('Hook: teardown_request') + return response + + +@app.teardown_appcontext +def teardown_appcontext(appcontext): + print('Hook: teardown_appcontext') + + +@app.route('/') +@limiter.limit('10 per second') +def index(): + routes = [ + dict( + rule='GET /', + description=['Endpoint for this page, which uses render_template().'], + links=[ +~~ dict(label='GET /', url=url_for('index')), + ], + ), + dict( + rule='GET /joke', + description=[ + 'Endpoint which uses requests to fetch a joke from icanhazdadjoke.com.', + 'This endpoint also registers a flask.after_this_request hook.' + ], + links=[ +~~ dict(label='GET /joke', url=url_for('joke')), + ], + ), + dict( + rule='GET /json', + description=[ + 'Endpoint which uses jsonify to return a JSON object to the user.', + ], + links=[ +~~ dict(label='GET /json', url=url_for('json')), + ], + ), + dict( + rule='GET /custom-endpoint/', + description=[ + ('Endpoint which was registered manually using @app.endpoint() ' + 'and app.add_url_rule()'), + 'This endpoint also has a /custom-endpoint/ url configured with a default ', + ('We have also attached a @tracer.wrap() to the endpoint and added a ' + 'with tracer.trace(): to the body of the view as well.'), + ], + links=[ +~~ dict(label='GET /custom-endpoint', url=url_for('custom-endpoint')), +~~ dict(label='GET /custom-endpoint/hello', url=url_for('custom-endpoint', msg='hello')), + ], + ), + dict( + rule='GET /custom-error', + description=[ + 'Endpoint which raises a customer user-defined Exception (non HTTPException)', + ], + links=[ +~~ dict(label='GET /custom-error', url=url_for('custom_error')), + ], + ), + dict( + rule='GET /stream', + description=[ + 'Endpoint which uses a generator to stream the response back to the user.', + ], + links=[ +~~ dict(label='GET /stream', url=url_for('stream')), + ], + ), + dict( + rule='GET /abort/', + description=[ + 'Endpoint which calls abort(code) for us', + ], + links=[ +~~ dict(label='GET /abort/{}'.format(code), url=url_for('abort_endpoint', code=code)) + for code in [400, 401, 403, 404, 500] + ], + ), + dict( + rule='GET /hello/', + description=[ + 'Endpoint which was generated from a flask.views.View', + ], + links=[ +~~ dict(label='GET /hello/Flask', url=url_for('myview', name='Flask')), + ], + ), + dict( + rule='GET /bp/', + description=[ + 'Blueprint endpoint that uses render_template_string()', + ], + links=[ +~~ dict(label='GET /bp/', url=url_for('bp.index')), + ], + ), + dict( + rule='GET /bp/unknown', + description=[ + 'Blueprint endpoint that calls abort(404)', + ], + links=[ +~~ dict(label='GET /bp/unkown', url=url_for('bp.unknown')), + ], + ), + dict( + rule='GET /static/test.txt', + description=[ + 'Endpoint to fetch a simple .txt static file.', + ], + links=[ +~~ dict(label='GET /static/test.txt', url=url_for('static', filename='test.txt')), + ], + ), + ] + return render_template('index.jinja2', routes=routes) + + +@app.route('/joke') +def joke(): + res = requests.get('https://icanhazdadjoke.com/', headers=dict(Accept='text/plain')) + res.raise_for_status() + + @after_this_request + def after_joke(response): + print('Hook: after_this_request') + return response + + return res.content + + +@app.route('/json') +def json(): + return jsonify(hello='world') + + + + +## ... source file continues with no further url_for examples... + +``` + diff --git a/content/pages/examples/flask/flask-json-jsonencoder.markdown b/content/pages/examples/flask/flask-json-jsonencoder.markdown new file mode 100644 index 000000000..7c217d86c --- /dev/null +++ b/content/pages/examples/flask/flask-json-jsonencoder.markdown @@ -0,0 +1,77 @@ +title: flask.json JSONEncoder Example Code +category: page +slug: flask-json-jsonencoder-examples +sortorder: 500021024 +toc: False +sidebartitle: flask.json JSONEncoder +meta: Example code for understanding how to use the JSONEncoder class from the flask.json module of the Flask project. + + +[JSONEncoder](https://github.com/pallets/flask/blob/master/src/flask/json/__init__.py) +is a class within the [Flask](/flask.html) project under the `flask.json` +module. `JSONEncoder` is the default [JSON](https://www.json.org/json-en.html) +encoder for Flask and was designed to handle more types than Python's +standard library [json](https://docs.python.org/3/library/json.html) module. + + +jsonify +is another callable from the `flask.json` package with code examples. + +## Example 1 from Flask-Security-Too +[Flask-Security-Too](https://github.com/Flask-Middleware/flask-security/) +([PyPi page](https://pypi.org/project/Flask-Security-Too/) and +[project documentation](https://flask-security-too.readthedocs.io/en/stable/)) +is a maintained fork of the original +[Flask-Security](https://github.com/mattupstate/flask-security) project that +makes it easier to add common security features to [Flask](/flask.html) +web applications. A few of the critical goals of the Flask-Security-Too +project are ensuring JavaScript client-based single-page applications (SPAs) +can work securely with Flask-based backends and that guidance by the +[OWASP](https://owasp.org/) organization is followed by default. + +The Flask-Security-Too project is provided as open source under the +[MIT license](https://github.com/Flask-Middleware/flask-security/blob/master/LICENSE). + +[**Flask-Security-Too / flask_security / core.py**](https://github.com/Flask-Middleware/flask-security/blob/master/flask_security/./core.py) + +```python +# core.py + +from datetime import datetime, timedelta +import re +import typing as t +import warnings + +import pkg_resources +from flask import _request_ctx_stack, current_app +~~from flask.json import JSONEncoder +from flask_login import AnonymousUserMixin, LoginManager +from flask_login import UserMixin as BaseUserMixin +from flask_login import current_user +from flask_principal import Identity, Principal, RoleNeed, UserNeed, identity_loaded +from flask_wtf import FlaskForm +from itsdangerous import URLSafeTimedSerializer +from passlib.context import CryptContext +from werkzeug.datastructures import ImmutableList +from werkzeug.local import LocalProxy + +from .babel import FsDomain +from .decorators import ( + default_reauthn_handler, + default_unauthn_handler, + default_unauthz_handler, +) +from .forms import ( + ChangePasswordForm, + ConfirmRegisterForm, + ForgotPasswordForm, + LoginForm, + PasswordlessLoginForm, + RegisterForm, + RegisterFormMixin, + + +## ... source file continues with no further JSONEncoder examples... + +``` + diff --git a/content/pages/examples/flask/flask-json-jsonify.markdown b/content/pages/examples/flask/flask-json-jsonify.markdown new file mode 100644 index 000000000..035721414 --- /dev/null +++ b/content/pages/examples/flask/flask-json-jsonify.markdown @@ -0,0 +1,1429 @@ +title: flask.json jsonify Example Code +category: page +slug: flask-json-jsonify-examples +sortorder: 500021025 +toc: False +sidebartitle: flask.json jsonify +meta: Python example code that shows how to use the jsonify callable from the flask.json module of the Flask project. + + +[jsonify](https://github.com/pallets/flask/blob/master/src/flask/json/__init__.py) +is a function in [Flask](/flask.html)'s `flask.json` module. `jsonify` +serializes data to +[JavaScript Object Notation (JSON)](https://www.json.org/json-en.html) format, +wraps it in a +[Response](https://blog.miguelgrinberg.com/post/customizing-the-flask-response-class) +object with the application/json mimetype. + +Note that `jsonify` is sometimes imported directly from the `flask` module +instead of from `flask.json`. It is the same function that is imported, but +there are less characters to type when you leave off the `.json` part. + +JSONEncoder +is another callable from the `flask.json` package with code examples. + +## Example 1 from Flask AppBuilder +[Flask-AppBuilder](https://github.com/dpgaspar/Flask-AppBuilder) +([documentation](https://flask-appbuilder.readthedocs.io/en/latest/) +and +[example apps](https://github.com/dpgaspar/Flask-AppBuilder/tree/master/examples)) +is a web application generator that uses Flask to automatically create +the code for database-driven applications based on parameters set +by the user. The generated applications include default security settings, +forms, and internationalization support. + +Flask App Builder is provided under the +[BSD 3-Clause "New" or "Revised" license](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/LICENSE). + +[**Flask AppBuilder / flask_appbuilder / security / decorators.py**](https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/security/decorators.py) + +```python +# decorators.py +import functools +import logging + +~~from flask import current_app, flash, jsonify, make_response, redirect, request, url_for +from flask_jwt_extended import verify_jwt_in_request +from flask_login import current_user + +from .._compat import as_unicode +from ..const import ( + FLAMSG_ERR_SEC_ACCESS_DENIED, + LOGMSG_ERR_SEC_ACCESS_DENIED, + PERMISSION_PREFIX, +) + +log = logging.getLogger(__name__) + + +def protect(allow_browser_login=False): + + def _protect(f): + if hasattr(f, "_permission_name"): + permission_str = f._permission_name + else: + permission_str = f.__name__ + + def wraps(self, *args, **kwargs): + permission_str = "{}{}".format(PERMISSION_PREFIX, f._permission_name) + if self.method_permission_name: + + +## ... source file abbreviated to get to jsonify examples ... + + + return functools.update_wrapper(wraps, f) + + +def has_access_api(f): + if hasattr(f, "_permission_name"): + permission_str = f._permission_name + else: + permission_str = f.__name__ + + def wraps(self, *args, **kwargs): + permission_str = "{}{}".format(PERMISSION_PREFIX, f._permission_name) + if self.method_permission_name: + _permission_name = self.method_permission_name.get(f.__name__) + if _permission_name: + permission_str = "{}{}".format(PERMISSION_PREFIX, _permission_name) + if permission_str in self.base_permissions and self.appbuilder.sm.has_access( + permission_str, self.class_permission_name + ): + return f(self, *args, **kwargs) + else: + log.warning( + LOGMSG_ERR_SEC_ACCESS_DENIED.format( + permission_str, self.__class__.__name__ + ) + ) +~~ response = make_response( +~~ jsonify( + {"message": str(FLAMSG_ERR_SEC_ACCESS_DENIED), "severity": "danger"} + ), + 401, + ) + response.headers["Content-Type"] = "application/json" + return response + + f._permission_name = permission_str + return functools.update_wrapper(wraps, f) + + +def permission_name(name): + + def wraps(f): + f._permission_name = name + return f + + return wraps + + + +## ... source file continues with no further jsonify examples... + +``` + + +## Example 2 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / management / views.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/management/views.py) + +```python +# views.py +import logging +import sys + +from celery import __version__ as celery_version +from flask import __version__ as flask_version +~~from flask import (Blueprint, current_app, flash, jsonify, redirect, request, + url_for) +from flask.views import MethodView +from flask_allows import Not, Permission +from flask_babelplus import gettext as _ +from flask_login import current_user, login_fresh +from pluggy import HookimplMarker + +from flaskbb import __version__ as flaskbb_version +from flaskbb.extensions import allows, celery, db +from flaskbb.forum.forms import UserSearchForm +from flaskbb.forum.models import Category, Forum, Post, Report, Topic +from flaskbb.management.forms import (AddForumForm, AddGroupForm, AddUserForm, + CategoryForm, EditForumForm, + EditGroupForm, EditUserForm) +from flaskbb.management.models import Setting, SettingsGroup +from flaskbb.plugins.models import PluginRegistry, PluginStore +from flaskbb.plugins.utils import validate_plugin +from flaskbb.user.models import Group, Guest, User +from flaskbb.utils.forms import populate_settings_dict, populate_settings_form +from flaskbb.utils.helpers import (get_online_users, register_view, + render_template, redirect_or_next, + time_diff, time_utcnow, FlashAndRedirect) +from flaskbb.utils.requirements import (CanBanUser, CanEditUser, IsAdmin, + IsAtleastModerator, + + +## ... source file abbreviated to get to jsonify examples ... + + + + flash(_('User updated.'), 'success') + return redirect(url_for('management.edit_user', user_id=user.id)) + + return render_template( + 'management/user_form.html', form=form, title=_('Edit User') + ) + + +class DeleteUser(MethodView): + decorators = [ + allows.requires( + IsAdmin, + on_fail=FlashAndRedirect( + message=_("You are not allowed to manage users"), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def post(self, user_id=None): + if request.get_json() is not None: + ids = request.get_json().get("ids") + if not ids: +~~ return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + data = [] + for user in User.query.filter(User.id.in_(ids)).all(): + if current_user.id == user.id: + continue + + if user.delete(): + data.append( + { + "id": user.id, + "type": "delete", + "reverse": False, + "reverse_name": None, + "reverse_url": None + } + ) + +~~ return jsonify( + message=f"{len(data)} users deleted.", + category="success", + data=data, + status=200 + ) + + user = User.query.filter_by(id=user_id).first_or_404() + + if current_user.id == user.id: + flash(_("You cannot delete yourself.", "danger")) + return redirect(url_for("management.users")) + + user.delete() + flash(_("User deleted."), "success") + return redirect(url_for("management.users")) + + +class AddUser(MethodView): + decorators = [ + allows.requires( + IsAdmin, + on_fail=FlashAndRedirect( + message=_("You are not allowed to manage users"), + level="danger", + + +## ... source file abbreviated to get to jsonify examples ... + + + + +class BanUser(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to manage users"), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def post(self, user_id=None): + if not Permission(CanBanUser, identity=current_user): + flash( + _("You do not have the permissions to ban this user."), + "danger" + ) + return redirect(url_for("management.overview")) + + if request.get_json() is not None: + ids = request.get_json().get("ids") + if not ids: +~~ return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + + data = [] + users = User.query.filter(User.id.in_(ids)).all() + for user in users: + if (current_user.id == user.id or + Permission(IsAdmin, identity=user) and + Permission(Not(IsAdmin), current_user)): + continue + + elif user.ban(): + data.append({ + "id": user.id, + "type": "ban", + "reverse": "unban", + "reverse_name": _("Unban"), + "reverse_url": url_for("management.unban_user", user_id=user.id) + }) + +~~ return jsonify( + message="{} users banned.".format(len(data)), + category="success", + data=data, + status=200 + ) + + user = User.query.filter_by(id=user_id).first_or_404() + if Permission(IsAdmin, identity=user) and Permission( + Not(IsAdmin), identity=current_user): + flash(_("A moderator cannot ban an admin user."), "danger") + return redirect(url_for("management.overview")) + + if not current_user.id == user.id and user.ban(): + flash(_("User is now banned."), "success") + else: + flash(_("Could not ban user."), "danger") + + return redirect_or_next(url_for("management.banned_users")) + + +class UnbanUser(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to manage users"), + level="danger", + endpoint="management.overview" + ) + + ) + ] + + def post(self, user_id=None): + + if not Permission(CanBanUser, identity=current_user): + flash( + _("You do not have the permissions to unban this user."), + "danger" + ) + return redirect(url_for("management.overview")) + + if request.get_json() is not None: + ids = request.get_json().get("ids") + if not ids: +~~ return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + + data = [] + for user in User.query.filter(User.id.in_(ids)).all(): + if user.unban(): + data.append( + { + "id": user.id, + "type": "ban", + "reverse": "ban", + "reverse_name": _("Ban"), + "reverse_url": url_for("management.ban_user", + user_id=user.id) + } + ) + +~~ return jsonify( + message=f"{len(data)} users unbanned.", + category="success", + data=data, + status=200 + ) + + user = User.query.filter_by(id=user_id).first_or_404() + + if user.unban(): + flash(_("User is now unbanned."), "success") + else: + flash(_("Could not unban user."), "danger") + + return redirect_or_next(url_for("management.users")) + + +class Groups(MethodView): + decorators = [ + allows.requires( + IsAdmin, + on_fail=FlashAndRedirect( + message=_("You are not allowed to modify groups."), + level="danger", + endpoint="management.overview" + + +## ... source file abbreviated to get to jsonify examples ... + + + + flash(_('Group updated.'), 'success') + return redirect(url_for('management.groups', group_id=group.id)) + + return render_template( + 'management/group_form.html', form=form, title=_('Edit Group') + ) + + +class DeleteGroup(MethodView): + decorators = [ + allows.requires( + IsAdmin, + on_fail=FlashAndRedirect( + message=_("You are not allowed to modify groups."), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def post(self, group_id=None): + if request.get_json() is not None: + ids = request.get_json().get("ids") + if not ids: +~~ return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + + if not (set(ids) & set(["1", "2", "3", "4", "5", "6"])): + data = [] + for group in Group.query.filter(Group.id.in_(ids)).all(): + group.delete() + data.append( + { + "id": group.id, + "type": "delete", + "reverse": False, + "reverse_name": None, + "reverse_url": None + } + ) + +~~ return jsonify( + message="{} groups deleted.".format(len(data)), + category="success", + data=data, + status=200 + ) +~~ return jsonify( + message=_("You cannot delete one of the standard groups."), + category="danger", + data=None, + status=404 + ) + + if group_id is not None: + if group_id <= 6: # there are 6 standard groups + flash( + _( + "You cannot delete the standard groups. " + "Try renaming it instead.", "danger" + ) + ) + return redirect(url_for("management.groups")) + + group = Group.query.filter_by(id=group_id).first_or_404() + group.delete() + flash(_("Group deleted."), "success") + return redirect(url_for("management.groups")) + + flash(_("No group chosen."), "danger") + return redirect(url_for("management.groups")) + + + +## ... source file abbreviated to get to jsonify examples ... + + + reports = Report.query.\ + filter(Report.zapped == None).\ + order_by(Report.id.desc()).\ + paginate(page, flaskbb_config['USERS_PER_PAGE'], False) + + return render_template("management/reports.html", reports=reports) + + +class MarkReportRead(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to view reports."), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def post(self, report_id=None): + + if request.get_json() is not None: + ids = request.get_json().get("ids") + if not ids: +~~ return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + data = [] + + for report in Report.query.filter(Report.id.in_(ids)).all(): + report.zapped_by = current_user.id + report.zapped = time_utcnow() + report.save() + data.append( + { + "id": report.id, + "type": "read", + "reverse": False, + "reverse_name": None, + "reverse_url": None + } + ) + +~~ return jsonify( + message="{} reports marked as read.".format(len(data)), + category="success", + data=data, + status=200 + ) + + if report_id: + report = Report.query.filter_by(id=report_id).first_or_404() + if report.zapped: + flash( + _("Report %(id)s is already marked as read.", id=report.id), + "success" + ) + return redirect_or_next(url_for("management.reports")) + + report.zapped_by = current_user.id + report.zapped = time_utcnow() + report.save() + flash(_("Report %(id)s marked as read.", id=report.id), "success") + return redirect_or_next(url_for("management.reports")) + + reports = Report.query.filter(Report.zapped == None).all() + report_list = [] + for report in reports: + + +## ... source file abbreviated to get to jsonify examples ... + + + report_list.append(report) + + db.session.add_all(report_list) + db.session.commit() + + flash(_("All reports were marked as read."), "success") + return redirect_or_next(url_for("management.reports")) + + +class DeleteReport(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to view reports."), + level="danger", + endpoint="management.overview" + ) + ) + ] + + def post(self, report_id=None): + if request.get_json() is not None: + ids = request.get_json().get("ids") + if not ids: +~~ return jsonify( + message="No ids provided.", + category="error", + status=404 + ) + + data = [] + for report in Report.query.filter(Report.id.in_(ids)).all(): + if report.delete(): + data.append( + { + "id": report.id, + "type": "delete", + "reverse": False, + "reverse_name": None, + "reverse_url": None + } + ) + +~~ return jsonify( + message="{} reports deleted.".format(len(data)), + category="success", + data=data, + status=200 + ) + + report = Report.query.filter_by(id=report_id).first_or_404() + report.delete() + flash(_("Report deleted."), "success") + return redirect_or_next(url_for("management.reports")) + + +class CeleryStatus(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to access the management settings"), # noqa + level="danger", + endpoint="management.overview" + ) + ) + ] + + def get(self): + celery_inspect = celery.control.inspect() + try: + celery_running = True if celery_inspect.ping() else False + except Exception: + celery_running = False + +~~ return jsonify(celery_running=celery_running, status=200) + + +class ManagementOverview(MethodView): + decorators = [ + allows.requires( + IsAtleastModerator, + on_fail=FlashAndRedirect( + message=_("You are not allowed to access the management panel"), + level="danger", + endpoint="forum.index" + ) + ) + ] + + def get(self): + banned_users = User.query.filter( + Group.banned == True, Group.id == User.primary_group_id + ).count() + if not current_app.config["REDIS_ENABLED"]: + online_users = User.query.filter(User.lastseen >= time_diff() + ).count() + else: + online_users = len(get_online_users()) + + + +## ... source file continues with no further jsonify examples... + +``` + + +## Example 3 from Flask-Meld +[Flask-Meld](https://github.com/mikeabrahamsen/Flask-Meld) +([PyPI package information](https://pypi.org/project/Flask-Meld/)) +allows you to write your front end web code in your back end +Python code. It does this by adding a `{% meld_scripts %}` tag to +the Flask template engine and then inserting components written +in Python scripts created by a developer. + +[**Flask-Meld / flask_meld / component.py**](https://github.com/mikeabrahamsen/Flask-Meld/blob/main/flask_meld/./component.py) + +```python +# component.py +import os +import uuid +from importlib.util import module_from_spec, spec_from_file_location +from itertools import groupby +from operator import itemgetter + +import orjson +from bs4 import BeautifulSoup +from bs4.element import Tag +from bs4.formatter import HTMLFormatter +~~from flask import current_app, jsonify, render_template +from jinja2.exceptions import TemplateNotFound + + +def convert_to_snake_case(s): + s.replace("-", "_") + return s + + +def convert_to_camel_case(s): + s = convert_to_snake_case(s) + return "".join(word.title() for word in s.split("_")) + + +def get_component_class(component_name): + module_name = convert_to_snake_case(component_name) + class_name = convert_to_camel_case(module_name) + module = get_component_module(module_name) + component_class = getattr(module, class_name) + + return component_class + + +def get_component_module(module_name): + user_specified_dir = current_app.config.get("MELD_COMPONENT_DIR", None) + + +## ... source file abbreviated to get to jsonify examples ... + + + + def _render_template(self, template_name: str, context_variables: dict): + try: + return render_template(template_name, **context_variables) + except TemplateNotFound: + return render_template(f"meld/{template_name}", **context_variables) + + def _view(self, component_name: str): + data = self._attributes() + context = self.__context__() + context_variables = {} + context_variables.update(context["attributes"]) + context_variables.update(context["methods"]) + context_variables.update({"form": self._form}) + + rendered_template = self._render_template( + f"{component_name}.html", context_variables + ) + + soup = BeautifulSoup(rendered_template, features="html.parser") + root_element = Component._get_root_element(soup) + root_element["meld:id"] = str(self.id) + self._set_values(root_element, context_variables) + + script = soup.new_tag("script", type="module") +~~ init = {"id": str(self.id), "name": component_name, "data": jsonify(data).json} + init_json = orjson.dumps(init).decode("utf-8") + + meld_import = 'import {Meld} from "/meld_js_src/meld.js";' + script.string = f"{meld_import} Meld.componentInit({init_json});" + root_element.append(script) + + rendered_template = Component._desoupify(soup) + + return rendered_template + + def _set_values(self, soup, context_variables): + for element in soup.select("input,select,textarea"): + model_attrs = [ + attr for attr in element.attrs.keys() if attr.startswith("meld:model") + ] + if len(model_attrs) > 1: + raise Exception( + "Multiple 'meld:model' attributes not allowed on one tag." + ) + + for model_attr in model_attrs: + value = context_variables[element.attrs[model_attr]] + element.attrs["value"] = value + if element.name == "select": + + +## ... source file continues with no further jsonify examples... + +``` + + +## Example 4 from flaskSaaS +[flaskSaas](https://github.com/alectrocute/flaskSaaS) is a boilerplate +starter project to build a software-as-a-service (SaaS) web application +in [Flask](/flask.html), with [Stripe](/stripe.html) for billing. The +boilerplate relies on many common Flask extensions such as +[Flask-WTF](https://flask-wtf.readthedocs.io/), +[Flask-Login](https://flask-login.readthedocs.io/en/latest/), +[Flask-Admin](https://flask-admin.readthedocs.io/en/latest/), and +many others. The project is provided as open source under the +[MIT license](https://github.com/alectrocute/flaskSaaS/blob/master/LICENSE). + +[**flaskSaaS / app / views / main.py**](https://github.com/alectrocute/flaskSaaS/blob/master/app/views/main.py) + +```python +# main.py +~~from flask import render_template, jsonify +from app import app +import random + + +@app.route('/') +@app.route('/index') +def index(): + return render_template('index.html', title='Home') + + +@app.route('/map') +def map(): + return render_template('map.html', title='Map') + + +@app.route('/map/refresh', methods=['POST']) +def map_refresh(): + points = [(random.uniform(48.8434100, 48.8634100), + random.uniform(2.3388000, 2.3588000)) + for _ in range(random.randint(2, 9))] +~~ return jsonify({'points': points}) + + +@app.route('/contact') +def contact(): + return render_template('contact.html', title='Contact') + + + +## ... source file continues with no further jsonify examples... + +``` + + +## Example 5 from Flask-SocketIO +[Flask-SocketIO](https://github.com/miguelgrinberg/Flask-SocketIO) +([PyPI package information](https://pypi.org/project/Flask-SocketIO/), +[official tutorial](https://blog.miguelgrinberg.com/post/easy-websockets-with-flask-and-gevent) +and +[project documentation](https://flask-socketio.readthedocs.io/en/latest/)) +is a code library by [Miguel Grinberg](https://blog.miguelgrinberg.com/index) +that provides Socket.IO integration for [Flask](/flask.html) applications. +This extension makes it easier to add bi-directional communications on the +web via the [WebSockets](/websockets.html) protocol. + +The Flask-SocketIO project is open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/LICENSE). + +[**Flask-SocketIO / example / sessions.py**](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/./example/sessions.py) + +```python +# sessions.py +~~from flask import Flask, render_template, session, request, jsonify +from flask_login import LoginManager, UserMixin, current_user, login_user, \ + logout_user +from flask_session import Session +from flask_socketio import SocketIO, emit + +app = Flask(__name__) +app.config['SECRET_KEY'] = 'top-secret!' +app.config['SESSION_TYPE'] = 'filesystem' +login = LoginManager(app) +Session(app) +socketio = SocketIO(app, manage_session=False) + + +class User(UserMixin, object): + def __init__(self, id=None): + self.id = id + + +@login.user_loader +def load_user(id): + return User(id) + + +@app.route('/') +def index(): + return render_template('sessions.html') + + +@app.route('/session', methods=['GET', 'POST']) +def session_access(): + if request.method == 'GET': +~~ return jsonify({ + 'session': session.get('value', ''), + 'user': current_user.id + if current_user.is_authenticated else 'anonymous' + }) + data = request.get_json() + if 'session' in data: + session['value'] = data['session'] + elif 'user' in data: + if data['user']: + login_user(User(data['user'])) + else: + logout_user() + return '', 204 + + +@socketio.on('get-session') +def get_session(): + emit('refresh-session', { + 'session': session.get('value', ''), + 'user': current_user.id + if current_user.is_authenticated else 'anonymous' + }) + + + + +## ... source file continues with no further jsonify examples... + +``` + + +## Example 6 from Datadog Flask Example App +The [Datadog Flask example app](https://github.com/DataDog/trace-examples/tree/master/python/flask) +contains many examples of the [Flask](/flask.html) core functions +available to a developer using the [web framework](/web-frameworks.html). + +[**Datadog Flask Example App / python/flask/app / app.py**](https://github.com/DataDog/trace-examples/blob/master/python/flask/app/./app.py) + +```python +# app.py +from ddtrace import patch_all; patch_all(flask=True, requests=True) # noqa + +from ddtrace import tracer + +from flask import Flask, Response +from flask import after_this_request +~~from flask import abort, jsonify, render_template, url_for +from flask.views import View +from werkzeug.routing import Rule + +from flask_caching import Cache +from flask_cors import CORS + +import requests + +from .blueprint import bp +from .exceptions import AppException +from .limiter import limiter +from .signals import connect_signals + +app = Flask(__name__) + +app.register_blueprint(bp) + +connect_signals(app) + +CORS(app) +Cache(app, config=dict(CACHE_TYPE='simple')) +limiter.init_app(app) + + + + +## ... source file abbreviated to get to jsonify examples ... + + + 'Endpoint to fetch a simple .txt static file.', + ], + links=[ + dict(label='GET /static/test.txt', url=url_for('static', filename='test.txt')), + ], + ), + ] + return render_template('index.jinja2', routes=routes) + + +@app.route('/joke') +def joke(): + res = requests.get('https://icanhazdadjoke.com/', headers=dict(Accept='text/plain')) + res.raise_for_status() + + @after_this_request + def after_joke(response): + print('Hook: after_this_request') + return response + + return res.content + + +@app.route('/json') +def json(): +~~ return jsonify(hello='world') + + +app.url_map.add(Rule('/custom-endpoint/', endpoint='custom-endpoint', defaults=dict(msg='Hello'))) +app.url_map.add(Rule('/custom-endpoint/', endpoint='custom-endpoint')) + +@app.endpoint('custom-endpoint') +@tracer.wrap('my-custom-endpoint') +def custom_endpoint(msg): + with tracer.trace('my-custom-endpoint.respond'): + return msg + + +@app.route('/custom-error') +def custom_error(): + raise AppException('custom app exception') + + +@app.route('/stream') +def stream(): + def generate(): + for i in range(100): + yield '{}\n'.format(i) + + return Response(generate(), mimetype='text/plain') + + +## ... source file continues with no further jsonify examples... + +``` + + +## Example 7 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / web / util.py**](https://github.com/indico/indico/blob/master/indico/web/util.py) + +```python +# util.py + +import hashlib +import sys +from datetime import datetime + +import sentry_sdk +from authlib.oauth2 import OAuth2Error +~~from flask import flash, g, has_request_context, jsonify, render_template, request, session +from itsdangerous import Signer +from markupsafe import Markup +from werkzeug.exceptions import BadRequest, Forbidden, ImATeapot +from werkzeug.urls import url_decode, url_encode, url_parse, url_unparse + +from indico.util.caching import memoize_request +from indico.util.i18n import _ +from indico.web.flask.templating import get_template_module + + +def inject_js(js): + if 'injected_js' not in g: + g.injected_js = [] + g.injected_js.append(Markup(js)) + + +def _pop_injected_js(): + js = None + if 'injected_js' in g: + js = g.injected_js + del g.injected_js + return js + + +def jsonify_form(form, fields=None, submit=None, back=None, back_url=None, back_button=True, disabled_until_change=True, + disabled_fields=(), form_header_kwargs=None, skip_labels=False, save_reminder=False, + footer_align_right=False, disable_if_locked=True, message=None): + if submit is None: + submit = _('Save') + if back is None: + back = _('Cancel') + if form_header_kwargs is None: + form_header_kwargs = {} + tpl = get_template_module('forms/_form.html') + html = tpl.simple_form(form, fields=fields, submit=submit, back=back, back_url=back_url, back_button=back_button, + disabled_until_change=disabled_until_change, disabled_fields=disabled_fields, + form_header_kwargs=form_header_kwargs, skip_labels=skip_labels, save_reminder=save_reminder, + footer_align_right=footer_align_right, disable_if_locked=disable_if_locked, message=message) +~~ return jsonify(html=html, js=_pop_injected_js()) + + +def jsonify_template(template, _render_func=render_template, _success=None, **context): + html = _render_func(template, **context) + jsonify_kw = {} + if _success is not None: + jsonify_kw['success'] = _success +~~ return jsonify(html=html, js=_pop_injected_js(), **jsonify_kw) + + +def jsonify_data(flash=True, **json_data): + json_data.setdefault('success', True) + if flash: + json_data['flashed_messages'] = render_template('flashed_messages.html') +~~ return jsonify(**json_data) + + +class ExpectedError(ImATeapot): + def __init__(self, message, **data): + super().__init__(message or 'Something went wrong') + self.data = dict(data, message=message) + + +def _format_request_data(data, hide_passwords=False): + if not hasattr(data, 'lists'): + data = ((k, [v]) for k, v in data.items()) + else: + data = data.lists() + rv = {} + for key, values in data: + if hide_passwords and 'password' in key: + values = [v if not v else f'<{len(v)} chars hidden>' for v in values] + rv[key] = values if len(values) != 1 else values[0] + return rv + + +def get_request_info(hide_passwords=True): + if not has_request_context(): + return None + + +## ... source file continues with no further jsonify examples... + +``` + + +## Example 8 from keras-flask-deploy-webapp +The +[keras-flask-deploy-webapp](https://github.com/mtobeiyf/keras-flask-deploy-webapp) +project combines the [Flask](/flask.html) [web framework](/web-frameworks.html) +with the [Keras deep learning library](https://keras.io/) to provide +an example image classifier that is easy to [deploy](/deployment.html). +The application can be quckly run in a [Docker](/docker.html) container +on your local development environment. The project is licensed under the +[GNU General Public License v3.0](https://github.com/mtobeiyf/keras-flask-deploy-webapp/blob/master/LICENSE). + +[**keras-flask-deploy-webapp / app.py**](https://github.com/mtobeiyf/keras-flask-deploy-webapp/blob/master/././app.py) + +```python +# app.py +import os +import sys + +~~from flask import Flask, redirect, url_for, request, render_template, Response, jsonify, redirect +from werkzeug.utils import secure_filename +from gevent.pywsgi import WSGIServer + +import tensorflow as tf +from tensorflow import keras + +from tensorflow.keras.applications.imagenet_utils import preprocess_input, decode_predictions +from tensorflow.keras.models import load_model +from tensorflow.keras.preprocessing import image + +import numpy as np +from util import base64_to_pil + + +app = Flask(__name__) + + + +from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2 +model = MobileNetV2(weights='imagenet') + +print('Model loaded. Check http://127.0.0.1:5000/') + + + + +## ... source file abbreviated to get to jsonify examples ... + + + x = preprocess_input(x, mode='tf') + + preds = model.predict(x) + return preds + + +@app.route('/', methods=['GET']) +def index(): + return render_template('index.html') + + +@app.route('/predict', methods=['GET', 'POST']) +def predict(): + if request.method == 'POST': + img = base64_to_pil(request.json) + + + preds = model_predict(img, model) + + pred_proba = "{:.3f}".format(np.amax(preds)) # Max probability + pred_class = decode_predictions(preds, top=1) # ImageNet Decode + + result = str(pred_class[0][0][1]) # Convert to string + result = result.replace('_', ' ').capitalize() + +~~ return jsonify(result=result, probability=pred_proba) + + return None + + +if __name__ == '__main__': + + http_server = WSGIServer(('0.0.0.0', 5000), app) + http_server.serve_forever() + + + +## ... source file continues with no further jsonify examples... + +``` + + +## Example 9 from sandman2 +[sandman2](https://github.com/jeffknupp/sandman2) +([project documentation](https://sandman2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/sandman2/)) +is a code library for automatically generating +[RESTful APIs](/application-programming-interfaces.html) from +existing database schemas. This approach is handy for solving +straightforward situations where you want to put an abstraction +layer between one or more applications and your +[relational database](/databases.html) to prevent or reduce +direct database access. + +The sandman2 project is provided under the +[Apache License 2.0](https://github.com/jeffknupp/sandman2/blob/master/LICENSE). + +[**sandman2 / sandman2 / service.py**](https://github.com/jeffknupp/sandman2/blob/master/sandman2/./service.py) + +```python +# service.py + +from flask import request, make_response +~~import flask +from flask.views import MethodView +from sqlalchemy import asc, desc + +from sandman2.exception import NotFoundException, BadRequestException +from sandman2.model import db +from sandman2.decorators import etag, validate_fields + + +def add_link_headers(response, links): + link_string = '<{}>; rel=self'.format(links['self']) + for link in links.values(): + link_string += ', <{}>; rel=related'.format(link) + response.headers['Link'] = link_string + return response + + +def jsonify(resource): + +~~ response = flask.jsonify(resource.to_dict()) + response = add_link_headers(response, resource.links()) + return response + + +def is_valid_method(model, resource=None): + validation_function_name = 'is_valid_{}'.format( + request.method.lower()) + if hasattr(model, validation_function_name): + return getattr(model, validation_function_name)(request, resource) + +class Service(MethodView): + + + __model__ = None + + __json_collection_name__ = 'resources' + + def delete(self, resource_id): + resource = self._resource(resource_id) + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + db.session().delete(resource) + db.session().commit() + return self._no_content_response() + + @etag + def get(self, resource_id=None): + if request.path.endswith('meta'): + return self._meta() + + if resource_id is None: + error_message = is_valid_method(self.__model__) + if error_message: + raise BadRequestException(error_message) + + if 'export' in request.args: + return self._export(self._all_resources()) + +~~ return flask.jsonify({ + self.__json_collection_name__: self._all_resources() + }) + else: + resource = self._resource(resource_id) + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + return jsonify(resource) + + def patch(self, resource_id): + resource = self._resource(resource_id) + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + if not request.json: + raise BadRequestException('No JSON data received') + resource.update(request.json) + db.session().merge(resource) + db.session().commit() + return jsonify(resource) + + @validate_fields + def post(self): + resource = self.__model__.query.filter_by(**request.json).first() + + +## ... source file abbreviated to get to jsonify examples ... + + + raise BadRequestException(error_message) + db.session().add(resource) + db.session().commit() + return self._created_response(resource) + + def put(self, resource_id): + resource = self.__model__.query.get(resource_id) + if resource: + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + resource.update(request.json) + db.session().merge(resource) + db.session().commit() + return jsonify(resource) + + resource = self.__model__(**request.json) # pylint: disable=not-callable + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + db.session().add(resource) + db.session().commit() + return self._created_response(resource) + + def _meta(self): +~~ return flask.jsonify(self.__model__.description()) + + def _resource(self, resource_id): + resource = self.__model__.query.get(resource_id) + if not resource: + raise NotFoundException() + return resource + + def _all_resources(self): + queryset = self.__model__.query + args = {k: v for (k, v) in request.args.items() if k not in ('page', 'export')} + limit = None + if args: + filters = [] + order = [] + for key, value in args.items(): + if value.startswith('%'): + filters.append(getattr(self.__model__, key).like(str(value), escape='/')) + elif key == 'sort': + direction = desc if value.startswith('-') else asc + order.append(direction(getattr(self.__model__, value.lstrip('-')))) + elif key == 'limit': + limit = int(value) + elif hasattr(self.__model__, key): + filters.append(getattr(self.__model__, key) == value) + + +## ... source file continues with no further jsonify examples... + +``` + + +## Example 10 from tedivms-flask +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + +[**tedivms-flask / app / views / apis.py**](https://github.com/tedivm/tedivms-flask/blob/master/app/views/apis.py) + +```python +# apis.py + +from flask import Blueprint, redirect +~~from flask import request, url_for, jsonify, current_app + +from app import db +from app.models import user_models +from app.utils.api import roles_accepted_api +from app.extensions.ldap import authenticate + +import uuid + +api_blueprint = Blueprint('api', __name__, template_folder='templates') + +@api_blueprint.route('/api/credentials', methods=['POST']) +def api_create_credentials(): + username = request.form['username'] + password = request.form['password'] + label = request.form.get('label', None) + user = user_models.User.query.filter(user_models.User.email == username).first() + if not user: + user = user_models.User.query.filter(user_models.User.username == username).first() + if not user: + abort(400) + + if current_app.config.get('USER_LDAP', False): + if not authenticate(username, password): + abort(401) + else: + if not current_app.user_manager.verify_password(password, user.password): + abort(401) + + id = uuid.uuid4().hex[0:12] + key = uuid.uuid4().hex + hash = current_app.user_manager.hash_password(key) + new_key = user_models.ApiKey(id=id, hash=hash, user_id=user.id, label=label) + db.session.add(new_key) + db.session.commit() + +~~ return jsonify({'id': id,'key': key}) + + + +## ... source file continues with no further jsonify examples... + +``` + diff --git a/content/pages/examples/flask/flask-sessions-badsignature.markdown b/content/pages/examples/flask/flask-sessions-badsignature.markdown new file mode 100644 index 000000000..afe01dee0 --- /dev/null +++ b/content/pages/examples/flask/flask-sessions-badsignature.markdown @@ -0,0 +1,418 @@ +title: flask.sessions BadSignature Example Code +category: page +slug: flask-sessions-badsignature-examples +sortorder: 500021026 +toc: False +sidebartitle: flask.sessions BadSignature +meta: Example code for understanding how to use the BadSignature class from the flask.sessions module of the Flask project. + + +[BadSignature](https://github.com/pallets/flask/blob/master/src/flask/sessions.py) +is a class often imported into [Flask](/flask.html) applications from +the `flask.sessions` module. `BadSignature` is actually defined in the +[itsdangerous](https://github.com/pallets/itsdangerous) project and +imported into Flask sessions for applications to use. + +SessionInterface +and +SessionMixin +are a couple of other callables within the `flask.sessions` package that also have code examples. + +## Example 1 from flask-base +[flask-base](https://github.com/hack4impact/flask-base) +([project documentation](http://hack4impact.github.io/flask-base/)) +provides boilerplate code for new [Flask](/flask.html) web apps. +The purpose of the boilerplate is to stitch together disparate +libraries that are commonly used in Flask projects, such as +[Redis](/redis.html) for fast caching and transient data storage, +[SendGrid](https://www.twilio.com/sendgrid) for transactional email, +[SQLAlchemy](/sqlalchemy.html) for persistent data storage through a +[relational database](/databases.html) backend, +[Flask-WTF](https://flask-wtf.readthedocs.io/) for form +handling and many others. + +flask-base is provided as open source under the +[MIT license](https://github.com/hack4impact/flask-base/blob/master/LICENSE.md). + +[**flask-base / app / models / user.py**](https://github.com/hack4impact/flask-base/blob/master/app/models/user.py) + +```python +# user.py +from flask import current_app +from flask_login import AnonymousUserMixin, UserMixin +from itsdangerous import TimedJSONWebSignatureSerializer as Serializer +~~from itsdangerous import BadSignature, SignatureExpired +from werkzeug.security import check_password_hash, generate_password_hash + +from .. import db, login_manager + + +class Permission: + GENERAL = 0x01 + ADMINISTER = 0xff + + +class Role(db.Model): + __tablename__ = 'roles' + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(64), unique=True) + index = db.Column(db.String(64)) + default = db.Column(db.Boolean, default=False, index=True) + permissions = db.Column(db.Integer) + users = db.relationship('User', backref='role', lazy='dynamic') + + @staticmethod + def insert_roles(): + roles = { + 'User': (Permission.GENERAL, 'main', True), + 'Administrator': ( + + +## ... source file abbreviated to get to BadSignature examples ... + + + + @password.setter + def password(self, password): + self.password_hash = generate_password_hash(password) + + def verify_password(self, password): + return check_password_hash(self.password_hash, password) + + def generate_confirmation_token(self, expiration=604800): + + s = Serializer(current_app.config['SECRET_KEY'], expiration) + return s.dumps({'confirm': self.id}) + + def generate_email_change_token(self, new_email, expiration=3600): + s = Serializer(current_app.config['SECRET_KEY'], expiration) + return s.dumps({'change_email': self.id, 'new_email': new_email}) + + def generate_password_reset_token(self, expiration=3600): + s = Serializer(current_app.config['SECRET_KEY'], expiration) + return s.dumps({'reset': self.id}) + + def confirm_account(self, token): + s = Serializer(current_app.config['SECRET_KEY']) + try: + data = s.loads(token) +~~ except (BadSignature, SignatureExpired): + return False + if data.get('confirm') != self.id: + return False + self.confirmed = True + db.session.add(self) + db.session.commit() + return True + + def change_email(self, token): + s = Serializer(current_app.config['SECRET_KEY']) + try: + data = s.loads(token) +~~ except (BadSignature, SignatureExpired): + return False + if data.get('change_email') != self.id: + return False + new_email = data.get('new_email') + if new_email is None: + return False + if self.query.filter_by(email=new_email).first() is not None: + return False + self.email = new_email + db.session.add(self) + db.session.commit() + return True + + def reset_password(self, token, new_password): + s = Serializer(current_app.config['SECRET_KEY']) + try: + data = s.loads(token) +~~ except (BadSignature, SignatureExpired): + return False + if data.get('reset') != self.id: + return False + self.password = new_password + db.session.add(self) + db.session.commit() + return True + + @staticmethod + def generate_fake(count=100, **kwargs): + from sqlalchemy.exc import IntegrityError + from random import seed, choice + from faker import Faker + + fake = Faker() + roles = Role.query.all() + + seed() + for i in range(count): + u = User( + first_name=fake.first_name(), + last_name=fake.last_name(), + email=fake.email(), + password='password', + + +## ... source file continues with no further BadSignature examples... + +``` + + +## Example 2 from flask-bones +[flask-bones](https://github.com/cburmeister/flask-bones) +([demo](http://flask-bones.herokuapp.com/)) +is large scale [Flask](/flask.html) example application built +with [Blueprints](https://flask.palletsprojects.com/en/1.1.x/blueprints/) +([example Blueprint code](/flask-blueprints-blueprint-examples.html)). +This project is provided as open source under the +[MIT license](https://github.com/cburmeister/flask-bones/blob/master/LICENSE). + +[**flask-bones / app / auth / views.py**](https://github.com/cburmeister/flask-bones/blob/master/app/auth/views.py) + +```python +# views.py +from flask import ( + current_app, request, redirect, url_for, render_template, flash, abort, +) +from flask_babel import gettext +from flask_login import login_user, login_required, logout_user +~~from itsdangerous import URLSafeSerializer, BadSignature +from app.extensions import lm +from app.jobs import send_registration_email +from app.user.models import User +from app.user.forms import RegisterUserForm +from .forms import LoginForm +from ..auth import auth + + +@lm.user_loader +def load_user(id): + return User.get_by_id(int(id)) + + +@auth.route('/login', methods=['GET', 'POST']) +def login(): + form = LoginForm() + if form.validate_on_submit(): + login_user(form.user) + flash( + gettext( + 'You were logged in as {username}'.format( + username=form.user.username + ), + ), + + +## ... source file abbreviated to get to BadSignature examples ... + + + remote_addr=request.remote_addr, + ) + + s = URLSafeSerializer(current_app.secret_key) + token = s.dumps(user.id) + + send_registration_email.queue(user.id, token) + + flash( + gettext( + 'Sent verification email to {email}'.format( + email=user.email + ) + ), + 'success' + ) + return redirect(url_for('index')) + return render_template('register.html', form=form) + + +@auth.route('/verify/', methods=['GET']) +def verify(token): + s = URLSafeSerializer(current_app.secret_key) + try: + id = s.loads(token) +~~ except BadSignature: + abort(404) + + user = User.query.filter_by(id=id).first_or_404() + if user.active: + abort(404) + else: + user.active = True + user.update() + + flash( + gettext( + 'Registered user {username}. Please login to continue.'.format( + username=user.username + ), + ), + 'success' + ) + return redirect(url_for('auth.login')) + + + +## ... source file continues with no further BadSignature examples... + +``` + + +## Example 3 from Flask-Security-Too +[Flask-Security-Too](https://github.com/Flask-Middleware/flask-security/) +([PyPi page](https://pypi.org/project/Flask-Security-Too/) and +[project documentation](https://flask-security-too.readthedocs.io/en/stable/)) +is a maintained fork of the original +[Flask-Security](https://github.com/mattupstate/flask-security) project that +makes it easier to add common security features to [Flask](/flask.html) +web applications. A few of the critical goals of the Flask-Security-Too +project are ensuring JavaScript client-based single-page applications (SPAs) +can work securely with Flask-based backends and that guidance by the +[OWASP](https://owasp.org/) organization is followed by default. + +The Flask-Security-Too project is provided as open source under the +[MIT license](https://github.com/Flask-Middleware/flask-security/blob/master/LICENSE). + +[**Flask-Security-Too / flask_security / utils.py**](https://github.com/Flask-Middleware/flask-security/blob/master/flask_security/./utils.py) + +```python +# utils.py +import typing as t +import warnings +from urllib.parse import parse_qsl, parse_qs, urlsplit, urlunsplit, urlencode +import urllib.request +import urllib.error + +from flask import ( + _request_ctx_stack, + after_this_request, + current_app, + flash, + g, + request, + render_template, + session, + url_for, +) +from flask.json import JSONEncoder +from flask_login import login_user as _login_user +from flask_login import logout_user as _logout_user +from flask_login import current_user +from flask_login import COOKIE_NAME as REMEMBER_COOKIE_NAME +from flask_principal import AnonymousIdentity, Identity, identity_changed, Need +from flask_wtf import csrf +from wtforms import ValidationError +~~from itsdangerous import BadSignature, SignatureExpired +from werkzeug import __version__ as werkzeug_version +from werkzeug.local import LocalProxy +from werkzeug.datastructures import MultiDict + +from .quart_compat import best, get_quart_status +from .proxies import _security, _datastore, _pwd_context, _hashing_context +from .signals import user_authenticated + +if t.TYPE_CHECKING: # pragma: no cover + from flask import Flask, Response + from .datastore import User + +SB = t.Union[str, bytes] + + +localize_callback = LocalProxy(lambda: _security.i18n_domain.gettext) + +FsPermNeed = partial(Need, "fsperm") +FsPermNeed.__doc__ = """A need with the method preset to `"fsperm"`.""" + + +def _(translate): + return translate + + + +## ... source file abbreviated to get to BadSignature examples ... + + + sender = _security.email_sender + if isinstance(sender, LocalProxy): + sender = sender._get_current_object() + + if isinstance(sender, tuple) and len(sender) == 2: + sender = (str(sender[0]), str(sender[1])) + else: + sender = str(sender) + + _security._mail_util.send_mail( + template, subject, recipient, sender, body, html, context.get("user", None) + ) + + +def get_token_status(token, serializer, max_age=None, return_data=False): + serializer = getattr(_security, serializer + "_serializer") + max_age = get_max_age(max_age) + user, data = None, None + expired, invalid = False, False + + try: + data = serializer.loads(token, max_age=max_age) + except SignatureExpired: + d, data = serializer.loads_unsafe(token) + expired = True +~~ except (BadSignature, TypeError, ValueError): + invalid = True + + if data: + user = _datastore.find_user(fs_uniquifier=data[0]) + + expired = expired and (user is not None) + + if return_data: + return expired, invalid, user, data + else: + return expired, invalid, user + + +def check_and_get_token_status( + token: str, serializer_name: str, within: datetime.timedelta +) -> t.Tuple[bool, bool, t.Any]: + serializer = getattr(_security, serializer_name + "_serializer") + max_age = within.total_seconds() + data = None + expired, invalid = False, False + + try: + data = serializer.loads(token, max_age=max_age) + except SignatureExpired: + d, data = serializer.loads_unsafe(token) + expired = True +~~ except (BadSignature, TypeError, ValueError): + invalid = True + + return expired, invalid, data + + +def get_identity_attributes(app: t.Optional["Flask"] = None) -> t.List[str]: + app = app or current_app + iattrs = app.config["SECURITY_USER_IDENTITY_ATTRIBUTES"] + if iattrs: + return [[*f][0] for f in iattrs] + return [] + + +def get_identity_attribute( + attr: str, app: t.Optional["Flask"] = None +) -> t.Dict[str, t.Any]: + app = app or current_app + iattrs = app.config["SECURITY_USER_IDENTITY_ATTRIBUTES"] + if iattrs: + details = [ + mapping[attr] for mapping in iattrs if list(mapping.keys())[0] == attr + ] + if details: + return details[0] + + +## ... source file continues with no further BadSignature examples... + +``` + diff --git a/content/pages/examples/flask/flask-sessions-sessioninterface.markdown b/content/pages/examples/flask/flask-sessions-sessioninterface.markdown new file mode 100644 index 000000000..ad230c936 --- /dev/null +++ b/content/pages/examples/flask/flask-sessions-sessioninterface.markdown @@ -0,0 +1,132 @@ +title: flask.sessions SessionInterface Example Code +category: page +slug: flask-sessions-sessioninterface-examples +sortorder: 500021027 +toc: False +sidebartitle: flask.sessions SessionInterface +meta: Example code for understanding how to use the SessionInterface class from the flask.sessions module of the Flask project. + + +[SessionInterface](https://github.com/pallets/flask/blob/master/src/flask/sessions.py) +is a class used with [Flask](/flask.html) projects that is defined in +the `flask.sessions` module. `SessionInterface` is the basic interface +that must be implemented to replace the default session interface. + +BadSignature +and +SessionMixin +are a couple of other callables within the `flask.sessions` package that also have code examples. + +## Example 1 from tedivms-flask +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + +[**tedivms-flask / app / __init__.py**](https://github.com/tedivm/tedivms-flask/blob/master/app/./__init__.py) + +```python +# __init__.py +import boto3 +from celery import Celery +from datetime import datetime +import os +import requests +import yaml + +from flask import Flask, render_template +from flask import session as current_session +from flask_mail import Mail +from flask_migrate import Migrate, MigrateCommand +~~from flask.sessions import SessionInterface +from flask_sqlalchemy import SQLAlchemy +from flask_user import user_logged_out +from flask_wtf.csrf import CSRFProtect + +from beaker.cache import CacheManager +from beaker.util import parse_cache_config_options +from beaker.middleware import SessionMiddleware + +db = SQLAlchemy() +csrf_protect = CSRFProtect() +mail = Mail() +migrate = Migrate() + + +def get_config(): + app = Flask(__name__) + + app.config.from_object('app.settings') + if 'APPLICATION_SETTINGS' in os.environ: + app.config.from_envvar(os.environ['APPLICATION_SETTINGS']) + if 'AWS_SECRETS_MANAGER_CONFIG' in os.environ: + secret_config = get_secrets(os.environ['AWS_SECRETS_MANAGER_CONFIG']) + app.config.update(secret_config) + elif 'AWS_SECRETS_MANAGER_CONFIG' in app.config: + + +## ... source file abbreviated to get to SessionInterface examples ... + + + cache = CacheManager(**parse_cache_config_options(cache_opts)) + + +def init_session_manager(app): + session_opts = {'cache.expire': 3600} + + if 'CACHE_TYPE' not in app.config or not app.config['CACHE_TYPE']: + app.config['CACHE_TYPE'] = 'file' + + if app.config['CACHE_TYPE'] == 'file': + if 'CACHE_ROOT' not in app.config or not app.config['CACHE_ROOT']: + app.config['CACHE_ROOT'] = '/tmp/%s' % __name__ + + session_opts['session.type'] = app.config['CACHE_TYPE'] + + if 'CACHE_ROOT' in app.config and app.config['CACHE_ROOT']: + session_opts['session.data_dir'] = app.config['CACHE_ROOT'] + '/session' + + if 'CACHE_URL' in app.config and app.config['CACHE_URL']: + session_opts['session.url'] = app.config['CACHE_URL'] + + session_opts['session.auto'] = app.config.get('SESSION_AUTO', True) + session_opts['session.cookie_expires'] = app.config.get('SESSION_COOKIE_EXPIRES', 86400) + session_opts['session.secret'] = app.secret_key + +~~ class BeakerSessionInterface(SessionInterface): + def open_session(self, app, request): + session = request.environ['beaker.session'] + return session + + def save_session(self, app, session, response): + session.save() + + app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts) + app.session_interface = BeakerSessionInterface() + + @user_logged_out.connect_via(app) + def clear_session(sender, user, **extra): + current_session.clear() + + +def init_celery_service(app): + celery.conf.update(app.config) + + +def init_error_handlers(app): + + def show_error(status, message='An unknown error has occured.'): + return render_template('pages/errors.html', error_code=status, message=message), status + + + +## ... source file continues with no further SessionInterface examples... + +``` + diff --git a/content/pages/examples/flask/flask-sessions-sessionmixin.markdown b/content/pages/examples/flask/flask-sessions-sessionmixin.markdown new file mode 100644 index 000000000..87a1b97b1 --- /dev/null +++ b/content/pages/examples/flask/flask-sessions-sessionmixin.markdown @@ -0,0 +1,113 @@ +title: flask.sessions SessionMixin Example Code +category: page +slug: flask-sessions-sessionmixin-examples +sortorder: 500021028 +toc: False +sidebartitle: flask.sessions SessionMixin +meta: Example code for understanding how to use the SessionMixin class from the flask.sessions module of the Flask project. + + +[SessionMixin](https://github.com/pallets/flask/blob/master/src/flask/sessions.py) +is a class used with [Flask](/flask.html) projects that is defined in +the `flask.sessions` module. `SessionMixin` expands a standard +[Python dictionary](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) +with [session](https://flask.palletsprojects.com/en/1.1.x/quickstart/#sessions) +attributes. + +BadSignature +and +SessionInterface +are a couple of other callables within the `flask.sessions` package that also have code examples. + +## Example 1 from Flask-SocketIO +[Flask-SocketIO](https://github.com/miguelgrinberg/Flask-SocketIO) +([PyPI package information](https://pypi.org/project/Flask-SocketIO/), +[official tutorial](https://blog.miguelgrinberg.com/post/easy-websockets-with-flask-and-gevent) +and +[project documentation](https://flask-socketio.readthedocs.io/en/latest/)) +is a code library by [Miguel Grinberg](https://blog.miguelgrinberg.com/index) +that provides Socket.IO integration for [Flask](/flask.html) applications. +This extension makes it easier to add bi-directional communications on the +web via the [WebSockets](/websockets.html) protocol. + +The Flask-SocketIO project is open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/LICENSE). + +[**Flask-SocketIO / flask_socketio / __init__.py**](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/./flask_socketio/__init__.py) + +```python +# __init__.py +from functools import wraps +import os +import sys + +gevent_socketio_found = True +try: + from socketio import socketio_manage # noqa: F401 +except ImportError: + gevent_socketio_found = False +if gevent_socketio_found: + print('The gevent-socketio package is incompatible with this version of ' + 'the Flask-SocketIO extension. Please uninstall it, and then ' + 'install the latest version of python-socketio in its place.') + sys.exit(1) + +import flask +from flask import _request_ctx_stack, has_request_context, json as flask_json +~~from flask.sessions import SessionMixin +import socketio +from socketio.exceptions import ConnectionRefusedError # noqa: F401 +from werkzeug.debug import DebuggedApplication +from werkzeug.serving import run_with_reloader + +from .namespace import Namespace +from .test_client import SocketIOTestClient + +__version__ = '5.0.2dev' + + +class _SocketIOMiddleware(socketio.WSGIApp): + def __init__(self, socketio_app, flask_app, socketio_path='socket.io'): + self.flask_app = flask_app + super(_SocketIOMiddleware, self).__init__(socketio_app, + flask_app.wsgi_app, + socketio_path=socketio_path) + + def __call__(self, environ, start_response): + environ = environ.copy() + environ['flask.app'] = self.flask_app + return super(_SocketIOMiddleware, self).__call__(environ, + start_response) + + +~~class _ManagedSession(dict, SessionMixin): + pass + + +class SocketIO(object): + + def __init__(self, app=None, **kwargs): + self.server = None + self.server_options = {} + self.wsgi_server = None + self.handlers = [] + self.namespace_handlers = [] + self.exception_handlers = {} + self.default_exception_handler = None + self.manage_session = True + if app is not None or 'message_queue' in kwargs: + self.init_app(app, **kwargs) + else: + self.server_options.update(kwargs) + + def init_app(self, app, **kwargs): + if app is not None: + if not hasattr(app, 'extensions'): + app.extensions = {} # pragma: no cover + app.extensions['socketio'] = self + + +## ... source file continues with no further SessionMixin examples... + +``` + diff --git a/content/pages/examples/flask/flask-signals-got-request-exception.markdown b/content/pages/examples/flask/flask-signals-got-request-exception.markdown new file mode 100644 index 000000000..dc2a466c4 --- /dev/null +++ b/content/pages/examples/flask/flask-signals-got-request-exception.markdown @@ -0,0 +1,141 @@ +title: flask.signals got_request_exception Example Code +category: page +slug: flask-signals-got-request-exception-examples +sortorder: 500021030 +toc: False +sidebartitle: flask.signals got_request_exception +meta: Python example code that shows how to use the got_request_exception callable from the flask.signals module of the Flask project. + + +[got_request_exception](https://github.com/pallets/flask/blob/master/src/flask/signals.py) +is a signal defined in the [Flask](/flask.html) project's +`flask.signals` module that interrupts the WSGI flow when there is an +issue with the HTTP request. It can also be thrown by your own +view functions if there is an error and you want to raise it via a signal. + +Namespace +is another callable from the `flask.signals` package with code examples. + +## Example 1 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / api.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./api.py) + +```python +# api.py +from __future__ import unicode_literals + +import difflib +import inspect +from itertools import chain +import logging +import operator +import re +import six +import sys +import warnings + +from collections import OrderedDict +from functools import wraps, partial +from types import MethodType + +from flask import url_for, request, current_app +from flask import make_response as original_flask_make_response +try: + from flask.helpers import _endpoint_from_view_func +except ImportError: + from flask.scaffold import _endpoint_from_view_func +~~from flask.signals import got_request_exception + +from jsonschema import RefResolver + +from werkzeug.utils import cached_property +from werkzeug.datastructures import Headers +from werkzeug.exceptions import ( + HTTPException, + MethodNotAllowed, + NotFound, + NotAcceptable, + InternalServerError, +) + +from werkzeug import __version__ as werkzeug_version + +if werkzeug_version.split('.')[0] >= '2': + from werkzeug.wrappers import Response as BaseResponse +else: + from werkzeug.wrappers import BaseResponse + +from . import apidoc +from .mask import ParseError, MaskError +from .namespace import Namespace +from .postman import PostmanCollectionV1 + + +## ... source file abbreviated to get to got_request_exception examples ... + + + and current_app.propagate_exceptions + and not isinstance(e, tuple(self._own_and_child_error_handlers.keys())) + ): + + exc_type, exc_value, tb = sys.exc_info() + if exc_value is e: + raise + else: + raise e + + include_message_in_response = current_app.config.get( + "ERROR_INCLUDE_MESSAGE", True + ) + default_data = {} + + headers = Headers() + + for typecheck, handler in six.iteritems(self._own_and_child_error_handlers): + if isinstance(e, typecheck): + result = handler(e) + default_data, code, headers = unpack( + result, HTTPStatus.INTERNAL_SERVER_ERROR + ) + break + else: +~~ got_request_exception.send(current_app._get_current_object(), exception=e) + + if isinstance(e, HTTPException): + code = HTTPStatus(e.code) + if include_message_in_response: + default_data = {"message": getattr(e, "description", code.phrase)} + headers = e.get_response().headers + elif self._default_error_handler: + result = self._default_error_handler(e) + default_data, code, headers = unpack( + result, HTTPStatus.INTERNAL_SERVER_ERROR + ) + else: + code = HTTPStatus.INTERNAL_SERVER_ERROR + if include_message_in_response: + default_data = { + "message": code.phrase, + } + + if include_message_in_response: + default_data["message"] = default_data.get("message", str(e)) + + data = getattr(e, "data", default_data) + fallback_mediatype = None + + + +## ... source file continues with no further got_request_exception examples... + +``` + diff --git a/content/pages/examples/flask/flask-signals-namespace.markdown b/content/pages/examples/flask/flask-signals-namespace.markdown new file mode 100644 index 000000000..f9987d40e --- /dev/null +++ b/content/pages/examples/flask/flask-signals-namespace.markdown @@ -0,0 +1,211 @@ +title: flask.signals Namespace Example Code +category: page +slug: flask-signals-namespace-examples +sortorder: 500021029 +toc: False +sidebartitle: flask.signals Namespace +meta: Example code for understanding how to use the Namespace class from the flask.signals module of the Flask project. + + +[Namespace](https://github.com/pallets/flask/blob/master/src/flask/signals.py) +is a class used within the `flask.signals` module, but it is +actually imported from the +[Blinker project](https://github.com/jek/blinker). Blinker +is a fast dispatching system for event subscriptions, also known as +"signals". [Flask](/flask.html) uses this library instead of +implementing its own event subscription signaling model. +[Namespace is defined within Blinker](https://github.com/jek/blinker/blob/master/blinker/base.py) +as a mapping of signal names to signals, and it serves the +same purpose in the Flask project. + +got_request_exception +is another callable from the `flask.signals` package with code examples. + +## Example 1 from flask-login +[Flask-Login](https://github.com/maxcountryman/flask-login) +([project documentation](https://flask-login.readthedocs.io/en/latest/) +and [PyPI package](https://pypi.org/project/Flask-Login/)) +is a [Flask](/flask.html) extension that provides user session +management, which handles common tasks such as logging in +and out of a [web application](/web-development.html) and +managing associated user session data. Flask-Login is +open sourced under the +[MIT license](https://github.com/maxcountryman/flask-login/blob/master/LICENSE). + +[**flask-login / flask_login / signals.py**](https://github.com/maxcountryman/flask-login/blob/master/flask_login/./signals.py) + +```python +# signals.py + + +~~from flask.signals import Namespace + + +~~_signals = Namespace() + + +user_logged_in = _signals.signal('logged-in') + +user_logged_out = _signals.signal('logged-out') + +user_loaded_from_cookie = _signals.signal('loaded-from-cookie') + +user_loaded_from_header = _signals.signal('loaded-from-header') + +user_loaded_from_request = _signals.signal('loaded-from-request') + +user_login_confirmed = _signals.signal('login-confirmed') + +user_unauthorized = _signals.signal('unauthorized') + +user_needs_refresh = _signals.signal('needs-refresh') + +user_accessed = _signals.signal('accessed') + +session_protected = _signals.signal('session-protected') + + + +## ... source file continues with no further Namespace examples... + +``` + + +## Example 2 from flask-sqlalchemy +[flask-sqlalchemy](https://github.com/pallets/flask-sqlalchemy) +([project documentation](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) +and +[PyPI information](https://pypi.org/project/Flask-SQLAlchemy/)) is a +[Flask](/flask.html) extension that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) when building Flask apps. flask-sqlalchemy +provides helper functions that reduce the amount of common boilerplate +code that you have to frequently write yourself if you did not use this +library when combining Flask with SQLAlchemy. + +flask-sqlalchemy is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/pallets/flask-sqlalchemy/blob/master/LICENSE.rst). + +[**flask-sqlalchemy / src/flask_sqlalchemy / __init__.py**](https://github.com/pallets/flask-sqlalchemy/blob/master/src/flask_sqlalchemy/./__init__.py) + +```python +# __init__.py +import functools +import os +import sys +import warnings +from math import ceil +from operator import itemgetter +from threading import Lock +from time import perf_counter + +import sqlalchemy +from flask import _app_ctx_stack +from flask import abort +from flask import current_app +from flask import request +~~from flask.signals import Namespace +from sqlalchemy import event +from sqlalchemy import inspect +from sqlalchemy import orm +from sqlalchemy.engine.url import make_url +from sqlalchemy.orm.exc import UnmappedClassError +from sqlalchemy.orm.session import Session as SessionBase + +from .model import DefaultMeta +from .model import Model + +try: + from sqlalchemy.orm import declarative_base + from sqlalchemy.orm import DeclarativeMeta +except ImportError: + from sqlalchemy.ext.declarative import declarative_base + from sqlalchemy.ext.declarative import DeclarativeMeta + +try: + from greenlet import getcurrent as _ident_func +except ImportError: + from threading import get_ident as _ident_func + +__version__ = "3.0.0.dev0" + +~~_signals = Namespace() +models_committed = _signals.signal("models-committed") +before_models_committed = _signals.signal("before-models-committed") + + +def _sa_url_set(url, **kwargs): + try: + url = url.set(**kwargs) + except AttributeError: + for key, value in kwargs.items(): + setattr(url, key, value) + + return url + + +def _sa_url_query_setdefault(url, **kwargs): + query = dict(url.query) + + for key, value in kwargs.items(): + query.setdefault(key, value) + + return _sa_url_set(url, query=query) + + +def _make_table(db): + + +## ... source file continues with no further Namespace examples... + +``` + + +## Example 3 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / signals.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/./signals.py) + +```python +# signals.py + + + +~~from flask.signals import Namespace + +~~_signals = Namespace() # Place Flask-User signals in our own namespace + + +user_changed_password = _signals.signal('user.user_changed_password') + +user_changed_username = _signals.signal('user.user_changed_username') + +user_confirmed_email = _signals.signal('user.user_confirmed_email') + +user_forgot_password = _signals.signal('user.forgot_password') + +user_logged_in = _signals.signal('user.user_logged_in') + +user_logged_out = _signals.signal('user.user_logged_out') + +user_registered = _signals.signal('user.user_registered') + +user_reset_password = _signals.signal('user.user_reset_password') + +user_sent_invitation = _signals.signal('user.user_sent_invitation') + + + + +## ... source file continues with no further Namespace examples... + +``` + diff --git a/content/pages/examples/flask/flask-templating-render-template-string.markdown b/content/pages/examples/flask/flask-templating-render-template-string.markdown new file mode 100644 index 000000000..7f74cb079 --- /dev/null +++ b/content/pages/examples/flask/flask-templating-render-template-string.markdown @@ -0,0 +1,321 @@ +title: flask.templating render_template_string Example Code +category: page +slug: flask-templating-render-template-string-examples +sortorder: 500021032 +toc: False +sidebartitle: flask.templating render_template_string +meta: Python example code that shows how to use the render_template_string callable from the flask.templating module of the Flask project. + + +[render_template_string](https://github.com/pallets/flask/blob/master/src/flask/templating.py) +is a [Flask](/flask.html) function from the `flask.templating` package. +`render_template` is used to generate output from a string +that is passed in rather than from a file in the templates folder. + +Note that `render_template_string` is sometimes imported from the `flask` +package instead of from `flask.templating`. It is the same function that is +imported, but there are less characters to type when you leave off +the `.templating` part. + +render_template +is another callable from the `flask.templating` package with code examples. + +These subjects go along with the `render_template_string` code examples: + +* [template engines](/template-engines.html), specifically [Jinja2](/jinja2.html) +* [Flask](/flask.html) and the concepts for [web frameworks](/web-frameworks.html) +* [Cascading Style Sheets (CSS)](/cascading-style-sheets.html) and [web design](/web-design.html) + + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / tests / test_themes.py**](https://github.com/CTFd/CTFd/blob/master/./tests/test_themes.py) + +```python +# test_themes.py + +import os +import shutil + +import pytest +~~from flask import render_template, render_template_string, request +from jinja2.exceptions import TemplateNotFound +from jinja2.sandbox import SecurityError +from werkzeug.test import Client + +from CTFd.config import TestingConfig +from CTFd.utils import get_config, set_config +from tests.helpers import create_ctfd, destroy_ctfd, gen_user, login_as_user + + +def test_themes_run_in_sandbox(): + app = create_ctfd() + with app.app_context(): + try: + app.jinja_env.from_string( + "{{ ().__class__.__bases__[0].__subclasses__()[40]('./test_utils.py').read() }}" + ).render() + except SecurityError: + pass + except Exception as e: + raise e + destroy_ctfd(app) + + +def test_themes_cant_access_configpy_attributes(): + + +## ... source file abbreviated to get to render_template_string examples ... + + + except TemplateNotFound: + pass + try: + r = client.get("/themes/foo_fallback/static/js/pages/main.dev.js") + except TemplateNotFound: + pass + destroy_ctfd(app) + + app = create_ctfd() + with app.app_context(): + set_config("ctf_theme", "foo_fallback") + assert app.config["THEME_FALLBACK"] == True + with app.test_client() as client: + r = client.get("/") + assert r.status_code == 200 + r = client.get("/themes/foo_fallback/static/js/pages/main.dev.js") + assert r.status_code == 200 + destroy_ctfd(app) + + os.rmdir(os.path.join(app.root_path, "themes", "foo_fallback")) + + +def test_theme_template_loading_by_prefix(): + app = create_ctfd() + with app.test_request_context(): +~~ tpl1 = render_template_string("{% extends 'core/page.html' %}", content="test") + tpl2 = render_template("page.html", content="test") + assert tpl1 == tpl2 + + +def test_theme_template_disallow_loading_admin_templates(): + app = create_ctfd() + with app.app_context(): + try: + filename = os.path.join( + app.root_path, "themes", "foo_disallow", "admin", "malicious.html" + ) + os.makedirs(os.path.dirname(filename), exist_ok=True) + set_config("ctf_theme", "foo_disallow") + with open(filename, "w") as f: + f.write("malicious") + + with pytest.raises(TemplateNotFound): +~~ render_template_string("{% include 'admin/malicious.html' %}") + finally: + shutil.rmtree( + os.path.join(app.root_path, "themes", "foo_disallow"), + ignore_errors=True, + ) + + + +## ... source file continues with no further render_template_string examples... + +``` + + +## Example 2 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / tests / tst_app.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/tests/tst_app.py) + +```python +# tst_app.py +import os +import datetime +~~from flask import Flask, render_template_string, request +from flask_babelex import Babel +from flask_user import login_required, roles_required, UserManager, UserMixin + +ORM_type = 'SQLAlchemy' # SQLAlchemy or MongoEngine + + +app = Flask(__name__) + +class ConfigClass(object): + SECRET_KEY = 'Test with short key' # Less than 32 bytes + + SQLALCHEMY_DATABASE_URI = 'sqlite:///tst_app.sqlite' # File-based SQL database + SQLALCHEMY_TRACK_MODIFICATIONS = False # Avoids SQLAlchemy warning + + MONGODB_SETTINGS = { + 'db': 'tst_app', + 'host': 'mongodb://localhost:27017/tst_app' + } + + MAIL_USERNAME = os.getenv('MAIL_USERNAME', 'email@example.com') + MAIL_PASSWORD = os.getenv('MAIL_PASSWORD', 'password') + MAIL_DEFAULT_SENDER = os.getenv('MAIL_DEFAULT_SENDER', '"TestApp" ') + MAIL_SERVER = os.getenv('MAIL_SERVER', 'smtp.gmail.com') + MAIL_PORT = int(os.getenv('MAIL_PORT', '465')) + + +## ... source file abbreviated to get to render_template_string examples ... + + + assert user_manager.USER_EMAIL_SENDER_EMAIL=='noreply@example.com' + + db_manager = user_manager.db_manager + db_manager.drop_all_tables() + db_manager.create_all_tables() + + token = user_manager.generate_token('abc', 123, 'xyz') + data_items = user_manager.token_manager.verify_token(token, 3600) + assert data_items is not None + assert data_items[0] == 'abc' + assert data_items[1] == 123 + assert data_items[2] == 'xyz' + + user = db_manager.add_user(username='member', email='member@example.com', + password=user_manager.hash_password('Password1'), email_confirmed_at=datetime.datetime.utcnow()) + db_manager.commit() + + user = db_manager.add_user(username='user007', email='admin@example.com', + password=user_manager.hash_password('Password1')) + db_manager.add_user_role(user, 'secret') + db_manager.add_user_role(user, 'agent') + db_manager.commit() + + @app.route('/') + def home_page(): +~~ return render_template_string(""" + {% extends "flask_user_layout.html" %} + {% block content %} +

    {%trans%}Home Page{%endtrans%}

    +

    {%trans%}Sign in{%endtrans%}

    + {% endblock %} + {% extends "flask_user_layout.html" %} + {% block content %} +

    {%trans%}Profile Page{%endtrans%}

    +

    {%trans%}Hello{%endtrans%} + {{ current_user.username or current_user.email }},

    +

    + {%trans%}Change username{%endtrans%}

    +

    + {%trans%}Change password{%endtrans%}

    +

    + {%trans%}Sign out{%endtrans%}

    + {% endblock %} + {% extends "flask_user_layout.html" %} + {% block content %} +

    {%trans%}Admin Page{%endtrans%}

    + {% endblock %} + + + +## ... source file continues with no further render_template_string examples... + +``` + + +## Example 3 from Datadog Flask Example App +The [Datadog Flask example app](https://github.com/DataDog/trace-examples/tree/master/python/flask) +contains many examples of the [Flask](/flask.html) core functions +available to a developer using the [web framework](/web-frameworks.html). + +[**Datadog Flask Example App / python/flask/app / blueprint.py**](https://github.com/DataDog/trace-examples/blob/master/python/flask/app/./blueprint.py) + +```python +# blueprint.py +from ddtrace import Pin +~~from flask import abort, Blueprint, render_template_string + +from .limiter import limiter + + +bp = Blueprint('bp', __name__, url_prefix='/bp/') + +Pin.override(bp, service='flask-bp', app='flask', app_type='web') + + +@bp.before_request +def bp_before_request(): + print('Hook: bp_before_request') + + +@bp.before_app_request +def bp_before_app_request(): + print('Hook: bp_before_app_request') + + +@bp.before_app_first_request +def bp_before_app_first_request(): + print('Hook: bp_before_app_first_request') + + + + +## ... source file abbreviated to get to render_template_string examples ... + + + print('Hook: bp_after_request') + return response + + +@bp.after_app_request +def bp_after_app_request(response): + print('Hook: bp_after_app_request') + return response + + +@bp.teardown_request +def bp_teardown_request(response): + print('Hook: bp_teardown_request') + return response + + +@bp.teardown_app_request +def bp_teardown_app_request(response): + print('Hook: bp_teardown_app_request') + return response + + +@bp.route('/') +@limiter.limit('10 per second') +def index(): +~~ return render_template_string('

    Blueprint

    ') + + +@bp.route('/unknown') +@limiter.exempt +def unknown(): + abort(404) + + +@bp.errorhandler(404) +def bp_not_found(e): + return 'oh no....', 404 + + + +## ... source file continues with no further render_template_string examples... + +``` + diff --git a/content/pages/examples/flask/flask-templating-render-template.markdown b/content/pages/examples/flask/flask-templating-render-template.markdown new file mode 100644 index 000000000..9d320fab4 --- /dev/null +++ b/content/pages/examples/flask/flask-templating-render-template.markdown @@ -0,0 +1,2295 @@ +title: flask.templating render_template Example Code +category: page +slug: flask-templating-render-template-examples +sortorder: 500021031 +toc: False +sidebartitle: flask.templating render_template +meta: Python example code that shows how to use the render_template callable from the flask.templating module of the Flask project. + + +[render_template](https://github.com/pallets/flask/blob/master/src/flask/templating.py) +is a [Flask](/flask.html) function from the `flask.templating` package. +`render_template` is used to generate output from a +[template file based on the Jinja2 engine](/template-engines.html) +that is found in the application's templates folder. + +Note that `render_template` is typically imported directly from the `flask` +package instead of from `flask.templating`. It is the same function that is +imported, but there are less characters to type when you leave off +the `.templating` part. + +render_template_string +is another callable from the `flask.templating` package with code examples. + +These topics are also useful while reading the `render_template` examples: + +* [template engines](/template-engines.html), specifically [Jinja2](/jinja2.html) +* [Flask](/flask.html) and the concepts for [web frameworks](/web-frameworks.html) +* [Cascading Style Sheets (CSS)](/cascading-style-sheets.html) and [web design](/web-design.html) + + +## Example 1 from Braintree Flask app +[Braintree's Flask example payments app](https://github.com/braintree/braintree_flask_example) +demonstrates how to incorporate this payment provider's +[API](/application-programming-interfaces.html) into your +[Flask](/flask.html) [web application](/web-development.html). +The code is open sourced under the +[MIT license](https://github.com/braintree/braintree_flask_example/blob/master/LICENSE). + +[**Braintree Flask app / app.py**](https://github.com/braintree/braintree_flask_example/blob/master/././app.py) + +```python +# app.py +~~from flask import Flask, redirect, url_for, render_template, request, flash + +import os +from os.path import join, dirname +from dotenv import load_dotenv +import braintree +from gateway import generate_client_token, transact, find_transaction + +load_dotenv() + +app = Flask(__name__) +app.secret_key = os.environ.get('APP_SECRET_KEY') + +PORT = int(os.environ.get('PORT', 4567)) + +TRANSACTION_SUCCESS_STATUSES = [ + braintree.Transaction.Status.Authorized, + braintree.Transaction.Status.Authorizing, + braintree.Transaction.Status.Settled, + braintree.Transaction.Status.SettlementConfirmed, + braintree.Transaction.Status.SettlementPending, + braintree.Transaction.Status.Settling, + braintree.Transaction.Status.SubmittedForSettlement +] + +@app.route('/', methods=['GET']) +def index(): + return redirect(url_for('new_checkout')) + +@app.route('/checkouts/new', methods=['GET']) +def new_checkout(): + client_token = generate_client_token() +~~ return render_template('checkouts/new.html', client_token=client_token) + +@app.route('/checkouts/', methods=['GET']) +def show_checkout(transaction_id): + transaction = find_transaction(transaction_id) + result = {} + if transaction.status in TRANSACTION_SUCCESS_STATUSES: + result = { + 'header': 'Sweet Success!', + 'icon': 'success', + 'message': 'Your test transaction has been successfully processed. See the Braintree API response and try again.' + } + else: + result = { + 'header': 'Transaction Failed', + 'icon': 'fail', + 'message': 'Your test transaction has a status of ' + transaction.status + '. See the Braintree API response and try again.' + } + +~~ return render_template('checkouts/show.html', transaction=transaction, result=result) + +@app.route('/checkouts', methods=['POST']) +def create_checkout(): + result = transact({ + 'amount': request.form['amount'], + 'payment_method_nonce': request.form['payment_method_nonce'], + 'options': { + "submit_for_settlement": True + } + }) + + if result.is_success or result.transaction: + return redirect(url_for('show_checkout',transaction_id=result.transaction.id)) + else: + for x in result.errors.deep_errors: flash('Error: %s: %s' % (x.code, x.message)) + return redirect(url_for('new_checkout')) + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=PORT, debug=True) + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 2 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [Flask](/flask.html). The application can be used +as-is to run CTF events, or modified for custom rules for related +scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / tests / test_themes.py**](https://github.com/CTFd/CTFd/blob/master/./tests/test_themes.py) + +```python +# test_themes.py + +import os +import shutil + +import pytest +~~from flask import render_template, render_template_string, request +from jinja2.exceptions import TemplateNotFound +from jinja2.sandbox import SecurityError +from werkzeug.test import Client + +from CTFd.config import TestingConfig +from CTFd.utils import get_config, set_config +from tests.helpers import create_ctfd, destroy_ctfd, gen_user, login_as_user + + +def test_themes_run_in_sandbox(): + app = create_ctfd() + with app.app_context(): + try: + app.jinja_env.from_string( + "{{ ().__class__.__bases__[0].__subclasses__()[40]('./test_utils.py').read() }}" + ).render() + except SecurityError: + pass + except Exception as e: + raise e + destroy_ctfd(app) + + +def test_themes_cant_access_configpy_attributes(): + + +## ... source file abbreviated to get to render_template examples ... + + + pass + try: + r = client.get("/themes/foo_fallback/static/js/pages/main.dev.js") + except TemplateNotFound: + pass + destroy_ctfd(app) + + app = create_ctfd() + with app.app_context(): + set_config("ctf_theme", "foo_fallback") + assert app.config["THEME_FALLBACK"] == True + with app.test_client() as client: + r = client.get("/") + assert r.status_code == 200 + r = client.get("/themes/foo_fallback/static/js/pages/main.dev.js") + assert r.status_code == 200 + destroy_ctfd(app) + + os.rmdir(os.path.join(app.root_path, "themes", "foo_fallback")) + + +def test_theme_template_loading_by_prefix(): + app = create_ctfd() + with app.test_request_context(): + tpl1 = render_template_string("{% extends 'core/page.html' %}", content="test") +~~ tpl2 = render_template("page.html", content="test") + assert tpl1 == tpl2 + + +def test_theme_template_disallow_loading_admin_templates(): + app = create_ctfd() + with app.app_context(): + try: + filename = os.path.join( + app.root_path, "themes", "foo_disallow", "admin", "malicious.html" + ) + os.makedirs(os.path.dirname(filename), exist_ok=True) + set_config("ctf_theme", "foo_disallow") + with open(filename, "w") as f: + f.write("malicious") + + with pytest.raises(TemplateNotFound): + render_template_string("{% include 'admin/malicious.html' %}") + finally: + shutil.rmtree( + os.path.join(app.root_path, "themes", "foo_disallow"), + ignore_errors=True, + ) + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 3 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / email.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/./email.py) + +```python +# email.py +import logging +~~from flask import render_template +from flask_mail import Message +from flask_babelplus import lazy_gettext as _ + +from flaskbb.extensions import mail, celery + + +logger = logging.getLogger(__name__) + + +@celery.task +def send_reset_token(token, username, email): + send_email( + subject=_("Password Recovery Confirmation"), + recipients=[email], +~~ text_body=render_template( + "email/reset_password.txt", + username=username, + token=token + ), +~~ html_body=render_template( + "email/reset_password.html", + username=username, + token=token + ) + ) + + +@celery.task +def send_activation_token(token, username, email): + send_email( + subject=_("Account Activation"), + recipients=[email], +~~ text_body=render_template( + "email/activate_account.txt", + username=username, + token=token + ), +~~ html_body=render_template( + "email/activate_account.html", + username=username, + token=token + ) + ) + + +@celery.task +def send_async_email(*args, **kwargs): + send_email(*args, **kwargs) + + +def send_email(subject, recipients, text_body, html_body, sender=None): + msg = Message(subject, recipients=recipients, sender=sender) + msg.body = text_body + msg.html = html_body + mail.send(msg) + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 4 from flask-base +[flask-base](https://github.com/hack4impact/flask-base) +([project documentation](http://hack4impact.github.io/flask-base/)) +provides boilerplate code for new [Flask](/flask.html) web apps. +The purpose of the boilerplate is to stitch together disparate +libraries that are commonly used in Flask projects, such as +[Redis](/redis.html) for fast caching and transient data storage, +[SendGrid](https://www.twilio.com/sendgrid) for transactional email, +[SQLAlchemy](/sqlalchemy.html) for persistent data storage through a +[relational database](/databases.html) backend, +[Flask-WTF](https://flask-wtf.readthedocs.io/) for form +handling and many others. + +flask-base is provided as open source under the +[MIT license](https://github.com/hack4impact/flask-base/blob/master/LICENSE.md). + +[**flask-base / app / email.py**](https://github.com/hack4impact/flask-base/blob/master/app/./email.py) + +```python +# email.py +import os + +~~from flask import render_template +from flask_mail import Message + +from app import create_app +from app import mail + + +def send_email(recipient, subject, template, **kwargs): + app = create_app(os.getenv('FLASK_CONFIG') or 'default') + with app.app_context(): + msg = Message( + app.config['EMAIL_SUBJECT_PREFIX'] + ' ' + subject, + sender=app.config['EMAIL_SENDER'], + recipients=[recipient]) +~~ msg.body = render_template(template + '.txt', **kwargs) +~~ msg.html = render_template(template + '.html', **kwargs) + mail.send(msg) + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 5 from flask-bones +[flask-bones](https://github.com/cburmeister/flask-bones) +([demo](http://flask-bones.herokuapp.com/)) +is large scale [Flask](/flask.html) example application built +with [Blueprints](https://flask.palletsprojects.com/en/1.1.x/blueprints/) +([example Blueprint code](/flask-blueprints-blueprint-examples.html)). +This project is provided as open source under the +[MIT license](https://github.com/cburmeister/flask-bones/blob/master/LICENSE). + +[**flask-bones / app / __init__.py**](https://github.com/cburmeister/flask-bones/blob/master/app/./__init__.py) + +```python +# __init__.py +import time + +~~from flask import Flask, g, render_template, request +import arrow +import requests + +from app import config +from app.assets import assets +from app.auth import auth +from app.commands import create_db, drop_db, populate_db, recreate_db +from app.database import db +from app.extensions import lm, travis, mail, migrate, bcrypt, babel, rq, limiter +from app.user import user +from app.utils import url_for_other_page + + +def create_app(config=config.base_config): + app = Flask(__name__) + app.config.from_object(config) + + register_extensions(app) + register_blueprints(app) + register_errorhandlers(app) + register_jinja_env(app) + register_commands(app) + + def get_locale(): + return request.accept_languages.best_match(config.SUPPORTED_LOCALES) + + if babel.locale_selector_func is None: + babel.locale_selector_func = get_locale + + @app.before_request + def before_request(): + g.request_start_time = time.time() + g.request_time = lambda: '%.5fs' % (time.time() - g.request_start_time) + g.pjax = 'X-PJAX' in request.headers + + @app.route('/', methods=['GET']) + def index(): +~~ return render_template('index.html') + + return app + + +def register_commands(app): + for command in [create_db, drop_db, populate_db, recreate_db]: + app.cli.command()(command) + + +def register_extensions(app): + travis.init_app(app) + db.init_app(app) + lm.init_app(app) + mail.init_app(app) + bcrypt.init_app(app) + assets.init_app(app) + babel.init_app(app) + rq.init_app(app) + migrate.init_app(app, db) + limiter.init_app(app) + + +def register_blueprints(app): + app.register_blueprint(user, url_prefix='/user') + app.register_blueprint(auth) + + +def register_errorhandlers(app): + + def render_error(e): +~~ return render_template('errors/%s.html' % e.code), e.code + + for e in [ + requests.codes.INTERNAL_SERVER_ERROR, + requests.codes.NOT_FOUND, + requests.codes.UNAUTHORIZED, + ]: + app.errorhandler(e)(render_error) + + +def register_jinja_env(app): + app.jinja_env.globals.update({ + 'timeago': lambda x: arrow.get(x).humanize(), + 'url_for_other_page': url_for_other_page, + }) + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 6 from flask-bookshelf +[flask-bookshelf](https://github.com/damyanbogoev/flask-bookshelf) is the +example [Flask](/flask.html) application that developers create when +going through +[this Flask series of blog posts](https://damyanon.net/tags/flask-series/). + +[**flask-bookshelf / bookshelf / __init__.py**](https://github.com/damyanbogoev/flask-bookshelf/blob/master/bookshelf/./__init__.py) + +```python +# __init__.py +~~from flask import abort, Flask, g, render_template, request, current_app +from flask_babel import Babel +from flask_security import current_user +from bookshelf.utils import get_instance_folder_path +from bookshelf.main.controllers import main +from bookshelf.admin.controllers import admin +from bookshelf.cache import cache +from bookshelf.config import configure_app +from bookshelf.data.models import db + +app = Flask( + __name__, + instance_path=get_instance_folder_path(), + instance_relative_config=True, + template_folder="templates", +) + +babel = Babel(app) +configure_app(app) +cache.init_app(app) +db.init_app(app) +app.jinja_env.add_extension("jinja2.ext.loopcontrols") + + +@app.url_defaults + + +## ... source file abbreviated to get to render_template examples ... + + + + +@app.before_request +def ensure_lang_support(): + lang_code = g.get("lang_code", None) + if lang_code and lang_code not in app.config["SUPPORTED_LANGUAGES"].keys(): + abort(404) + + +@babel.localeselector +def get_locale(): + return g.get("lang_code", app.config["BABEL_DEFAULT_LOCALE"]) + + +@babel.timezoneselector +def get_timezone(): + user = g.get("user", None) + if user is not None: + return user.timezone + return "UTC" + + +@app.errorhandler(404) +def page_not_found(error): + current_app.logger.error("Page not found: %s", (request.path, error)) +~~ return render_template("404.htm"), 404 + + +@app.errorhandler(500) +def internal_server_error(error): + current_app.logger.error("Server Error: %s", (error)) +~~ return render_template("500.htm"), 500 + + +@app.errorhandler(Exception) +def unhandled_exception(error): + current_app.logger.error("Unhandled Exception: %s", (error)) +~~ return render_template("500.htm"), 500 + + +@app.context_processor +def inject_data(): + return dict(user=current_user, lang_code=g.get("lang_code", None)) + + +@app.route("/") +@app.route("//") +@cache.cached(300) +def home(lang_code=None): +~~ return render_template("index.htm") + + +app.register_blueprint(main, url_prefix="/main") +app.register_blueprint(main, url_prefix="//main") +app.register_blueprint(admin, url_prefix="/admin") +app.register_blueprint(admin, url_prefix="//admin") + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 7 from flaskex +[Flaskex](https://github.com/anfederico/Flaskex) is a working example +[Flask](/flask.html) web application intended as a base to build your +own applications upon. The application comes with pre-built sign up, log in +and related screens, as well as a database backend. Flaskex is provided +as open source under the +[MIT license](https://github.com/anfederico/Flaskex/blob/master/LICENSE.txt). + +[**flaskex / app.py**](https://github.com/anfederico/Flaskex/blob/master/././app.py) + +```python +# app.py + +from scripts import tabledef +from scripts import forms +from scripts import helpers +~~from flask import Flask, redirect, url_for, render_template, request, session +import json +import sys +import os + +app = Flask(__name__) +app.secret_key = os.urandom(12) # Generic key for dev purposes only + + +@app.route('/', methods=['GET', 'POST']) +def login(): + if not session.get('logged_in'): + form = forms.LoginForm(request.form) + if request.method == 'POST': + username = request.form['username'].lower() + password = request.form['password'] + if form.validate(): + if helpers.credentials_valid(username, password): + session['logged_in'] = True + session['username'] = username + return json.dumps({'status': 'Login successful'}) + return json.dumps({'status': 'Invalid user/pass'}) + return json.dumps({'status': 'Both fields required'}) +~~ return render_template('login.html', form=form) + user = helpers.get_user() +~~ return render_template('home.html', user=user) + + +@app.route("/logout") +def logout(): + session['logged_in'] = False + return redirect(url_for('login')) + + +@app.route('/signup', methods=['GET', 'POST']) +def signup(): + if not session.get('logged_in'): + form = forms.LoginForm(request.form) + if request.method == 'POST': + username = request.form['username'].lower() + password = helpers.hash_password(request.form['password']) + email = request.form['email'] + if form.validate(): + if not helpers.username_taken(username): + helpers.add_user(username, password, email) + session['logged_in'] = True + session['username'] = username + return json.dumps({'status': 'Signup successful'}) + return json.dumps({'status': 'Username taken'}) + return json.dumps({'status': 'User/Pass required'}) +~~ return render_template('login.html', form=form) + return redirect(url_for('login')) + + +@app.route('/settings', methods=['GET', 'POST']) +def settings(): + if session.get('logged_in'): + if request.method == 'POST': + password = request.form['password'] + if password != "": + password = helpers.hash_password(password) + email = request.form['email'] + helpers.change_user(password=password, email=email) + return json.dumps({'status': 'Saved'}) + user = helpers.get_user() +~~ return render_template('settings.html', user=user) + return redirect(url_for('login')) + + +if __name__ == "__main__": + app.run(debug=True, use_reloader=True, host="0.0.0.0") + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 8 from flask_jsondash +[Flask JSONDash](https://github.com/christabor/flask_jsondash) is a +configurable web application built in Flask that creates charts and +dashboards from arbitrary API endpoints. Everything for the web app +is configured in JSON. The code is provided as open source under the +[MIT license](https://github.com/christabor/flask_jsondash/blob/master/LICENSE). + +[**flask_jsondash / flask_jsondash / charts_builder.py**](https://github.com/christabor/flask_jsondash/blob/master/flask_jsondash/./charts_builder.py) + +```python +# charts_builder.py + + +import json +import os +import uuid +from datetime import datetime as dt + +import jinja2 +~~from flask import (Blueprint, current_app, flash, redirect, render_template, + request, send_from_directory, url_for) + +from flask_jsondash import static, templates + +from flask_jsondash import db +from flask_jsondash import settings +from flask_jsondash.utils import setting +from flask_jsondash.utils import adapter +from flask_jsondash import utils +from flask_jsondash.schema import ( + validate_raw_json, InvalidSchemaError, +) + +TEMPLATE_DIR = os.path.dirname(templates.__file__) +STATIC_DIR = os.path.dirname(static.__file__) + +REQUIRED_STATIC_FAMILES = ['D3'] + +charts = Blueprint( + 'jsondash', + __name__, + template_folder=TEMPLATE_DIR, + static_url_path=STATIC_DIR, + static_folder=STATIC_DIR, + + +## ... source file abbreviated to get to render_template examples ... + + + opts.update( + filter=dict(created_by=setting('JSONDASH_GLOBAL_USER'))) + views += list(adapter.read(**opts)) + else: + views = list(adapter.read(**opts)) + if views: + pagination = utils.paginator(count=len(views), + page=page, per_page=per_page) + opts.update(limit=pagination.limit, skip=pagination.skip) + views = views[pagination.skip:pagination.next] + else: + pagination = None + categorized = utils.categorize_views(views) + kwargs = dict( + total=len(views), + views=categorized, + view=None, + paginator=pagination, + creating=True, + can_edit_global=auth(authtype='edit_global'), + total_modules=sum([ + len(view.get('modules', [])) for view in views + if isinstance(view, dict) + ]), + ) +~~ return render_template('pages/charts_index.html', **kwargs) + + +@charts.route('/charts/', methods=['GET']) +def view(c_id): + if not auth(authtype='view', view_id=c_id): + flash('You do not have access to view this dashboard.', 'error') + return redirect(url_for('jsondash.dashboard')) + viewjson = adapter.read(c_id=c_id) + if not viewjson: + flash('Could not find view: {}'.format(c_id), 'error') + return redirect(url_for('jsondash.dashboard')) + if '_id' in viewjson: + viewjson.pop('_id') + if 'modules' not in viewjson: + flash('Invalid configuration - missing modules.', 'error') + return redirect(url_for('jsondash.dashboard')) + active_charts = [v.get('family') for v in viewjson['modules'] + if v.get('family') is not None] + if metadata(key='username') == viewjson.get('created_by'): + can_edit = True + else: + can_edit = auth(authtype='edit_others', view_id=c_id) + layout_type = viewjson.get('layout', 'freeform') + kwargs = dict( + id=c_id, + view=viewjson, + categories=get_categories(), + num_rows=( + None if layout_type == 'freeform' else utils.get_num_rows(viewjson) + ), + modules=utils.sort_modules(viewjson), + assets=get_active_assets(active_charts), + can_edit=can_edit, + can_edit_global=auth(authtype='edit_global'), + is_global=utils.is_global_dashboard(viewjson), + ) +~~ return render_template('pages/chart_detail.html', **kwargs) + + +@charts.route('/charts//delete', methods=['POST']) +def delete(c_id): + dash_url = url_for('jsondash.dashboard') + if not auth(authtype='delete'): + flash('You do not have access to delete dashboards.', 'error') + return redirect(dash_url) + adapter.delete(c_id) + flash('Deleted dashboard "{}"'.format(c_id)) + return redirect(dash_url) + + +@charts.route('/charts//update', methods=['POST']) +def update(c_id): + if not auth(authtype='update'): + flash('You do not have access to update dashboards.', 'error') + return redirect(url_for('jsondash.dashboard')) + viewjson = adapter.read(c_id=c_id) + if not viewjson: + flash('Could not find view: {}'.format(c_id), 'error') + return redirect(url_for('jsondash.dashboard')) + form_data = request.form + view_url = url_for('jsondash.view', c_id=c_id) + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 9 from flask-phone-input +[flask-phone-input](https://github.com/miguelgrinberg/flask-phone-input) +is an example application that ties together the +[intTellInput.js](https://github.com/jackocnr/intl-tel-input) +JavaScript plugin with the +[Flask-WTF](https://flask-wtf.readthedocs.io/) form-handling +library. flask-phone-input is provided as open source under the +[MIT license](https://github.com/miguelgrinberg/flask-phone-input/blob/1a1c227c044474ce0fe133493d7f8b0fb8312409/LICENSE). + +[**flask-phone-input / app.py**](https://github.com/miguelgrinberg/flask-phone-input/blob/master/././app.py) + +```python +# app.py +~~from flask import Flask, render_template, session, redirect, url_for +from flask_bootstrap import Bootstrap +from flask_wtf import FlaskForm +import phonenumbers +from wtforms import StringField, SubmitField +from wtforms.validators import DataRequired, ValidationError + +app = Flask(__name__) +app.config['SECRET_KEY'] = 'top-secret!' +Bootstrap(app) + + +class PhoneForm(FlaskForm): + phone = StringField('Phone', validators=[DataRequired()]) + submit = SubmitField('Submit') + + def validate_phone(self, phone): + try: + p = phonenumbers.parse(phone.data) + if not phonenumbers.is_valid_number(p): + raise ValueError() + except (phonenumbers.phonenumberutil.NumberParseException, ValueError): + raise ValidationError('Invalid phone number') + + +@app.route('/', methods=['GET', 'POST']) +def index(): + form = PhoneForm() + if form.validate_on_submit(): + session['phone'] = form.phone.data + return redirect(url_for('show_phone')) +~~ return render_template('index.html', form=form) + + +@app.route('/showphone') +def show_phone(): +~~ return render_template('show_phone.html', phone=session['phone']) + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 10 from Flask-Meld +[Flask-Meld](https://github.com/mikeabrahamsen/Flask-Meld) +([PyPI package information](https://pypi.org/project/Flask-Meld/)) +allows you to write your front end web code in your back end +Python code. It does this by adding a `{% meld_scripts %}` tag to +the Flask template engine and then inserting components written +in Python scripts created by a developer. + +[**Flask-Meld / flask_meld / component.py**](https://github.com/mikeabrahamsen/Flask-Meld/blob/main/flask_meld/./component.py) + +```python +# component.py +import os +import uuid +from importlib.util import module_from_spec, spec_from_file_location +from itertools import groupby +from operator import itemgetter + +import orjson +from bs4 import BeautifulSoup +from bs4.element import Tag +from bs4.formatter import HTMLFormatter +~~from flask import current_app, jsonify, render_template +from jinja2.exceptions import TemplateNotFound + + +def convert_to_snake_case(s): + s.replace("-", "_") + return s + + +def convert_to_camel_case(s): + s = convert_to_snake_case(s) + return "".join(word.title() for word in s.split("_")) + + +def get_component_class(component_name): + module_name = convert_to_snake_case(component_name) + class_name = convert_to_camel_case(module_name) + module = get_component_module(module_name) + component_class = getattr(module, class_name) + + return component_class + + +def get_component_module(module_name): + user_specified_dir = current_app.config.get("MELD_COMPONENT_DIR", None) + + +## ... source file abbreviated to get to render_template examples ... + + + for func in dir(self) + if callable(getattr(self, func)) + and not func.startswith("_") + and func not in self._meld_attrs + ] + + for func in function_list: + functions[func] = getattr(self, func) + + return functions + + def __context__(self): + return { + "attributes": self._attributes(), + "methods": self._functions(), + } + + def updated(self, name): + pass + + def render(self, component_name: str): + return self._view(component_name) + + def _render_template(self, template_name: str, context_variables: dict): + try: +~~ return render_template(template_name, **context_variables) + except TemplateNotFound: +~~ return render_template(f"meld/{template_name}", **context_variables) + + def _view(self, component_name: str): + data = self._attributes() + context = self.__context__() + context_variables = {} + context_variables.update(context["attributes"]) + context_variables.update(context["methods"]) + context_variables.update({"form": self._form}) + + rendered_template = self._render_template( + f"{component_name}.html", context_variables + ) + + soup = BeautifulSoup(rendered_template, features="html.parser") + root_element = Component._get_root_element(soup) + root_element["meld:id"] = str(self.id) + self._set_values(root_element, context_variables) + + script = soup.new_tag("script", type="module") + init = {"id": str(self.id), "name": component_name, "data": jsonify(data).json} + init_json = orjson.dumps(init).decode("utf-8") + + meld_import = 'import {Meld} from "/meld_js_src/meld.js";' + script.string = f"{meld_import} Meld.componentInit({init_json});" + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 11 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / apidoc.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./apidoc.py) + +```python +# apidoc.py +from __future__ import unicode_literals + +~~from flask import url_for, Blueprint, render_template + + +class Apidoc(Blueprint): + + def __init__(self, *args, **kwargs): + self.registered = False + super(Apidoc, self).__init__(*args, **kwargs) + + def register(self, *args, **kwargs): + super(Apidoc, self).register(*args, **kwargs) + self.registered = True + + +apidoc = Apidoc( + "restx_doc", + __name__, + template_folder="templates", + static_folder="static", + static_url_path="/swaggerui", +) + + +@apidoc.add_app_template_global +def swagger_static(filename): + return url_for("restx_doc.static", filename=filename) + + +def ui_for(api): +~~ return render_template("swagger-ui.html", title=api.title, specs_url=api.specs_url) + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 12 from flaskSaaS +[flaskSaas](https://github.com/alectrocute/flaskSaaS) is a boilerplate +starter project to build a software-as-a-service (SaaS) web application +in [Flask](/flask.html), with [Stripe](/stripe.html) for billing. The +boilerplate relies on many common Flask extensions such as +[Flask-WTF](https://flask-wtf.readthedocs.io/), +[Flask-Login](https://flask-login.readthedocs.io/en/latest/), +[Flask-Admin](https://flask-admin.readthedocs.io/en/latest/), and +many others. The project is provided as open source under the +[MIT license](https://github.com/alectrocute/flaskSaaS/blob/master/LICENSE). + +[**flaskSaaS / app / views / user.py**](https://github.com/alectrocute/flaskSaaS/blob/master/app/views/user.py) + +```python +# user.py +~~from flask import (Blueprint, render_template, redirect, request, url_for, + abort, flash) +from flask.ext.login import login_user, logout_user, login_required, current_user +from itsdangerous import URLSafeTimedSerializer +from app import app, models, db +from app.forms import user as user_forms +from app.toolbox import email +import stripe +import json +from json import dumps + +stripe_keys = { + 'secret_key': "sk_test_GvpPOs0XFxeP0fQiWMmk6HYe", + 'publishable_key': "pk_test_UU62FhsIB6457uPiUX6mJS5x" +} + +stripe.api_key = stripe_keys['secret_key'] + +ts = URLSafeTimedSerializer(app.config['SECRET_KEY']) + +userbp = Blueprint('userbp', __name__, url_prefix='/user') + + +@userbp.route('/signup', methods=['GET', 'POST']) +def signup(): + form = user_forms.SignUp() + if form.validate_on_submit(): + user = models.User( + first_name=form.first_name.data, + last_name=form.last_name.data, + phone=form.phone.data, + email=form.email.data, + confirmation=False, + password=form.password.data, + ) + db.session.add(user) + db.session.commit() + subject = 'Please confirm your email address.' + token = ts.dumps(user.email, salt='email-confirm-key') + confirmUrl = url_for('userbp.confirm', token=token, _external=True) +~~ html = render_template('email/confirm.html', + confirm_url=confirmUrl) + email.send(user.email, subject, html) + flash('Check your emails to confirm your email address.', 'positive') + return redirect(url_for('index')) +~~ return render_template('user/signup.html', form=form, title='Sign up') + + +@userbp.route('/confirm/', methods=['GET', 'POST']) +def confirm(token): + try: + email = ts.loads(token, salt='email-confirm-key', max_age=86400) + except: + abort(404) + user = models.User.query.filter_by(email=email).first() + user.confirmation = True + db.session.commit() + flash( + 'Your email address has been confirmed, you can sign in.', 'positive') + return redirect(url_for('userbp.signin')) + + +@userbp.route('/signin', methods=['GET', 'POST']) +def signin(): + form = user_forms.Login() + if form.validate_on_submit(): + user = models.User.query.filter_by(email=form.email.data).first() + if user is not None: + if user.check_password(form.password.data): + if user.confirmation == True: + login_user(user) + flash('Succesfully signed in.', 'positive') + return redirect(url_for('userbp.account')) + else: + flash('Confirm your email address first.', 'negative') + return redirect(url_for('userbp.signin')) + else: + flash('The password you have entered is wrong.', 'negative') + return redirect(url_for('userbp.signin')) + else: + flash('Unknown email address.', 'negative') + return redirect(url_for('userbp.signin')) +~~ return render_template('user/signin.html', form=form, title='Sign in') + + +@userbp.route('/signout') +def signout(): + logout_user() + flash('Succesfully signed out.', 'positive') + return redirect(url_for('index')) + + +@userbp.route('/account') +@login_required +def account(): +~~ return render_template('user/account.html', title='Account') + + +@userbp.route('/forgot', methods=['GET', 'POST']) +def forgot(): + form = user_forms.Forgot() + if form.validate_on_submit(): + user = models.User.query.filter_by(email=form.email.data).first() + if user is not None: + subject = 'Reset your password.' + token = ts.dumps(user.email, salt='password-reset-key') + resetUrl = url_for('userbp.reset', token=token, _external=True) +~~ html = render_template('email/reset.html', reset_url=resetUrl) + email.send(user.email, subject, html) + flash('Check your emails to reset your password.', 'positive') + return redirect(url_for('index')) + else: + flash('Unknown email address.', 'negative') + return redirect(url_for('userbp.forgot')) +~~ return render_template('user/forgot.html', form=form) + + +@userbp.route('/reset/', methods=['GET', 'POST']) +def reset(token): + try: + email = ts.loads(token, salt='password-reset-key', max_age=86400) + except: + abort(404) + form = user_forms.Reset() + if form.validate_on_submit(): + user = models.User.query.filter_by(email=email).first() + if user is not None: + user.password = form.password.data + db.session.commit() + flash('Your password has been reset, you can sign in.', 'positive') + return redirect(url_for('userbp.signin')) + else: + flash('Unknown email address.', 'negative') + return redirect(url_for('userbp.forgot')) +~~ return render_template('user/reset.html', form=form, token=token) + +@app.route('/user/pay') +@login_required +def pay(): + user = models.User.query.filter_by(email=current_user.email).first() + if user.paid == 0: +~~ return render_template('user/buy.html', key=stripe_keys['publishable_key'], email=current_user.email) + return "You already paid." + +@app.route('/user/charge', methods=['POST']) +@login_required +def charge(): + amount = 500 + customer = stripe.Customer.create(email=current_user.email, source=request.form['stripeToken']) + charge = stripe.Charge.create( + customer=customer.id, + amount=amount, + currency='usd', + description='Service Plan' + ) + user = models.User.query.filter_by(email=current_user.email).first() + user.paid = 1 + db.session.commit() +~~ return render_template('user/charge.html', amount=amount) + +@app.route('/api/payFail', methods=['POST', 'GET']) +def payFail(): + content = request.json + stripe_email = content['data']['object']['email'] + user = models.User.query.filter_by(email=stripe_email).first() + if user is not None: + user.paid = 0 + db.session.commit() + return "Response: User with associated email " + str(stripe_email) + " updated on our end (payment failure)." + +@app.route('/api/paySuccess', methods=['POST', 'GET']) +def paySuccess(): + content = request.json + stripe_email = content['data']['object']['email'] + user = models.User.query.filter_by(email=stripe_email).first() + if user is not None: + user.paid = 1 + db.session.commit() + return "Response: User with associated email " + str(stripe_email) + " updated on our end (paid)." + + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 13 from Flask-SocketIO +[Flask-SocketIO](https://github.com/miguelgrinberg/Flask-SocketIO) +([PyPI package information](https://pypi.org/project/Flask-SocketIO/), +[official tutorial](https://blog.miguelgrinberg.com/post/easy-websockets-with-flask-and-gevent) +and +[project documentation](https://flask-socketio.readthedocs.io/en/latest/)) +is a code library by [Miguel Grinberg](https://blog.miguelgrinberg.com/index) +that provides Socket.IO integration for [Flask](/flask.html) applications. +This extension makes it easier to add bi-directional communications on the +web via the [WebSockets](/websockets.html) protocol. + +The Flask-SocketIO project is open source under the +[MIT license](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/LICENSE). + +[**Flask-SocketIO / example / sessions.py**](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/./example/sessions.py) + +```python +# sessions.py +~~from flask import Flask, render_template, session, request, jsonify +from flask_login import LoginManager, UserMixin, current_user, login_user, \ + logout_user +from flask_session import Session +from flask_socketio import SocketIO, emit + +app = Flask(__name__) +app.config['SECRET_KEY'] = 'top-secret!' +app.config['SESSION_TYPE'] = 'filesystem' +login = LoginManager(app) +Session(app) +socketio = SocketIO(app, manage_session=False) + + +class User(UserMixin, object): + def __init__(self, id=None): + self.id = id + + +@login.user_loader +def load_user(id): + return User(id) + + +@app.route('/') +def index(): +~~ return render_template('sessions.html') + + +@app.route('/session', methods=['GET', 'POST']) +def session_access(): + if request.method == 'GET': + return jsonify({ + 'session': session.get('value', ''), + 'user': current_user.id + if current_user.is_authenticated else 'anonymous' + }) + data = request.get_json() + if 'session' in data: + session['value'] = data['session'] + elif 'user' in data: + if data['user']: + login_user(User(data['user'])) + else: + logout_user() + return '', 204 + + +@socketio.on('get-session') +def get_session(): + emit('refresh-session', { + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 14 from Flask-User +[Flask-User](https://github.com/lingthio/Flask-User) +([PyPI information](https://pypi.org/project/Flask-User/) +and +[project documentation](https://flask-user.readthedocs.io/en/latest/)) +is a [Flask](/flask.html) extension that makes it easier to add +custom user account management and authentication to the projects +you are building. The extension supports persistent data storage +through both [relational databases](/databases.html) and +[MongoDB](/mongodb.html). The project is provided as open source under +the [MIT license](https://github.com/lingthio/Flask-User/blob/master/LICENSE.txt). + +[**Flask-User / flask_user / email_manager.py**](https://github.com/lingthio/Flask-User/blob/master/flask_user/./email_manager.py) + +```python +# email_manager.py + + +~~from flask import render_template, url_for + +from flask_user import ConfigError + +class EmailManager(object): + + def __init__(self, app): + self.app = app + self.user_manager = app.user_manager + self.sender_name = self.user_manager.USER_EMAIL_SENDER_NAME + self.sender_email = self.user_manager.USER_EMAIL_SENDER_EMAIL + + if not self.sender_email: + raise ConfigError('Config setting USER_EMAIL_SENDER_EMAIL is missing.') + + if '@' not in self.sender_email: + raise ConfigError('Config setting USER_EMAIL_SENDER_EMAIL is not a valid email address.') + + + def send_confirm_email_email(self, user, user_email): + + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_ENABLE_CONFIRM_EMAIL: return + + email = user_email.email if user_email else user.email + + +## ... source file abbreviated to get to render_template examples ... + + + user, + self.user_manager.USER_REGISTERED_EMAIL_TEMPLATE, + confirm_email_link=confirm_email_link, + ) + + def send_username_changed_email(self, user): + + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_SEND_USERNAME_CHANGED_EMAIL: return + + user_or_user_email_object = self.user_manager.db_manager.get_primary_user_email_object(user) + email = user_or_user_email_object.email + + self._render_and_send_email( + email, + user, + self.user_manager.USER_USERNAME_CHANGED_EMAIL_TEMPLATE, + ) + + def _render_and_send_email(self, email, user, template_filename, **kwargs): + kwargs['app_name'] = self.user_manager.USER_APP_NAME + kwargs['email'] = email + kwargs['user'] = user + kwargs['user_manager'] = self.user_manager + +~~ subject = render_template(template_filename+'_subject.txt', **kwargs) + subject = subject.replace('\n', ' ') + subject = subject.replace('\r', ' ') +~~ html_message = render_template(template_filename+'_message.html', **kwargs) +~~ text_message = render_template(template_filename+'_message.txt', **kwargs) + + self.user_manager.email_adapter.send_email_message( + email, subject, html_message, text_message, + self.sender_email, self.sender_name) + + + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 15 from Flasky +[Flasky](https://github.com/miguelgrinberg/flasky) is a wonderful +example application by +[Miguel Grinberg](https://github.com/miguelgrinberg) that he builds +while teaching developers how to use [Flask](/flask.html) in +[his books and videos](https://courses.miguelgrinberg.com/). Flasky +is [open sourced under the MIT license](https://github.com/miguelgrinberg/flasky/blob/master/LICENSE). + +[**Flasky / app / email.py**](https://github.com/miguelgrinberg/flasky/blob/master/./app/email.py) + +```python +# email.py +from threading import Thread +~~from flask import current_app, render_template +from flask_mail import Message +from . import mail + + +def send_async_email(app, msg): + with app.app_context(): + mail.send(msg) + + +def send_email(to, subject, template, **kwargs): + app = current_app._get_current_object() + msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + ' ' + subject, + sender=app.config['FLASKY_MAIL_SENDER'], recipients=[to]) +~~ msg.body = render_template(template + '.txt', **kwargs) +~~ msg.html = render_template(template + '.html', **kwargs) + thr = Thread(target=send_async_email, args=[app, msg]) + thr.start() + return thr + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 16 from Datadog Flask Example App +The [Datadog Flask example app](https://github.com/DataDog/trace-examples/tree/master/python/flask) +contains many examples of the [Flask](/flask.html) core functions +available to a developer using the [web framework](/web-frameworks.html). + +[**Datadog Flask Example App / python/flask/app / app.py**](https://github.com/DataDog/trace-examples/blob/master/python/flask/app/./app.py) + +```python +# app.py +from ddtrace import patch_all; patch_all(flask=True, requests=True) # noqa + +from ddtrace import tracer + +from flask import Flask, Response +from flask import after_this_request +~~from flask import abort, jsonify, render_template, url_for +from flask.views import View +from werkzeug.routing import Rule + +from flask_caching import Cache +from flask_cors import CORS + +import requests + +from .blueprint import bp +from .exceptions import AppException +from .limiter import limiter +from .signals import connect_signals + +app = Flask(__name__) + +app.register_blueprint(bp) + +connect_signals(app) + +CORS(app) +Cache(app, config=dict(CACHE_TYPE='simple')) +limiter.init_app(app) + + + + +## ... source file abbreviated to get to render_template examples ... + + + 'Blueprint endpoint that uses render_template_string()', + ], + links=[ + dict(label='GET /bp/', url=url_for('bp.index')), + ], + ), + dict( + rule='GET /bp/unknown', + description=[ + 'Blueprint endpoint that calls abort(404)', + ], + links=[ + dict(label='GET /bp/unkown', url=url_for('bp.unknown')), + ], + ), + dict( + rule='GET /static/test.txt', + description=[ + 'Endpoint to fetch a simple .txt static file.', + ], + links=[ + dict(label='GET /static/test.txt', url=url_for('static', filename='test.txt')), + ], + ), + ] +~~ return render_template('index.jinja2', routes=routes) + + +@app.route('/joke') +def joke(): + res = requests.get('https://icanhazdadjoke.com/', headers=dict(Accept='text/plain')) + res.raise_for_status() + + @after_this_request + def after_joke(response): + print('Hook: after_this_request') + return response + + return res.content + + +@app.route('/json') +def json(): + return jsonify(hello='world') + + +app.url_map.add(Rule('/custom-endpoint/', endpoint='custom-endpoint', defaults=dict(msg='Hello'))) +app.url_map.add(Rule('/custom-endpoint/', endpoint='custom-endpoint')) + +@app.endpoint('custom-endpoint') + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 17 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management. +The code is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / util / mathjax.py**](https://github.com/indico/indico/blob/master/indico/util/mathjax.py) + +```python +# mathjax.py + +~~from flask import current_app, render_template + + +class MathjaxMixin: + def _get_head_content(self): +~~ return render_template('mathjax_config.html') + str(current_app.manifest['mathjax.js']) + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 18 from keras-flask-deploy-webapp +The +[keras-flask-deploy-webapp](https://github.com/mtobeiyf/keras-flask-deploy-webapp) +project combines the [Flask](/flask.html) [web framework](/web-frameworks.html) +with the [Keras deep learning library](https://keras.io/) to provide +an example image classifier that is easy to [deploy](/deployment.html). +The application can be quckly run in a [Docker](/docker.html) container +on your local development environment. The project is licensed under the +[GNU General Public License v3.0](https://github.com/mtobeiyf/keras-flask-deploy-webapp/blob/master/LICENSE). + +[**keras-flask-deploy-webapp / app.py**](https://github.com/mtobeiyf/keras-flask-deploy-webapp/blob/master/././app.py) + +```python +# app.py +import os +import sys + +~~from flask import Flask, redirect, url_for, request, render_template, Response, jsonify, redirect +from werkzeug.utils import secure_filename +from gevent.pywsgi import WSGIServer + +import tensorflow as tf +from tensorflow import keras + +from tensorflow.keras.applications.imagenet_utils import preprocess_input, decode_predictions +from tensorflow.keras.models import load_model +from tensorflow.keras.preprocessing import image + +import numpy as np +from util import base64_to_pil + + +app = Flask(__name__) + + + +from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2 +model = MobileNetV2(weights='imagenet') + +print('Model loaded. Check http://127.0.0.1:5000/') + + +MODEL_PATH = 'models/your_model.h5' + + + +def model_predict(img, model): + img = img.resize((224, 224)) + + x = image.img_to_array(img) + x = np.expand_dims(x, axis=0) + + x = preprocess_input(x, mode='tf') + + preds = model.predict(x) + return preds + + +@app.route('/', methods=['GET']) +def index(): +~~ return render_template('index.html') + + +@app.route('/predict', methods=['GET', 'POST']) +def predict(): + if request.method == 'POST': + img = base64_to_pil(request.json) + + + preds = model_predict(img, model) + + pred_proba = "{:.3f}".format(np.amax(preds)) # Max probability + pred_class = decode_predictions(preds, top=1) # ImageNet Decode + + result = str(pred_class[0][0][1]) # Convert to string + result = result.replace('_', ' ').capitalize() + + return jsonify(result=result, probability=pred_proba) + + return None + + +if __name__ == '__main__': + + http_server = WSGIServer(('0.0.0.0', 5000), app) + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 19 from newspie +[NewsPie](https://github.com/skamieniarz/newspie) is a minimalistic news +aggregator created with [Flask](/flask.html) and the +[News API](https://newsapi.org/). + +NewsPie is provided as open source under the +[MIT license](https://github.com/skamieniarz/newspie/blob/master/LICENSE). + +[**newspie / news.py**](https://github.com/skamieniarz/newspie/blob/master/././news.py) + +```python +# news.py +import configparser +import json +import logging +import os +from typing import Union + +import requests +import requests_cache +from dateutil import parser +~~from flask import (Flask, make_response, redirect, render_template, request, + url_for) + +CONFIG = configparser.ConfigParser() +CONFIG.read('config.ini') +API_KEY = os.environ.get('NEWS_API_KEY') +TOP_HEADLINES = CONFIG['ENDPOINTS']['TOP_HEADLINES'] +EVERYTHING = CONFIG['ENDPOINTS']['EVERYTHING'] +PAGE_SIZE = int(CONFIG['VARIOUS']['PAGE_SIZE']) + +CATEGORIES = ('general', 'sports', 'business', 'entertainment', 'health', + 'science', 'technology') +with open('data/countries.json') as json_file: + COUNTRIES = json.load(json_file) + +logging.basicConfig(level=logging.DEBUG) +requests_cache.install_cache(cache_name='news_cache', + backend='sqlite', + expire_after=300) + +APP = Flask(__name__) +SESSION = requests.Session() +SESSION.headers.update({'Authorization': API_KEY}) + + + + +## ... source file abbreviated to get to render_template examples ... + + + return redirect(url_for('category', category='general', page=1)) + + +@APP.route('/category/', methods=['GET', 'POST']) +def category(category): + page = request.args.get('page', default=1, type=int) + if page < 1: + return redirect(url_for('category', category=category, page=1)) + if request.method == 'POST' and category in CATEGORIES: + return do_post(page, category) + if category in CATEGORIES: + params = {'page': page, 'category': category, 'pageSize': PAGE_SIZE} + country = get_cookie('country') + if country is not None: + params.update({'country': country}) + response = SESSION.get(TOP_HEADLINES, params=params) + if response.status_code == 200: + pages = count_pages(response.json()) + if page > pages: + page = pages + return redirect( + url_for('category', category=category, page=page)) + articles = parse_articles(response.json()) + return render(articles, page, pages, country, category) + elif response.status_code == 401: +~~ return render_template(CONFIG['VARIOUS']['401_TEMPLATE']) + return redirect(url_for('category', category='general', page=page)) + + +@APP.route('/search/', methods=['GET', 'POST']) +def search(query: str): + page = request.args.get('page', default=1, type=int) + if page < 1: + return redirect(url_for('search', query=query, page=1)) + params = { + 'qInTitle': query, + 'sortBy': 'relevancy', + 'page': page, + 'pageSize': PAGE_SIZE + } + if request.method == 'POST': + return do_post(page, category='search', current_query=query) + response = SESSION.get(EVERYTHING, params=params) + pages = count_pages(response.json()) + if page > pages: + page = pages + return redirect(url_for('search', query=query, page=page)) + articles = parse_articles(response.json()) + return render(articles, + page, + + +## ... source file abbreviated to get to render_template examples ... + + + parsed_articles = [] + if response.get('status') == 'ok': + for article in response.get('articles'): + parsed_articles.append({ + 'published_at': + parser.isoparse(article['publishedAt'] + ).strftime('%Y-%m-%d %H:%M'), + 'title': + article['title'], + 'url': + article['url'], + 'source': + article['source']['name'] + }) + return parsed_articles + + +def count_pages(response: dict) -> int: + if response.get('status') == 'ok': + return (-(-response.get('totalResults', 0) // PAGE_SIZE)) + return 0 + + +def render(articles, page, pages, country, category): + pages = pages if pages <= 12 else 12 +~~ return render_template(CONFIG['VARIOUS']['TEMPLATE'], + articles=articles, + categories=CATEGORIES, + category=category, + countries=COUNTRIES, + country=country, + page=page, + pages=pages) + + +def get_cookie(key: str) -> Union[str, None]: + return request.cookies.get(key) + + +if __name__ == '__main__': + APP.run() + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 20 from Science Flask +[Science Flask](https://github.com/danielhomola/science_flask) +is a [Flask](/flask.html)-powered web application for online +scientific research tools. The project was built as a template +for any scientist or groups of scientists to use when working +together without having to really understand how the application +is built. The application includes an academic registration +process (only valid academic email addresses can be used), an +admin panel, logging, and analysis forms. + +[@danielhomola](https://github.com/danielhomola) is the +primary creator of Science Flask and the project is open +source under the +[GNU General Public License](https://github.com/danielhomola/science_flask/blob/master/LICENSE). + +[**Science Flask / frontend / views.py**](https://github.com/danielhomola/science_flask/blob/master/./frontend/views.py) + +```python +# views.py +import datetime +import json +import os +import shutil +~~from flask import render_template, redirect, request, g, url_for, flash, abort,\ + send_from_directory, session +from flask_login import login_required +from flask_security import current_user +from werkzeug.utils import secure_filename + +from .analysis import run_analysis, terminate_analysis +from .view_functions import save_study, get_form, save_analysis, \ + get_studies_array, get_analyses_array, \ + get_user_folder, security_check +from backend.utils.check_uploaded_files import clear_up_study +from . import app, db, models +from .forms import UploadForm, AnalysisForm + + +@app.route('/') +def index(): +~~ return render_template('index.html') + +@app.route('/about') +def about(): +~~ return render_template('about.html') + +@app.route('/help') +def help(): +~~ return render_template('help.html') + +@app.route('/tc') +def tc(): +~~ return render_template('tc.html') + + +@app.route('/upload', methods=['GET', 'POST']) +@login_required +def upload(): + + if request.method == 'POST': + form = UploadForm(data=get_form(request.values, request.files)) + try: + check = request.form['check'] + if check == 'true': + check = True + else: + check = False + except: + return json.dumps(dict(status='invalid')) + + if check: + if form.validate_on_submit(): + return json.dumps(dict(status='OK')) + else: + return json.dumps(dict(status='errors', errors=form.errors)) + + else: + try: + return save_study(form, request.files) + except: + user_folder = get_user_folder() + study_folder = secure_filename(form.study_name.data) + user_data_folder = os.path.join(user_folder, study_folder) + clear_up_study(user_data_folder) + return json.dumps(dict(status='invalid')) + + else: + form = UploadForm() + too_many_studies = 0 + if len(current_user.studies.all()) >= app.config['ACTIVE_STUDY_PER_USER']: + too_many_studies = 1 + if current_user.num_studies >= app.config['STUDY_PER_USER']: + too_many_studies = 2 +~~ return render_template('upload.html', form=form, + too_many_studies=too_many_studies) + + +@app.route('/too_large_file') +@login_required +def too_large_file(): +~~ return render_template('utils/max_file_size.html') + + +@app.route('/something_wrong/') +@login_required +def something_wrong(page): +~~ return render_template('utils/something_wrong.html', page=page) + + +@app.route('/analysis/_', methods=['GET', 'POST']) +@login_required +def analysis(user_id, study_id): + if not security_check(user_id, study_id): + abort(403) + + if len(current_user.analyses.filter_by(status=1).all()) > 0: +~~ return render_template('utils/analysis_in_progress.html') + + if request.method == 'POST': + form = AnalysisForm(data=get_form(request.values, request.files)) + try: + check = request.form['check'] + if check == 'true': + check = True + else: + check = False + except: + return json.dumps(dict(status='invalid')) + + if check: + session['study_id'] = study_id + if form.validate_on_submit(): + return json.dumps(dict(status='OK')) + else: + return json.dumps(dict(status='errors', errors=form.errors)) + + else: + try: + save_analysis(form, study_id) + task = run_analysis.apply_async(args=[current_user.id], countdown=1) + session['task_id'] = task.id + return json.dumps(dict(status='OK')) + except: + return json.dumps(dict(status='invalid')) + + else: + form = AnalysisForm() + too_many_analyses = 0 + if len(current_user.analyses.all()) >= app.config['ACTIVE_ANALYSIS_PER_USER']: + too_many_analyses = 1 + if current_user.num_analyses >= app.config['ANALYSIS_PER_USER']: + too_many_analyses = 2 + + study = models.Studies.query.get(study_id) + study_name = study.study_name +~~ return render_template('analysis.html', form=form, user_id=user_id, + study_id=study_id, study_name=study_name, + too_many_analyses=too_many_analyses) + + +@app.route('/profile') +@login_required +def profile(): + studies_array = get_studies_array() + analyses_array = get_analyses_array() + user_id = current_user.id + if len(studies_array) > 0: + study_id = studies_array[0]['id'] + else: + study_id = 0 + + if current_user.profile_intro == 0: + profile_intro = True + current_user.profile_intro = 1 + db.session.add(current_user) + db.session.commit() + else: + profile_intro = False + + stats = { + 'active_studies': len(current_user.studies.all()), + 'all_studies': current_user.num_studies, + 'active_analyses': len(current_user.analyses.all()), + 'all_analyses': current_user.num_analyses + } +~~ return render_template('profile.html', studies=studies_array, stats=stats, + analyses=analyses_array, profile_intro=profile_intro, + user_id=user_id, study_id=study_id) + + +@app.route('/delete_study/_/', methods=['POST']) +@login_required +def delete_study(user_id, study_id): + if not security_check(user_id, study_id): + abort(403) + + study = models.Studies.query.get(study_id) + study_name = study.study_name + for analysis in study.analyses.all(): + db.session.delete(analysis) + db.session.delete(study) + db.session.commit() + + user_folder = get_user_folder() + study_folder = secure_filename(study_name) + folder_to_delete = os.path.join(user_folder, study_folder) + if os.path.exists(folder_to_delete): + shutil.rmtree(folder_to_delete) + return redirect(url_for('profile')) + + + +## ... source file abbreviated to get to render_template examples ... + + + + +@app.route('/vis/__') +@login_required +def vis(user_id, analysis_id, data_file): + if not security_check(user_id, analysis_id, True): + abort(403) + + if data_file not in ['dataset1_2', 'dataset1', 'dataset2']: + abort(403) + + analysis = models.Analyses.query.get(analysis_id) + analysis_name = analysis.analysis_name + study = models.Studies.query.get(analysis.study_id) + study_name = study.study_name + username = app.config['USER_PREFIX'] + str(current_user.id) + analysis_folder = os.path.join(username, secure_filename(study_name), + secure_filename(analysis_name)) + autocorr = bool(study.autocorr) + dataset_names = [study.dataset1_type] + if autocorr: + dataset_names += study.dataset1_type + else: + dataset_names += [study.dataset2_type] + +~~ return render_template('vis.html', analysis_folder=analysis_folder, + analysis_name=analysis_name, autocorr=autocorr, + user_id=user_id, analysis_id=analysis_id, + data_file=data_file, + dataset_names=dataset_names) + + +@app.errorhandler(403) +def forbidden_error(error): + app.logger.error('403 - Forbidden request: %s', request.path) +~~ return render_template('utils/403.html'), 403 + + +@app.errorhandler(404) +def not_found_error(error): + if "/get_file/" not in request.path: + app.logger.error('404 - Page not found: %s', request.path) +~~ return render_template('utils/404.html'), 404 + + +@app.errorhandler(500) +def internal_error(error): + db.session.rollback() + app.logger.error('500 - Internal server error: %s', request.path) +~~ return render_template('utils/500.html'), 500 + + +@app.errorhandler(500) +def all_exception_error(exception): + db.session.rollback() + app.logger.error('All other exception error: %s', request.path) +~~ return render_template('utils/500.html'), 500 + + + +@app.route('/robots.txt') +@app.route('/sitemap.xml') +@app.route('/favicon.ico') +def static_from_root(): + return send_from_directory(app.static_folder, request.path[1:]) + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 21 from tedivms-flask +[tedivm's flask starter app](https://github.com/tedivm/tedivms-flask) is a +base of [Flask](/flask.html) code and related projects such as +[Celery](/celery.html) which provides a template to start your own +Flask web app. The project comes baked with an admin panel, +[API authentication and authorization](/application-programming-interfaces.html), +[SQLAlchemy](/sqlalchemy.html) and many other common libraries that are +often used with Flask. + +The project's code is provided as open source under the +[BSD 2-Clause "Simplified" license](https://github.com/tedivm/tedivms-flask/blob/master/LICENSE.txt). + +[**tedivms-flask / app / __init__.py**](https://github.com/tedivm/tedivms-flask/blob/master/app/./__init__.py) + +```python +# __init__.py +import boto3 +from celery import Celery +from datetime import datetime +import os +import requests +import yaml + +~~from flask import Flask, render_template +from flask import session as current_session +from flask_mail import Mail +from flask_migrate import Migrate, MigrateCommand +from flask.sessions import SessionInterface +from flask_sqlalchemy import SQLAlchemy +from flask_user import user_logged_out +from flask_wtf.csrf import CSRFProtect + +from beaker.cache import CacheManager +from beaker.util import parse_cache_config_options +from beaker.middleware import SessionMiddleware + +db = SQLAlchemy() +csrf_protect = CSRFProtect() +mail = Mail() +migrate = Migrate() + + +def get_config(): + app = Flask(__name__) + + app.config.from_object('app.settings') + if 'APPLICATION_SETTINGS' in os.environ: + app.config.from_envvar(os.environ['APPLICATION_SETTINGS']) + + +## ... source file abbreviated to get to render_template examples ... + + + session_opts['session.secret'] = app.secret_key + + class BeakerSessionInterface(SessionInterface): + def open_session(self, app, request): + session = request.environ['beaker.session'] + return session + + def save_session(self, app, session, response): + session.save() + + app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts) + app.session_interface = BeakerSessionInterface() + + @user_logged_out.connect_via(app) + def clear_session(sender, user, **extra): + current_session.clear() + + +def init_celery_service(app): + celery.conf.update(app.config) + + +def init_error_handlers(app): + + def show_error(status, message='An unknown error has occured.'): +~~ return render_template('pages/errors.html', error_code=status, message=message), status + + @app.errorhandler(401) + def error_unauthorized(e): + return show_error(401, 'Unauthorized') + + @app.errorhandler(403) + def error_forbidden(e): + return show_error(403, 'Forbidden') + + @app.errorhandler(404) + def error_pagenotfound(e): + return show_error(404, 'Page not found.') + + @app.errorhandler(500) + def error_servererror(e): + return show_error(500, 'An unknown error has occurred on the server.') + + + +## ... source file continues with no further render_template examples... + +``` + + +## Example 22 from trape +[trape](https://github.com/jofpin/trape) is a research tool for tracking +people's activities that are logged digitally. The tool uses +[Flask](/flask.html) to create a web front end to view aggregated data +on an individual the application is set to track. The source code is +provided as open source under the MIT license, according to the +[README](https://github.com/jofpin/trape/blob/master/README.md). + +[**trape / core / stats.py**](https://github.com/jofpin/trape/blob/master/./core/stats.py) + +```python +# stats.py +from core.dependence import urllib2 +import sys +import os +~~from flask import Flask, render_template, session, request, json, redirect, url_for, send_from_directory +from flask_cors import CORS +from trape import Trape +import urllib +from core.db import Database + +trape = Trape(1) + +if getattr(sys, 'frozen', False): + template_folder = os.path.join(sys._MEIPASS, 'templates') + static_folder = os.path.join(sys._MEIPASS, 'static') + app = Flask(__name__, template_folder=template_folder, static_folder=static_folder) +else: + app = Flask(__name__, template_folder='../templates', static_folder='../static') + +cors = CORS(app) + +db = Database() + +trape.header() + + +@app.route("/" + trape.stats_path) +def index(): + return trape.injectCSS_Paths(render_template("/login.html").replace('[LOGIN_SRC]', trape.JSFiles[2]['src']).replace('[LIBS_SRC]', trape.JSFiles[1]['src'])) + + +## ... source file abbreviated to get to render_template examples ... + + + server_code = '' + if trape.nGrokUrl != '': + server_code = str(trape.nGrokUrl) + else: + server_code = str(trape.localIp) + ':' + str(trape.app_port) + + codeToInject = codeToInject.replace('[HOST_ADDRESS]', server_code) + codeToInject = codeToInject.replace('[YOUR_GMAPS_API_KEY]', trape.gmaps) + return codeToInject + +@app.route("/static/js/") +def busted(JSFile): + code = '' + mPath = '' + if getattr(sys, 'frozen', False): + mPath = sys._MEIPASS + '/' + for obj in trape.JSFiles: + if str(obj['src']) == str(JSFile): + s_code = open(mPath + "static/js/" + obj['path'],"r") + code = s_code.read() + s_code.close() + break + if code != '': + return code + else: +~~ return render_template('404.html') + +@app.route("/styles/") +def style_redirect(CSSFile): + code = '' + for obj in trape.CSSFiles: + if str(obj['src']) == str(CSSFile): + code = obj['path'] + break + return redirect(code) + +@app.route("/static/files/") +def file_redirect(File): + uploads = os.path.join(os.getcwd(), './') + return send_from_directory(directory=uploads, filename=File) + + + +## ... source file continues with no further render_template examples... + +``` + diff --git a/content/pages/examples/flask/flask-views-http-method-funcs.markdown b/content/pages/examples/flask/flask-views-http-method-funcs.markdown new file mode 100644 index 000000000..d9ad8fb08 --- /dev/null +++ b/content/pages/examples/flask/flask-views-http-method-funcs.markdown @@ -0,0 +1,137 @@ +title: flask.views http_method_funcs Example Code +category: page +slug: flask-views-http-method-funcs-examples +sortorder: 500021035 +toc: False +sidebartitle: flask.views http_method_funcs +meta: Python example code that shows how to use the http_method_funcs callable from the flask.views module of the Flask project. + + +`http_method_funcs` is an immutable Python set within the +[flask.views module](https://github.com/pallets/flask/blob/master/src/flask/views.py) +of the [Flask](/flask.html) project. It contains strings of the HTTP methods +"get", "post", "head", "options", "delete", "put", "trace", and "patch", +which is useful for checking if an HTTP method is valid by comparing it +against the items in this set. + +MethodView +and +View +are a couple of other callables within the `flask.views` package that also have code examples. + +These subjects go along with the `http_method_funcs` code examples: + +* [web development](/web-development.html) and [web design](/web-design.html) +* [web framework concepts](/web-frameworks.html) and the [Flask framework](/flask.html) + + +## Example 1 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / namespace.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./namespace.py) + +```python +# namespace.py +from __future__ import unicode_literals + +import inspect +import warnings +import logging +from collections import namedtuple, OrderedDict + +import six +from flask import request +~~from flask.views import http_method_funcs + +from ._http import HTTPStatus +from .errors import abort +from .marshalling import marshal, marshal_with +from .model import Model, OrderedModel, SchemaModel +from .reqparse import RequestParser +from .utils import merge + +ResourceRoute = namedtuple("ResourceRoute", "resource urls route_doc kwargs") + + +class Namespace(object): + + def __init__( + self, + name, + description=None, + path=None, + decorators=None, + validate=None, + authorizations=None, + ordered=False, + **kwargs + ): + + +## ... source file abbreviated to get to http_method_funcs examples ... + + + return (self._path or ("/" + self.name)).rstrip("/") + + def add_resource(self, resource, *urls, **kwargs): + route_doc = kwargs.pop("route_doc", {}) + self.resources.append(ResourceRoute(resource, urls, route_doc, kwargs)) + for api in self.apis: + ns_urls = api.ns_urls(self, urls) + api.register_resource(self, resource, *ns_urls, **kwargs) + + def route(self, *urls, **kwargs): + + def wrapper(cls): + doc = kwargs.pop("doc", None) + if doc is not None: + kwargs["route_doc"] = self._build_doc(cls, doc) + self.add_resource(cls, *urls, **kwargs) + return cls + + return wrapper + + def _build_doc(self, cls, doc): + if doc is False: + return False + unshortcut_params_description(doc) + handle_deprecations(doc) +~~ for http_method in http_method_funcs: + if http_method in doc: + if doc[http_method] is False: + continue + unshortcut_params_description(doc[http_method]) + handle_deprecations(doc[http_method]) + if "expect" in doc[http_method] and not isinstance( + doc[http_method]["expect"], (list, tuple) + ): + doc[http_method]["expect"] = [doc[http_method]["expect"]] + return merge(getattr(cls, "__apidoc__", {}), doc) + + def doc(self, shortcut=None, **kwargs): + if isinstance(shortcut, six.text_type): + kwargs["id"] = shortcut + show = shortcut if isinstance(shortcut, bool) else True + + def wrapper(documented): + documented.__apidoc__ = self._build_doc( + documented, kwargs if show else False + ) + return documented + + return wrapper + + + +## ... source file continues with no further http_method_funcs examples... + +``` + diff --git a/content/pages/examples/flask/flask-views-methodview.markdown b/content/pages/examples/flask/flask-views-methodview.markdown new file mode 100644 index 000000000..c0e34c8e9 --- /dev/null +++ b/content/pages/examples/flask/flask-views-methodview.markdown @@ -0,0 +1,559 @@ +title: flask.views MethodView Example Code +category: page +slug: flask-views-methodview-examples +sortorder: 500021033 +toc: False +sidebartitle: flask.views MethodView +meta: Example code for understanding how to use the MethodView class from the flask.views module of the Flask project. + + +[MethodView](https://github.com/pallets/flask/blob/master/src/flask/views.py) +is a class within the `flask.views` module of the [Flask](/flask.html) +project. `MethodView` is a +[Python Metaclass](https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python) +that determines the methods, such as GET, POST, PUT, etc, that +a view defines. + +View +and +http_method_funcs +are a couple of other callables within the `flask.views` package that also have code examples. + +You should read up on these subjects along with these `MethodView` examples: + +* [web development](/web-development.html) and [web design](/web-design.html) +* [web framework concepts](/web-frameworks.html) and the [Flask framework](/flask.html) + + +## Example 1 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / auth / views.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/auth/views.py) + +```python +# views.py +import logging +from datetime import datetime + +from flask import Blueprint, current_app, flash, g, redirect, request, url_for +~~from flask.views import MethodView +from flask_babelplus import gettext as _ +from flask_login import ( + confirm_login, + current_user, + login_fresh, + login_required, + login_user, + logout_user, +) + +from flaskbb.auth.forms import ( + AccountActivationForm, + ForgotPasswordForm, + LoginForm, + LoginRecaptchaForm, + ReauthForm, + RegisterForm, + RequestActivationForm, + ResetPasswordForm, +) +from flaskbb.extensions import db, limiter +from flaskbb.utils.helpers import ( + anonymous_required, + enforce_recaptcha, + + +## ... source file abbreviated to get to MethodView examples ... + + + get_available_languages, + redirect_or_next, + register_view, + registration_enabled, + render_template, + requires_unactivated, +) +from flaskbb.utils.settings import flaskbb_config + +from ..core.auth.authentication import StopAuthentication +from ..core.auth.registration import UserRegistrationInfo +from ..core.exceptions import PersistenceError, StopValidation, ValidationError +from ..core.tokens import TokenError +from .plugins import impl +from .services import ( + account_activator_factory, + authentication_manager_factory, + reauthentication_manager_factory, + registration_service_factory, + reset_service_factory, +) + +logger = logging.getLogger(__name__) + + +~~class Logout(MethodView): + decorators = [limiter.exempt, login_required] + + def get(self): + logout_user() + flash(_("Logged out"), "success") + return redirect(url_for("forum.index")) + + +~~class Login(MethodView): + decorators = [anonymous_required] + + def __init__(self, authentication_manager_factory): + self.authentication_manager_factory = authentication_manager_factory + + def form(self): + if enforce_recaptcha(limiter): + return LoginRecaptchaForm() + return LoginForm() + + def get(self): + return render_template("auth/login.html", form=self.form()) + + def post(self): + form = self.form() + if form.validate_on_submit(): + auth_manager = self.authentication_manager_factory() + try: + user = auth_manager.authenticate( + identifier=form.login.data, secret=form.password.data + ) + login_user(user, remember=form.remember_me.data) + return redirect_or_next(url_for("forum.index"), False) + except StopAuthentication as e: + flash(e.reason, "danger") + except Exception: + flash(_("Unrecoverable error while handling login")) + + return render_template("auth/login.html", form=form) + + +~~class Reauth(MethodView): + decorators = [login_required, limiter.exempt] + form = ReauthForm + + def __init__(self, reauthentication_factory): + self.reauthentication_factory = reauthentication_factory + + def get(self): + if not login_fresh(): + return render_template("auth/reauth.html", form=self.form()) + return redirect_or_next(current_user.url) + + def post(self): + form = self.form() + if form.validate_on_submit(): + + reauth_manager = self.reauthentication_factory() + try: + reauth_manager.reauthenticate( + user=current_user, secret=form.password.data + ) + confirm_login() + flash(_("Reauthenticated."), "success") + return redirect_or_next(current_user.url) + except StopAuthentication as e: + flash(e.reason, "danger") + except Exception: + flash(_("Unrecoverable error while handling reauthentication")) + raise + + return render_template("auth/reauth.html", form=form) + + +~~class Register(MethodView): + decorators = [anonymous_required, registration_enabled] + + def __init__(self, registration_service_factory): + self.registration_service_factory = registration_service_factory + + def form(self): + current_app.pluggy.hook.flaskbb_form_registration(form=RegisterForm) + form = RegisterForm() + + form.language.choices = get_available_languages() + form.language.default = flaskbb_config['DEFAULT_LANGUAGE'] + form.process(request.form) # needed because a default is overriden + return form + + def get(self): + return render_template("auth/register.html", form=self.form()) + + def post(self): + form = self.form() + if form.validate_on_submit(): + registration_info = UserRegistrationInfo( + username=form.username.data, + password=form.password.data, + group=4, + + +## ... source file abbreviated to get to MethodView examples ... + + + service = self.registration_service_factory() + try: + service.register(registration_info) + except StopValidation as e: + form.populate_errors(e.reasons) + return render_template("auth/register.html", form=form) + except PersistenceError: + logger.exception("Database error while persisting user") + flash( + _( + "Could not process registration due" + "to an unrecoverable error" + ), "danger" + ) + + return render_template("auth/register.html", form=form) + + current_app.pluggy.hook.flaskbb_event_user_registered( + username=registration_info.username + ) + return redirect_or_next(url_for('forum.index')) + + return render_template("auth/register.html", form=form) + + +~~class ForgotPassword(MethodView): + decorators = [anonymous_required] + form = ForgotPasswordForm + + def __init__(self, password_reset_service_factory): + self.password_reset_service_factory = password_reset_service_factory + + def get(self): + return render_template("auth/forgot_password.html", form=self.form()) + + def post(self): + form = self.form() + if form.validate_on_submit(): + + try: + service = self.password_reset_service_factory() + service.initiate_password_reset(form.email.data) + except ValidationError: + flash( + _( + "You have entered an username or email address that " + "is not linked with your account." + ), "danger" + ) + else: + flash(_("Email sent! Please check your inbox."), "info") + return redirect(url_for("auth.forgot_password")) + + return render_template("auth/forgot_password.html", form=form) + + +~~class ResetPassword(MethodView): + decorators = [anonymous_required] + form = ResetPasswordForm + + def __init__(self, password_reset_service_factory): + self.password_reset_service_factory = password_reset_service_factory + + def get(self, token): + form = self.form() + form.token.data = token + return render_template("auth/reset_password.html", form=form) + + def post(self, token): + form = self.form() + if form.validate_on_submit(): + try: + service = self.password_reset_service_factory() + service.reset_password( + token, form.email.data, form.password.data + ) + except TokenError as e: + flash(e.reason, 'danger') + return redirect(url_for('auth.forgot_password')) + except StopValidation as e: + form.populate_errors(e.reasons) + form.token.data = token + return render_template("auth/reset_password.html", form=form) + except Exception: + logger.exception("Error when resetting password") + flash(_('Error when resetting password')) + return redirect(url_for('auth.forgot_password')) + finally: + try: + db.session.commit() + except Exception: + logger.exception( + "Error while finalizing database when resetting password" # noqa + ) + db.session.rollback() + + flash(_("Your password has been updated."), "success") + return redirect(url_for("auth.login")) + + form.token.data = token + return render_template("auth/reset_password.html", form=form) + + +~~class RequestActivationToken(MethodView): + decorators = [requires_unactivated] + form = RequestActivationForm + + def __init__(self, account_activator_factory): + self.account_activator_factory = account_activator_factory + + def get(self): + return render_template( + "auth/request_account_activation.html", form=self.form() + ) + + def post(self): + form = self.form() + if form.validate_on_submit(): + activator = self.account_activator_factory() + try: + activator.initiate_account_activation(form.email.data) + except ValidationError as e: + form.populate_errors([(e.attribute, e.reason)]) + else: + flash( + _( + "A new account activation token has been sent to " + "your email address." + ), "success" + ) + return redirect(url_for('forum.index')) + + return render_template( + "auth/request_account_activation.html", form=form + ) + + +~~class AutoActivateAccount(MethodView): + decorators = [requires_unactivated] + + def __init__(self, account_activator_factory): + self.account_activator_factory = account_activator_factory + + def get(self, token): + activator = self.account_activator_factory() + + try: + activator.activate_account(token) + except TokenError as e: + flash(e.reason, 'danger') + except ValidationError as e: + flash(e.reason, 'danger') + return redirect(url_for('forum.index')) + + else: + try: + db.session.commit() + except Exception: # noqa + logger.exception("Database error while activating account") + db.session.rollback() + flash( + _( + "Could not activate account due to an unrecoverable error" # noqa + ), "danger" + ) + + return redirect(url_for('auth.request_activation_token')) + + flash( + _("Your account has been activated and you can now login."), + "success" + ) + return redirect(url_for("forum.index")) + + return redirect(url_for('auth.activate_account')) + + +~~class ActivateAccount(MethodView): + decorators = [requires_unactivated] + form = AccountActivationForm + + def __init__(self, account_activator_factory): + self.account_activator_factory = account_activator_factory + + def get(self): + return render_template( + "auth/account_activation.html", + form=self.form() + ) + + def post(self): + form = self.form() + if form.validate_on_submit(): + token = form.token.data + activator = self.account_activator_factory() + try: + activator.activate_account(token) + except TokenError as e: + form.populate_errors([('token', e.reason)]) + except ValidationError as e: + flash(e.reason, 'danger') + return redirect(url_for('forum.index')) + + +## ... source file continues with no further MethodView examples... + +``` + + +## Example 2 from flask-restx +[Flask RESTX](https://github.com/python-restx/flask-restx) is an +extension that makes it easier to build +[RESTful APIs](/application-programming-interfaces.html) into +your applications. Flask RESTX aims for minimal configuration to +get basic APIs running for existing applications and it exposes +endpoint documentation using [Swagger](https://swagger.io/). + +Flask RESTX is provided as open source under the +[BSD 3-Clause license](https://github.com/python-restx/flask-restx/blob/master/LICENSE). + +[**flask-restx / flask_restx / resource.py**](https://github.com/python-restx/flask-restx/blob/master/flask_restx/./resource.py) + +```python +# resource.py +from __future__ import unicode_literals + +from flask import request +~~from flask.views import MethodView +from werkzeug import __version__ as werkzeug_version + +if werkzeug_version.split('.')[0] >= '2': + from werkzeug.wrappers import Response as BaseResponse +else: + from werkzeug.wrappers import BaseResponse + +from .model import ModelBase + +from .utils import unpack + + +~~class Resource(MethodView): + + representations = None + method_decorators = [] + + def __init__(self, api=None, *args, **kwargs): + self.api = api + + def dispatch_request(self, *args, **kwargs): + meth = getattr(self, request.method.lower(), None) + if meth is None and request.method == "HEAD": + meth = getattr(self, "get", None) + assert meth is not None, "Unimplemented method %r" % request.method + + for decorator in self.method_decorators: + meth = decorator(meth) + + self.validate_payload(meth) + + resp = meth(*args, **kwargs) + + if isinstance(resp, BaseResponse): + return resp + + representations = self.representations or {} + + +## ... source file continues with no further MethodView examples... + +``` + + +## Example 3 from sandman2 +[sandman2](https://github.com/jeffknupp/sandman2) +([project documentation](https://sandman2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/sandman2/)) +is a code library for automatically generating +[RESTful APIs](/application-programming-interfaces.html) from +existing database schemas. This approach is handy for solving +straightforward situations where you want to put an abstraction +layer between one or more applications and your +[relational database](/databases.html) to prevent or reduce +direct database access. + +The sandman2 project is provided under the +[Apache License 2.0](https://github.com/jeffknupp/sandman2/blob/master/LICENSE). + +[**sandman2 / sandman2 / service.py**](https://github.com/jeffknupp/sandman2/blob/master/sandman2/./service.py) + +```python +# service.py + +from flask import request, make_response +import flask +~~from flask.views import MethodView +from sqlalchemy import asc, desc + +from sandman2.exception import NotFoundException, BadRequestException +from sandman2.model import db +from sandman2.decorators import etag, validate_fields + + +def add_link_headers(response, links): + link_string = '<{}>; rel=self'.format(links['self']) + for link in links.values(): + link_string += ', <{}>; rel=related'.format(link) + response.headers['Link'] = link_string + return response + + +def jsonify(resource): + + response = flask.jsonify(resource.to_dict()) + response = add_link_headers(response, resource.links()) + return response + + +def is_valid_method(model, resource=None): + validation_function_name = 'is_valid_{}'.format( + request.method.lower()) + if hasattr(model, validation_function_name): + return getattr(model, validation_function_name)(request, resource) + +~~class Service(MethodView): + + + __model__ = None + + __json_collection_name__ = 'resources' + + def delete(self, resource_id): + resource = self._resource(resource_id) + error_message = is_valid_method(self.__model__, resource) + if error_message: + raise BadRequestException(error_message) + db.session().delete(resource) + db.session().commit() + return self._no_content_response() + + @etag + def get(self, resource_id=None): + if request.path.endswith('meta'): + return self._meta() + + if resource_id is None: + error_message = is_valid_method(self.__model__) + if error_message: + raise BadRequestException(error_message) + + +## ... source file continues with no further MethodView examples... + +``` + diff --git a/content/pages/examples/flask/flask-views-view.markdown b/content/pages/examples/flask/flask-views-view.markdown new file mode 100644 index 000000000..1f8e51936 --- /dev/null +++ b/content/pages/examples/flask/flask-views-view.markdown @@ -0,0 +1,148 @@ +title: flask.views View Example Code +category: page +slug: flask-views-view-examples +sortorder: 500021034 +toc: False +sidebartitle: flask.views View +meta: Example code for understanding how to use the View class from the flask.views module of the Flask project. + + +[View](https://github.com/pallets/flask/blob/master/src/flask/views.py) +is a class within the `flask.views` module of the [Flask](/flask.html) +project. `View` provides an alternative way to use view functions +by subclassing this class and implementing `dispatch_request` +for the routing system. This is typically only used in more advanced +situations such as extending the Flask source code, rather than +a standard way of interacting with the framework. + +MethodView +and +http_method_funcs +are a couple of other callables within the `flask.views` package that also have code examples. + +You should read up on these subjects along with these `View` examples: + +* [web development](/web-development.html) and [web design](/web-design.html) +* [web framework concepts](/web-frameworks.html) and the [Flask framework](/flask.html) + + +## Example 1 from FlaskBB +[FlaskBB](https://github.com/flaskbb/flaskbb) +([project website](https://flaskbb.org/)) is a [Flask](/flask.html)-based +forum web application. The web app allows users to chat in an open +message board or send private messages in plain text or +[Markdown](/markdown.html). + +FlaskBB is provided as open source +[under this license](https://github.com/flaskbb/flaskbb/blob/master/LICENSE). + +[**FlaskBB / flaskbb / utils / views.py**](https://github.com/flaskbb/flaskbb/blob/master/flaskbb/utils/views.py) + +```python +# views.py +from flaskbb.utils.helpers import render_template +~~from flask.views import View + + +~~class RenderableView(View): + def __init__(self, template, view): + self.template = template + self.view = view + + def dispatch_request(self, *args, **kwargs): + view_model = self.view(*args, **kwargs) + return render_template(self.template, **view_model) + + + +## ... source file continues with no further View examples... + +``` + + +## Example 2 from Datadog Flask Example App +The [Datadog Flask example app](https://github.com/DataDog/trace-examples/tree/master/python/flask) +contains many examples of the [Flask](/flask.html) core functions +available to a developer using the [web framework](/web-frameworks.html). + +[**Datadog Flask Example App / python/flask/app / app.py**](https://github.com/DataDog/trace-examples/blob/master/python/flask/app/./app.py) + +```python +# app.py +from ddtrace import patch_all; patch_all(flask=True, requests=True) # noqa + +from ddtrace import tracer + +from flask import Flask, Response +from flask import after_this_request +from flask import abort, jsonify, render_template, url_for +~~from flask.views import View +from werkzeug.routing import Rule + +from flask_caching import Cache +from flask_cors import CORS + +import requests + +from .blueprint import bp +from .exceptions import AppException +from .limiter import limiter +from .signals import connect_signals + +app = Flask(__name__) + +app.register_blueprint(bp) + +connect_signals(app) + +CORS(app) +Cache(app, config=dict(CACHE_TYPE='simple')) +limiter.init_app(app) + + +@app.context_processor + + +## ... source file abbreviated to get to View examples ... + + + +@app.route('/stream') +def stream(): + def generate(): + for i in range(100): + yield '{}\n'.format(i) + + return Response(generate(), mimetype='text/plain') + + +@app.route('/abort/') +def abort_endpoint(code): + abort(code) + + +@app.errorhandler(404) +def handle_404(e): + return '404', 404 + + +@app.errorhandler(500) +def handle_500(e): + return '500', 500 + + +~~class MyView(View): + methods = ['GET'] + + def dispatch_request(self, name): + return 'Hello %s!' % name + + +app.add_url_rule('/hello/', view_func=MyView.as_view('myview')) + + + +## ... source file continues with no further View examples... + +``` + diff --git a/content/pages/examples/pandas/pandas-example-projects-code.markdown b/content/pages/examples/pandas/pandas-example-projects-code.markdown new file mode 100644 index 000000000..facc17141 --- /dev/null +++ b/content/pages/examples/pandas/pandas-example-projects-code.markdown @@ -0,0 +1,63 @@ +title: pandas Example Projects and Code +category: page +slug: pandas-code-examples +sortorder: 500090001 +toc: False +sidebartitle: pandas Example Code +meta: Python example projects and code that show how to use the pandas data analysis library. + + +## Projects with pandas Example Code +The following active projects use the [pandas](/pandas.html) data analysis +library in various ways that can show you how to inspect your own data sets +and build your own applications. + + +### 100-pandas-puzzles +[100 pandas puzzles](https://github.com/ajcr/100-pandas-puzzles) is a project with +100 exercises that test knowledge of pandas' functionality. The project contains two +[Jupyter Notebooks](/jupyter-notebook.html), one with +[just the puzzles](https://github.com/ajcr/100-pandas-puzzles/blob/master/100-pandas-puzzles.ipynb) +and the other with +[both puzzles and solutions](https://github.com/ajcr/100-pandas-puzzles/blob/master/100-pandas-puzzles-with-solutions.ipynb). + +The project is provided as open source under the +[MIT license](https://github.com/ajcr/100-pandas-puzzles/blob/master/LICENSE). + + +### data-science-ipython-notebooks +[data-science-ipython-notebooks](https://github.com/donnemartin/data-science-ipython-notebooks) +is a collection of Jupyter Notebooks including a folder with +[pandas code examples](https://github.com/donnemartin/data-science-ipython-notebooks/tree/master/pandas). + +These notebooks are provided as open source under the +[Apache 2.0 license](https://github.com/donnemartin/data-science-ipython-notebooks/blob/master/LICENSE). + + +### pandas-videos +[Python pandas Q&A video series](https://github.com/justmarkham/pandas-videos) contains the +Python code that pairs with +[Kevin Markham's video series on data analysis with pandas](https://www.youtube.com/playlist?list=PL5-da3qGB5ICCsgW1MxlZ0Hq8LL5U3u9y). +The repository contains several Jupyter Notebooks, including ones on +[the top pandas tricks](https://github.com/justmarkham/pandas-videos/blob/master/top_25_pandas_tricks.ipynb), +[merging DataFrames](https://github.com/justmarkham/pandas-videos/blob/master/pandas_merge.ipynb), +and +[using MultiIndex](https://github.com/justmarkham/pandas-videos/blob/master/pandas_multiindex.ipynb). + + +### ved-explore +[ved-explore](https://github.com/joaofig/ved-explore) is a set of open source +Jupyter Notebooks that demonstrate analysis of the +[Vehicle Energy Dataset (VED)](https://arxiv.org/abs/1905.02081). The project +is provided as open source under the +[MIT license](https://github.com/joaofig/ved-explore/blob/master/LICENSE). + + +### viz +[viz](https://github.com/donnemartin/viz) +([project site](https://donnemartin.com/viz/)) +is a collection of interactive Jupyter Notebooks that show metrics +about open source Git repositories stored on GitHub. The code is open source +under the +[Apache 2.0 license](https://github.com/donnemartin/viz/blob/master/LICENSE.md). + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-databases-mysql.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-databases-mysql.markdown new file mode 100644 index 000000000..4ae90ea25 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-databases-mysql.markdown @@ -0,0 +1,83 @@ +title: sqlalchemy.databases mysql Example Code +category: page +slug: sqlalchemy-databases-mysql-examples +sortorder: 500031000 +toc: False +sidebartitle: sqlalchemy.databases mysql +meta: Python example code that shows how to use the mysql callable from the sqlalchemy.databases module of the SQLAlchemy project. + + +`mysql` is a callable within the `sqlalchemy.databases` module of the SQLAlchemy project. + + + +## Example 1 from PyHive +[PyHive](https://github.com/dropbox/PyHive) +([PyPI package information](https://pypi.org/project/PyHive/)) +is a set of [DB-API](https://www.python.org/dev/peps/pep-0249/) +and +[SQLAlchemy](/sqlalchemy.html) +interfaces that make it easier to use [Presto](https://prestodb.io/) +and [Apache Hive](http://hive.apache.org/) with Python. +[Dropbox's engineering team](https://www.dropbox.com/jobs/teams/engineering) +created this code library, open sourced it and put it out under +the [Apache 2.0 license](https://github.com/dropbox/PyHive/blob/master/LICENSE). + +[**PyHive / pyhive / sqlalchemy_presto.py**](https://github.com/dropbox/PyHive/blob/master/pyhive/./sqlalchemy_presto.py) + +```python +# sqlalchemy_presto.py + +from __future__ import absolute_import +from __future__ import unicode_literals + +import re +from sqlalchemy import exc +from sqlalchemy import types +from sqlalchemy import util +~~from sqlalchemy.databases import mysql +from sqlalchemy.engine import default +from sqlalchemy.sql import compiler +from sqlalchemy.sql.compiler import SQLCompiler + +from pyhive import presto +from pyhive.common import UniversalSet + + +class PrestoIdentifierPreparer(compiler.IdentifierPreparer): + reserved_words = UniversalSet() + + +_type_map = { + 'boolean': types.Boolean, +~~ 'tinyint': mysql.MSTinyInteger, + 'smallint': types.SmallInteger, + 'integer': types.Integer, + 'bigint': types.BigInteger, + 'real': types.Float, + 'double': types.Float, + 'varchar': types.String, + 'timestamp': types.TIMESTAMP, + 'date': types.DATE, + 'varbinary': types.VARBINARY, +} + + +class PrestoCompiler(SQLCompiler): + def visit_char_length_func(self, fn, **kw): + return 'length{}'.format(self.function_argspec(fn, **kw)) + + +class PrestoTypeCompiler(compiler.GenericTypeCompiler): + def visit_CLOB(self, type_, **kw): + raise ValueError("Presto does not support the CLOB column type.") + + def visit_NCLOB(self, type_, **kw): + raise ValueError("Presto does not support the NCLOB column type.") + + + +## ... source file continues with no further mysql examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-mssql.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-mssql.markdown new file mode 100644 index 000000000..64753b3d9 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-mssql.markdown @@ -0,0 +1,125 @@ +title: sqlalchemy.dialects mssql Example Code +category: page +slug: sqlalchemy-dialects-mssql-examples +sortorder: 500031001 +toc: False +sidebartitle: sqlalchemy.dialects mssql +meta: Python example code that shows how to use the mssql callable from the sqlalchemy.dialects module of the SQLAlchemy project. + + +`mssql` is a callable within the `sqlalchemy.dialects` module of the SQLAlchemy project. + +mysql, +oracle, +postgresql, +and sqlite +are several other callables with code examples from the same `sqlalchemy.dialects` package. + +## Example 1 from marshmallow-sqlalchemy +[marshmallow-sqlalchemy](https://github.com/marshmallow-code/marshmallow-sqlalchemy) +([project documentation](https://marshmallow-sqlalchemy.readthedocs.io/en/latest/)) +is a code library that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) with the +[Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +data serialization tool. + +The marshmallow-sqlalchemy project is provided as open source under the +[MIT license](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/LICENSE). + +[**marshmallow-sqlalchemy / src/marshmallow_sqlalchemy / convert.py**](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/src/marshmallow_sqlalchemy/./convert.py) + +```python +# convert.py +import inspect +import functools +import warnings + +import uuid +import marshmallow as ma +from marshmallow import validate, fields +~~from sqlalchemy.dialects import postgresql, mysql, mssql +from sqlalchemy.orm import SynonymProperty +import sqlalchemy as sa + +from .exceptions import ModelConversionError +from .fields import Related, RelatedList + + +def _is_field(value): + return isinstance(value, type) and issubclass(value, fields.Field) + + +def _has_default(column): + return ( + column.default is not None + or column.server_default is not None + or _is_auto_increment(column) + ) + + +def _is_auto_increment(column): + return column.table is not None and column is column.table._autoincrement_column + + +def _postgres_array_factory(converter, data_type): + + +## ... source file abbreviated to get to mssql examples ... + + + +class ModelConverter: + + SQLA_TYPE_MAPPING = { + sa.Enum: fields.Field, + sa.JSON: fields.Raw, + postgresql.BIT: fields.Integer, + postgresql.OID: fields.Integer, + postgresql.UUID: fields.UUID, + postgresql.MACADDR: fields.String, + postgresql.INET: fields.String, + postgresql.CIDR: fields.String, + postgresql.JSON: fields.Raw, + postgresql.JSONB: fields.Raw, + postgresql.HSTORE: fields.Raw, + postgresql.ARRAY: _postgres_array_factory, + postgresql.MONEY: fields.Decimal, + postgresql.DATE: fields.Date, + postgresql.TIME: fields.Time, + mysql.BIT: fields.Integer, + mysql.YEAR: fields.Integer, + mysql.SET: fields.List, + mysql.ENUM: fields.Field, + mysql.INTEGER: fields.Integer, + mysql.DATETIME: fields.DateTime, +~~ mssql.BIT: fields.Integer, + } + DIRECTION_MAPPING = {"MANYTOONE": False, "MANYTOMANY": True, "ONETOMANY": True} + + def __init__(self, schema_cls=None): + self.schema_cls = schema_cls + + @property + def type_mapping(self): + if self.schema_cls: + return self.schema_cls.TYPE_MAPPING + else: + return ma.Schema.TYPE_MAPPING + + def fields_for_model( + self, + model, + *, + include_fk=False, + include_relationships=False, + fields=None, + exclude=None, + base_fields=None, + dict_cls=dict, + ): + + +## ... source file continues with no further mssql examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-mysql-pymysql.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-mysql-pymysql.markdown new file mode 100644 index 000000000..1994a2809 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-mysql-pymysql.markdown @@ -0,0 +1,86 @@ +title: sqlalchemy.dialects.mysql pymysql Example Code +category: page +slug: sqlalchemy-dialects-mysql-pymysql-examples +sortorder: 500031006 +toc: False +sidebartitle: sqlalchemy.dialects.mysql pymysql +meta: Python example code that shows how to use the pymysql callable from the sqlalchemy.dialects.mysql module of the SQLAlchemy project. + + +`pymysql` is a callable within the `sqlalchemy.dialects.mysql` module of the SQLAlchemy project. + + + +## Example 1 from databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + +[**databases / databases / backends / mysql.py**](https://github.com/encode/databases/blob/master/databases/backends/mysql.py) + +```python +# mysql.py +import getpass +import logging +import typing +import uuid + +import aiomysql +~~from sqlalchemy.dialects.mysql import pymysql +from sqlalchemy.engine.interfaces import Dialect, ExecutionContext +from sqlalchemy.engine.result import ResultMetaData, RowProxy +from sqlalchemy.sql import ClauseElement +from sqlalchemy.types import TypeEngine + +from databases.core import LOG_EXTRA, DatabaseURL +from databases.interfaces import ConnectionBackend, DatabaseBackend, TransactionBackend + +logger = logging.getLogger("databases") + + +class MySQLBackend(DatabaseBackend): + def __init__( + self, database_url: typing.Union[DatabaseURL, str], **options: typing.Any + ) -> None: + self._database_url = DatabaseURL(database_url) + self._options = options +~~ self._dialect = pymysql.dialect(paramstyle="pyformat") + self._dialect.supports_native_decimal = True + self._pool = None + + def _get_connection_kwargs(self) -> dict: + url_options = self._database_url.options + + kwargs = {} + min_size = url_options.get("min_size") + max_size = url_options.get("max_size") + ssl = url_options.get("ssl") + + if min_size is not None: + kwargs["minsize"] = int(min_size) + if max_size is not None: + kwargs["maxsize"] = int(max_size) + if ssl is not None: + kwargs["ssl"] = {"true": True, "false": False}[ssl.lower()] + + for key, value in self._options.items(): + if key == "min_size": + key = "minsize" + elif key == "max_size": + key = "maxsize" + kwargs[key] = value + + +## ... source file continues with no further pymysql examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-mysql.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-mysql.markdown new file mode 100644 index 000000000..2508a798d --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-mysql.markdown @@ -0,0 +1,216 @@ +title: sqlalchemy.dialects mysql Example Code +category: page +slug: sqlalchemy-dialects-mysql-examples +sortorder: 500031002 +toc: False +sidebartitle: sqlalchemy.dialects mysql +meta: Python example code that shows how to use the mysql callable from the sqlalchemy.dialects module of the SQLAlchemy project. + + +`mysql` is a callable within the `sqlalchemy.dialects` module of the SQLAlchemy project. + +mssql, +oracle, +postgresql, +and sqlite +are several other callables with code examples from the same `sqlalchemy.dialects` package. + +## Example 1 from marshmallow-sqlalchemy +[marshmallow-sqlalchemy](https://github.com/marshmallow-code/marshmallow-sqlalchemy) +([project documentation](https://marshmallow-sqlalchemy.readthedocs.io/en/latest/)) +is a code library that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) with the +[Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +data serialization tool. + +The marshmallow-sqlalchemy project is provided as open source under the +[MIT license](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/LICENSE). + +[**marshmallow-sqlalchemy / src/marshmallow_sqlalchemy / convert.py**](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/src/marshmallow_sqlalchemy/./convert.py) + +```python +# convert.py +import inspect +import functools +import warnings + +import uuid +import marshmallow as ma +from marshmallow import validate, fields +~~from sqlalchemy.dialects import postgresql, mysql, mssql +from sqlalchemy.orm import SynonymProperty +import sqlalchemy as sa + +from .exceptions import ModelConversionError +from .fields import Related, RelatedList + + +def _is_field(value): + return isinstance(value, type) and issubclass(value, fields.Field) + + +def _has_default(column): + return ( + column.default is not None + or column.server_default is not None + or _is_auto_increment(column) + ) + + +def _is_auto_increment(column): + return column.table is not None and column is column.table._autoincrement_column + + +def _postgres_array_factory(converter, data_type): + return functools.partial( + fields.List, converter._get_field_class_for_data_type(data_type.item_type) + ) + + +class ModelConverter: + + SQLA_TYPE_MAPPING = { + sa.Enum: fields.Field, + sa.JSON: fields.Raw, + postgresql.BIT: fields.Integer, + postgresql.OID: fields.Integer, + postgresql.UUID: fields.UUID, + postgresql.MACADDR: fields.String, + postgresql.INET: fields.String, + postgresql.CIDR: fields.String, + postgresql.JSON: fields.Raw, + postgresql.JSONB: fields.Raw, + postgresql.HSTORE: fields.Raw, + postgresql.ARRAY: _postgres_array_factory, + postgresql.MONEY: fields.Decimal, + postgresql.DATE: fields.Date, + postgresql.TIME: fields.Time, +~~ mysql.BIT: fields.Integer, +~~ mysql.YEAR: fields.Integer, +~~ mysql.SET: fields.List, +~~ mysql.ENUM: fields.Field, +~~ mysql.INTEGER: fields.Integer, +~~ mysql.DATETIME: fields.DateTime, + mssql.BIT: fields.Integer, + } + DIRECTION_MAPPING = {"MANYTOONE": False, "MANYTOMANY": True, "ONETOMANY": True} + + def __init__(self, schema_cls=None): + self.schema_cls = schema_cls + + @property + def type_mapping(self): + if self.schema_cls: + return self.schema_cls.TYPE_MAPPING + else: + return ma.Schema.TYPE_MAPPING + + def fields_for_model( + self, + model, + *, + include_fk=False, + include_relationships=False, + fields=None, + exclude=None, + base_fields=None, + dict_cls=dict, + + +## ... source file continues with no further mysql examples... + +``` + + +## Example 2 from sqlalchemy-datatables +[sqlalchemy-datatables](https://github.com/Pegase745/sqlalchemy-datatables) +([PyPI package information](https://pypi.org/project/sqlalchemy-datatables/)) +is a helper library that makes it easier to use [SQLAlchemy](/sqlalchemy.html) +with the jQuery [JavaScript](/javascript.html) +[DataTables](https://datatables.net/) plugin. This library is designed to +be [web framework](/web-frameworks.html) agnostic and provides code examples +for both [Flask](/flask.html) and [Pyramid](/pyramid.html). + +The project is built and maintained by +[Michel Nemnom (Pegase745)](https://github.com/Pegase745) and is open +sourced under the +[MIT license](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/LICENSE). + +[**sqlalchemy-datatables / datatables / datatables.py**](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/./datatables/datatables.py) + +```python +# datatables.py +from __future__ import absolute_import + +import math + +from sqlalchemy import Text, func, or_ +~~from sqlalchemy.dialects import mysql, postgresql, sqlite + +from datatables.clean_regex import clean_regex +from datatables.search_methods import SEARCH_METHODS + + +class DataTables: + + def __init__(self, request, query, columns, allow_regex_searches=False): + self.params = dict(request) + if 'sEcho' in self.params: + raise ValueError( + 'Legacy datatables not supported, upgrade to >=1.10') + self.query = query + self.columns = columns + self.results = None + self.allow_regex_searches = allow_regex_searches + + self.cardinality_filtered = 0 + + self.cardinality = 0 + + self.yadcf_params = [] + self.filter_expressions = [] + self.error = None + + +## ... source file abbreviated to get to mysql examples ... + + + direction = self.params.get('order[{:d}][dir]'.format(i)) + sort_expr = column.sqla_expr + if direction == 'asc': + sort_expr = sort_expr.asc() + elif direction == 'desc': + sort_expr = sort_expr.desc() + else: + raise ValueError( + 'Invalid order direction: {}'.format(direction)) + if column.nulls_order: + if column.nulls_order == 'nullsfirst': + sort_expr = sort_expr.nullsfirst() + elif column.nulls_order == 'nullslast': + sort_expr = sort_expr.nullslast() + else: + raise ValueError( + 'Invalid order direction: {}'.format(direction)) + + sort_expressions.append(sort_expr) + i += 1 + self.sort_expressions = sort_expressions + + def _get_regex_operator(self): + if isinstance(self.query.session.bind.dialect, postgresql.dialect): + return '-' +~~ elif isinstance(self.query.session.bind.dialect, mysql.dialect): + return 'REGEXP' + elif isinstance(self.query.session.bind.dialect, sqlite.dialect): + return 'REGEXP' + else: + raise NotImplementedError( + 'Regex searches are not implemented for this dialect') + + + +## ... source file continues with no further mysql examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-oracle.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-oracle.markdown new file mode 100644 index 000000000..9786f3422 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-oracle.markdown @@ -0,0 +1,125 @@ +title: sqlalchemy.dialects oracle Example Code +category: page +slug: sqlalchemy-dialects-oracle-examples +sortorder: 500031003 +toc: False +sidebartitle: sqlalchemy.dialects oracle +meta: Python example code that shows how to use the oracle callable from the sqlalchemy.dialects module of the SQLAlchemy project. + + +`oracle` is a callable within the `sqlalchemy.dialects` module of the SQLAlchemy project. + +mssql, +mysql, +postgresql, +and sqlite +are several other callables with code examples from the same `sqlalchemy.dialects` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / types / password.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/types/password.py) + +```python +# password.py +import weakref + +import six +from sqlalchemy import types +~~from sqlalchemy.dialects import oracle, postgresql, sqlite +from sqlalchemy.ext.mutable import Mutable + +from ..exceptions import ImproperlyConfigured +from .scalar_coercible import ScalarCoercible + +passlib = None +try: + import passlib + from passlib.context import LazyCryptContext +except ImportError: + pass + + +class Password(Mutable, object): + + @classmethod + def coerce(cls, key, value): + if isinstance(value, Password): + return value + + if isinstance(value, (six.string_types, six.binary_type)): + return cls(value, secret=True) + + super(Password, cls).coerce(key, value) + + +## ... source file abbreviated to get to oracle examples ... + + + if self._max_length is None: + self._max_length = self.calculate_max_length() + + return self._max_length + + def calculate_max_length(self): + max_lengths = [1024] + for name in self.context.schemes(): + scheme = getattr(__import__('passlib.hash').hash, name) + length = 4 + len(scheme.name) + length += len(str(getattr(scheme, 'max_rounds', ''))) + length += (getattr(scheme, 'max_salt_size', 0) or 0) + length += getattr( + scheme, + 'encoded_checksum_size', + scheme.checksum_size + ) + max_lengths.append(length) + + return max(max_lengths) + + def load_dialect_impl(self, dialect): + if dialect.name == 'postgresql': + impl = postgresql.BYTEA(self.length) + elif dialect.name == 'oracle': +~~ impl = oracle.RAW(self.length) + elif dialect.name == 'sqlite': + impl = sqlite.BLOB(self.length) + else: + impl = types.VARBINARY(self.length) + return dialect.type_descriptor(impl) + + def process_bind_param(self, value, dialect): + if isinstance(value, Password): + if value.secret is not None: + return self._hash(value.secret).encode('utf8') + + return value.hash + + if isinstance(value, six.string_types): + return self._hash(value).encode('utf8') + + def process_result_value(self, value, dialect): + if value is not None: + return Password(value, self.context) + + def _hash(self, value): + return getattr(self.context, self.hashing_method)(value) + + def _coerce(self, value): + + +## ... source file continues with no further oracle examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-array.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-array.markdown new file mode 100644 index 000000000..1772e23a0 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-array.markdown @@ -0,0 +1,278 @@ +title: sqlalchemy.dialects.postgresql ARRAY Example Code +category: page +slug: sqlalchemy-dialects-postgresql-array-examples +sortorder: 500031007 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql ARRAY +meta: Python example code that shows how to use the ARRAY constant from the sqlalchemy.dialects.postgresql module of the SQLAlchemy project. + + +`ARRAY` is a constant within the `sqlalchemy.dialects.postgresql` module of the SQLAlchemy project. + +BIGINT, +BIT, +DOUBLE_PRECISION, +ExcludeConstraint, +INTEGER, +JSON, +TSVECTOR, +array, +json, +and pypostgresql +are several other callables with code examples from the same `sqlalchemy.dialects.postgresql` package. + +## Example 1 from sqlacodegen +[sqlacodegen](https://github.com/agronholm/sqlacodegen) +([PyPI package information](https://pypi.org/project/sqlacodegen/)) +is a tool for +reading from an existing [relational database](/databases.html) to +generate code to create [SQLAlchemy](/sqlalchemy.html) models based +on that database. The project is primarily written and maintained +by [Alex Grönholm (agronholm)](https://github.com/agronholm) and it +is open sourced under the +[MIT license](https://github.com/agronholm/sqlacodegen/blob/master/LICENSE). + +[**sqlacodegen / sqlacodegen / codegen.py**](https://github.com/agronholm/sqlacodegen/blob/master/sqlacodegen/./codegen.py) + +```python +# codegen.py +from __future__ import unicode_literals, division, print_function, absolute_import + +import inspect +import re +import sys +from collections import defaultdict +from importlib import import_module +from inspect import ArgSpec +from keyword import iskeyword + +import sqlalchemy +import sqlalchemy.exc +from sqlalchemy import ( + Enum, ForeignKeyConstraint, PrimaryKeyConstraint, CheckConstraint, UniqueConstraint, Table, + Column, Float) +from sqlalchemy.schema import ForeignKey +from sqlalchemy.sql.sqltypes import NullType +from sqlalchemy.types import Boolean, String +from sqlalchemy.util import OrderedDict + +try: + from sqlalchemy import ARRAY +except ImportError: +~~ from sqlalchemy.dialects.postgresql import ARRAY + +try: + from sqlalchemy import Computed +except ImportError: + Computed = None + +try: + import geoalchemy2 # noqa: F401 +except ImportError: + pass + +_re_boolean_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \(0, 1\)") +_re_column_name = re.compile(r'(?:(["`]?)(?:.*)\1\.)?(["`]?)(.*)\2') +_re_enum_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \((.+)\)") +_re_enum_item = re.compile(r"'(.*?)(? 1: + collector.add_literal_import('sqlalchemy', 'ForeignKeyConstraint') + else: + collector.add_literal_import('sqlalchemy', 'ForeignKey') + elif isinstance(constraint, UniqueConstraint): + if len(constraint.columns) > 1: + collector.add_literal_import('sqlalchemy', 'UniqueConstraint') + elif not isinstance(constraint, PrimaryKeyConstraint): + collector.add_import(constraint) + + for index in self.table.indexes: + if len(index.columns) > 1: + collector.add_import(index) + + @staticmethod + def _convert_to_valid_identifier(name): + assert name, 'Identifier cannot be empty' + if name[0].isdigit() or iskeyword(name): + name = '_' + name + elif name == 'metadata': + + +## ... source file continues with no further ARRAY examples... + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / asserts.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./asserts.py) + +```python +# asserts.py +from decimal import Decimal + +import sqlalchemy as sa +~~from sqlalchemy.dialects.postgresql import ARRAY +from sqlalchemy.exc import DataError, IntegrityError + + +def _update_field(obj, field, value): + session = sa.orm.object_session(obj) + column = sa.inspect(obj.__class__).columns[field] + query = column.table.update().values(**{column.key: value}) + session.execute(query) + session.flush() + + +def _expect_successful_update(obj, field, value, reraise_exc): + try: + _update_field(obj, field, value) + except (reraise_exc) as e: + session = sa.orm.object_session(obj) + session.rollback() + assert False, str(e) + + +def _expect_failing_update(obj, field, value, expected_exc): + try: + _update_field(obj, field, value) + except expected_exc: + pass + else: + raise AssertionError('Expected update to raise %s' % expected_exc) + finally: + session = sa.orm.object_session(obj) + session.rollback() + + +def _repeated_value(type_): +~~ if isinstance(type_, ARRAY): + if isinstance(type_.item_type, sa.Integer): + return [0] + elif isinstance(type_.item_type, sa.String): + return [u'a'] + elif isinstance(type_.item_type, sa.Numeric): + return [Decimal('0')] + else: + raise TypeError('Unknown array item type') + else: + return u'a' + + +def _expected_exception(type_): +~~ if isinstance(type_, ARRAY): + return IntegrityError + else: + return DataError + + +def assert_nullable(obj, column): + _expect_successful_update(obj, column, None, IntegrityError) + + +def assert_non_nullable(obj, column): + _expect_failing_update(obj, column, None, IntegrityError) + + +def assert_max_length(obj, column, max_length): + type_ = sa.inspect(obj.__class__).columns[column].type + _expect_successful_update( + obj, + column, + _repeated_value(type_) * max_length, + _expected_exception(type_) + ) + _expect_failing_update( + obj, + column, + + +## ... source file continues with no further ARRAY examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-base-pgcompiler.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-base-pgcompiler.markdown new file mode 100644 index 000000000..5d36ff625 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-base-pgcompiler.markdown @@ -0,0 +1,114 @@ +title: sqlalchemy.dialects.postgresql.base PGCompiler Example Code +category: page +slug: sqlalchemy-dialects-postgresql-base-pgcompiler-examples +sortorder: 500031016 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql.base PGCompiler +meta: Example code for understanding how to use the PGCompiler class from the sqlalchemy.dialects.postgresql.base module of the SQLAlchemy project. + + +`PGCompiler` is a class within the `sqlalchemy.dialects.postgresql.base` module of the SQLAlchemy project. + +PGIdentifierPreparer +and +PGTypeCompiler +are a couple of other callables within the `sqlalchemy.dialects.postgresql.base` package that also have code examples. + +## Example 1 from sqlalchemy-clickhouse +[sqlalchemy-clickhouse](https://github.com/cloudflare/sqlalchemy-clickhouse) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +for communicating with the open source [ClickHouse](https://clickhouse.tech/) +database management system. ClickHouse is column-oriented and therefore +better for some use cases and worse for others compared to a traditional +[relational database](/databases.html). + +The code for this project is open sourced under the +[MIT license](https://github.com/cloudflare/sqlalchemy-clickhouse/blob/master/LICENSE.txt) +while ClickHouse is provided as open source under the +[Apache License 2.0](https://github.com/ClickHouse/ClickHouse/blob/master/LICENSE). + +[**sqlalchemy-clickhouse / base.py**](https://github.com/cloudflare/sqlalchemy-clickhouse/blob/master/././base.py) + +```python +# base.py + +import re + +import sqlalchemy.types as sqltypes +from sqlalchemy import exc as sa_exc +from sqlalchemy import util as sa_util +from sqlalchemy.engine import default, reflection +from sqlalchemy.sql import compiler, expression +from sqlalchemy.sql.elements import quoted_name +~~from sqlalchemy.dialects.postgresql.base import PGCompiler, PGIdentifierPreparer +from sqlalchemy.types import ( + CHAR, DATE, DATETIME, INTEGER, SMALLINT, BIGINT, DECIMAL, TIME, + TIMESTAMP, VARCHAR, BINARY, BOOLEAN, FLOAT, REAL) + +VERSION = (0, 1, 0, None) + +colspecs = {} + +class ARRAY(sqltypes.TypeEngine): + __visit_name__ = 'ARRAY' + +ischema_names = { + 'Int64': INTEGER, + 'Int32': INTEGER, + 'Int16': INTEGER, + 'Int8': INTEGER, + 'UInt64': INTEGER, + 'UInt32': INTEGER, + 'UInt16': INTEGER, + 'UInt8': INTEGER, + 'Date': DATE, + 'DateTime': DATETIME, + 'Float64': FLOAT, + 'Float32': FLOAT, + 'String': VARCHAR, + 'FixedString': VARCHAR, + 'Enum': VARCHAR, + 'Enum8': VARCHAR, + 'Enum16': VARCHAR, + 'Array': ARRAY, +} + +class ClickHouseIdentifierPreparer(PGIdentifierPreparer): + def quote_identifier(self, value): + return self._escape_identifier(value) + def quote(self, ident, force=None): + if self._requires_quotes(ident): + return '"{}"'.format(ident) + return ident + +~~class ClickHouseCompiler(PGCompiler): + def visit_count_func(self, fn, **kw): + return 'count{0}'.format(self.process(fn.clause_expr, **kw)) + + def visit_random_func(self, fn, **kw): + return 'rand()' + + def visit_now_func(self, fn, **kw): + return 'now()' + + def visit_current_date_func(self, fn, **kw): + return 'today()' + + def visit_true(self, element, **kw): + return '1' + + def visit_false(self, element, **kw): + return '0' + + def visit_cast(self, cast, **kwargs): + if self.dialect.supports_cast: + return super(ClickHouseCompiler, self).visit_cast(cast, **kwargs) + else: + return self.process(cast.clause, **kwargs) + + + +## ... source file continues with no further PGCompiler examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-base-pgidentifierpreparer.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-base-pgidentifierpreparer.markdown new file mode 100644 index 000000000..80d538b96 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-base-pgidentifierpreparer.markdown @@ -0,0 +1,106 @@ +title: sqlalchemy.dialects.postgresql.base PGIdentifierPreparer Example Code +category: page +slug: sqlalchemy-dialects-postgresql-base-pgidentifierpreparer-examples +sortorder: 500031017 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql.base PGIdentifierPreparer +meta: Example code for understanding how to use the PGIdentifierPreparer class from the sqlalchemy.dialects.postgresql.base module of the SQLAlchemy project. + + +`PGIdentifierPreparer` is a class within the `sqlalchemy.dialects.postgresql.base` module of the SQLAlchemy project. + +PGCompiler +and +PGTypeCompiler +are a couple of other callables within the `sqlalchemy.dialects.postgresql.base` package that also have code examples. + +## Example 1 from sqlalchemy-clickhouse +[sqlalchemy-clickhouse](https://github.com/cloudflare/sqlalchemy-clickhouse) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +for communicating with the open source [ClickHouse](https://clickhouse.tech/) +database management system. ClickHouse is column-oriented and therefore +better for some use cases and worse for others compared to a traditional +[relational database](/databases.html). + +The code for this project is open sourced under the +[MIT license](https://github.com/cloudflare/sqlalchemy-clickhouse/blob/master/LICENSE.txt) +while ClickHouse is provided as open source under the +[Apache License 2.0](https://github.com/ClickHouse/ClickHouse/blob/master/LICENSE). + +[**sqlalchemy-clickhouse / base.py**](https://github.com/cloudflare/sqlalchemy-clickhouse/blob/master/././base.py) + +```python +# base.py + +import re + +import sqlalchemy.types as sqltypes +from sqlalchemy import exc as sa_exc +from sqlalchemy import util as sa_util +from sqlalchemy.engine import default, reflection +from sqlalchemy.sql import compiler, expression +from sqlalchemy.sql.elements import quoted_name +~~from sqlalchemy.dialects.postgresql.base import PGCompiler, PGIdentifierPreparer +from sqlalchemy.types import ( + CHAR, DATE, DATETIME, INTEGER, SMALLINT, BIGINT, DECIMAL, TIME, + TIMESTAMP, VARCHAR, BINARY, BOOLEAN, FLOAT, REAL) + +VERSION = (0, 1, 0, None) + +colspecs = {} + +class ARRAY(sqltypes.TypeEngine): + __visit_name__ = 'ARRAY' + +ischema_names = { + 'Int64': INTEGER, + 'Int32': INTEGER, + 'Int16': INTEGER, + 'Int8': INTEGER, + 'UInt64': INTEGER, + 'UInt32': INTEGER, + 'UInt16': INTEGER, + 'UInt8': INTEGER, + 'Date': DATE, + 'DateTime': DATETIME, + 'Float64': FLOAT, + 'Float32': FLOAT, + 'String': VARCHAR, + 'FixedString': VARCHAR, + 'Enum': VARCHAR, + 'Enum8': VARCHAR, + 'Enum16': VARCHAR, + 'Array': ARRAY, +} + +~~class ClickHouseIdentifierPreparer(PGIdentifierPreparer): + def quote_identifier(self, value): + return self._escape_identifier(value) + def quote(self, ident, force=None): + if self._requires_quotes(ident): + return '"{}"'.format(ident) + return ident + +class ClickHouseCompiler(PGCompiler): + def visit_count_func(self, fn, **kw): + return 'count{0}'.format(self.process(fn.clause_expr, **kw)) + + def visit_random_func(self, fn, **kw): + return 'rand()' + + def visit_now_func(self, fn, **kw): + return 'now()' + + def visit_current_date_func(self, fn, **kw): + return 'today()' + + def visit_true(self, element, **kw): + return '1' + + def visit_false(self, element, **kw): + + +## ... source file continues with no further PGIdentifierPreparer examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-base-pgtypecompiler.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-base-pgtypecompiler.markdown new file mode 100644 index 000000000..406989729 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-base-pgtypecompiler.markdown @@ -0,0 +1,69 @@ +title: sqlalchemy.dialects.postgresql.base PGTypeCompiler Example Code +category: page +slug: sqlalchemy-dialects-postgresql-base-pgtypecompiler-examples +sortorder: 500031018 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql.base PGTypeCompiler +meta: Example code for understanding how to use the PGTypeCompiler class from the sqlalchemy.dialects.postgresql.base module of the SQLAlchemy project. + + +`PGTypeCompiler` is a class within the `sqlalchemy.dialects.postgresql.base` module of the SQLAlchemy project. + +PGCompiler +and +PGIdentifierPreparer +are a couple of other callables within the `sqlalchemy.dialects.postgresql.base` package that also have code examples. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / types / ltree.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/types/ltree.py) + +```python +# ltree.py +from __future__ import absolute_import + +from sqlalchemy import types +from sqlalchemy.dialects.postgresql import ARRAY +~~from sqlalchemy.dialects.postgresql.base import ischema_names, PGTypeCompiler +from sqlalchemy.sql import expression + +from ..primitives import Ltree +from .scalar_coercible import ScalarCoercible + + +class LtreeType(types.Concatenable, types.UserDefinedType, ScalarCoercible): + + class comparator_factory(types.Concatenable.Comparator): + def ancestor_of(self, other): + if isinstance(other, list): + return self.op('@>')(expression.cast(other, ARRAY(LtreeType))) + else: + return self.op('@>')(other) + + def descendant_of(self, other): + if isinstance(other, list): + return self.op('<@')(expression.cast(other, ARRAY(LtreeType))) + else: + return self.op('<@')(other) + + def lquery(self, other): + if isinstance(other, list): + return self.op('?')(expression.cast(other, ARRAY(LQUERY))) + + +## ... source file continues with no further PGTypeCompiler examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-bigint.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-bigint.markdown new file mode 100644 index 000000000..58ca37105 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-bigint.markdown @@ -0,0 +1,73 @@ +title: sqlalchemy.dialects.postgresql BIGINT Example Code +category: page +slug: sqlalchemy-dialects-postgresql-bigint-examples +sortorder: 500031008 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql BIGINT +meta: Python example code that shows how to use the BIGINT constant from the sqlalchemy.dialects.postgresql module of the SQLAlchemy project. + + +`BIGINT` is a constant within the `sqlalchemy.dialects.postgresql` module of the SQLAlchemy project. + +ARRAY, +BIT, +DOUBLE_PRECISION, +ExcludeConstraint, +INTEGER, +JSON, +TSVECTOR, +array, +json, +and pypostgresql +are several other callables with code examples from the same `sqlalchemy.dialects.postgresql` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / postgresql.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/postgresql.py) + +```python +# postgresql.py +import logging +import re + +from sqlalchemy import Column +from sqlalchemy import Numeric +from sqlalchemy import text +from sqlalchemy import types as sqltypes +~~from sqlalchemy.dialects.postgresql import BIGINT +from sqlalchemy.dialects.postgresql import ExcludeConstraint +from sqlalchemy.dialects.postgresql import INTEGER +from sqlalchemy.sql.expression import ColumnClause +from sqlalchemy.sql.expression import UnaryExpression +from sqlalchemy.types import NULLTYPE + +from .base import alter_column +from .base import alter_table +from .base import AlterColumn +from .base import ColumnComment +from .base import compiles +from .base import format_column_name +from .base import format_table_name +from .base import format_type +from .base import RenameTable +from .impl import DefaultImpl +from .. import util +from ..autogenerate import render +from ..operations import ops +from ..operations import schemaobj +from ..operations.base import BatchOperations +from ..operations.base import Operations +from ..util import compat +from ..util import sqla_compat + + +## ... source file continues with no further BIGINT examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-bit.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-bit.markdown new file mode 100644 index 000000000..b8181d37b --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-bit.markdown @@ -0,0 +1,66 @@ +title: sqlalchemy.dialects.postgresql BIT Example Code +category: page +slug: sqlalchemy-dialects-postgresql-bit-examples +sortorder: 500031009 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql BIT +meta: Python example code that shows how to use the BIT constant from the sqlalchemy.dialects.postgresql module of the SQLAlchemy project. + + +`BIT` is a constant within the `sqlalchemy.dialects.postgresql` module of the SQLAlchemy project. + +ARRAY, +BIGINT, +DOUBLE_PRECISION, +ExcludeConstraint, +INTEGER, +JSON, +TSVECTOR, +array, +json, +and pypostgresql +are several other callables with code examples from the same `sqlalchemy.dialects.postgresql` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / types / bit.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/types/bit.py) + +```python +# bit.py +import sqlalchemy as sa +~~from sqlalchemy.dialects.postgresql import BIT + + +class BitType(sa.types.TypeDecorator): + impl = sa.types.BINARY + + def __init__(self, length=1, **kwargs): + self.length = length + sa.types.TypeDecorator.__init__(self, **kwargs) + + def load_dialect_impl(self, dialect): + if dialect.name == 'postgresql': + return dialect.type_descriptor(BIT(self.length)) + elif dialect.name == 'sqlite': + return dialect.type_descriptor(sa.String(self.length)) + else: + return dialect.type_descriptor(type(self.impl)(self.length)) + + + +## ... source file continues with no further BIT examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-double-precision.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-double-precision.markdown new file mode 100644 index 000000000..ce7288b95 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-double-precision.markdown @@ -0,0 +1,136 @@ +title: sqlalchemy.dialects.postgresql DOUBLE_PRECISION Example Code +category: page +slug: sqlalchemy-dialects-postgresql-double-precision-examples +sortorder: 500031010 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql DOUBLE_PRECISION +meta: Python example code that shows how to use the DOUBLE_PRECISION constant from the sqlalchemy.dialects.postgresql module of the SQLAlchemy project. + + +`DOUBLE_PRECISION` is a constant within the `sqlalchemy.dialects.postgresql` module of the SQLAlchemy project. + +ARRAY, +BIGINT, +BIT, +ExcludeConstraint, +INTEGER, +JSON, +TSVECTOR, +array, +json, +and pypostgresql +are several other callables with code examples from the same `sqlalchemy.dialects.postgresql` package. + +## Example 1 from Amazon Redshift SQLAlchemy Dialect +[Amazon Redshift SQLAlchemy Dialect](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +that can communicate with the [AWS Redshift](https://aws.amazon.com/redshift/) +data store. The SQL is essentially [PostgreSQL](/postgresql.html) +and requires [psycopg2](https://www.psycopg.org/) to properly +operate. This project and its code are open sourced under the +[MIT license](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/LICENSE). + +[**Amazon Redshift SQLAlchemy Dialect / sqlalchemy_redshift / dialect.py**](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/sqlalchemy_redshift/./dialect.py) + +```python +# dialect.py +import re +from collections import defaultdict, namedtuple + +from packaging.version import Version +import pkg_resources +import sqlalchemy as sa +from sqlalchemy import inspect +from sqlalchemy.dialects.postgresql.base import ( + PGCompiler, PGDDLCompiler, PGIdentifierPreparer, PGTypeCompiler +) +from sqlalchemy.dialects.postgresql.psycopg2 import PGDialect_psycopg2 +from sqlalchemy.engine import reflection +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.sql.expression import ( + BinaryExpression, BooleanClauseList, Delete +) +from sqlalchemy.types import ( + VARCHAR, NullType, SMALLINT, INTEGER, BIGINT, + DECIMAL, REAL, BOOLEAN, CHAR, DATE, TIMESTAMP) +~~from sqlalchemy.dialects.postgresql import DOUBLE_PRECISION + +from .commands import ( + CopyCommand, UnloadFromSelect, Format, Compression, Encoding, + CreateLibraryCommand, AlterTableAppendCommand, RefreshMaterializedView +) +from .ddl import ( + CreateMaterializedView, DropMaterializedView, get_table_attributes +) + +sa_version = Version(sa.__version__) + +try: + import alembic +except ImportError: + pass +else: + from alembic.ddl import postgresql + + from alembic.ddl.base import RenameTable + compiles(RenameTable, 'redshift')(postgresql.visit_rename_table) + + if Version(alembic.__version__) >= Version('1.0.6'): + from alembic.ddl.base import ColumnComment + compiles(ColumnComment, 'redshift')(postgresql.visit_column_comment) + + +## ... source file continues with no further DOUBLE_PRECISION examples... + +``` + + +## Example 2 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / comparator.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./comparator.py) + +```python +# comparator.py + +from sqlalchemy import types as sqltypes +from sqlalchemy.types import UserDefinedType +~~from sqlalchemy.dialects.postgresql import DOUBLE_PRECISION +from sqlalchemy.sql import operators +try: + from sqlalchemy.sql.functions import _FunctionGenerator +except ImportError: # SQLA < 0.9 # pragma: no cover + from sqlalchemy.sql.expression import _FunctionGenerator + + +INTERSECTS = operators.custom_op('&&') +OVERLAPS_OR_TO_LEFT = operators.custom_op('&<') +OVERLAPS_OR_TO_RIGHT = operators.custom_op('&>') +OVERLAPS_OR_BELOW = operators.custom_op('&<|') +TO_LEFT = operators.custom_op('<<') +BELOW = operators.custom_op('<<|') +TO_RIGHT = operators.custom_op('>>') +CONTAINED = operators.custom_op('@') +OVERLAPS_OR_ABOVE = operators.custom_op('|&>') +ABOVE = operators.custom_op('|>>') +CONTAINS = operators.custom_op('-') +SAME = operators.custom_op('-=') +DISTANCE_CENTROID = operators.custom_op('<->') +DISTANCE_BOX = operators.custom_op('<#>') + + +class BaseComparator(UserDefinedType.Comparator): + + +## ... source file continues with no further DOUBLE_PRECISION examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-excludeconstraint.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-excludeconstraint.markdown new file mode 100644 index 000000000..89b02571f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-excludeconstraint.markdown @@ -0,0 +1,161 @@ +title: sqlalchemy.dialects.postgresql ExcludeConstraint Example Code +category: page +slug: sqlalchemy-dialects-postgresql-excludeconstraint-examples +sortorder: 500031011 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql ExcludeConstraint +meta: Example code for understanding how to use the ExcludeConstraint class from the sqlalchemy.dialects.postgresql module of the SQLAlchemy project. + + +`ExcludeConstraint` is a class within the `sqlalchemy.dialects.postgresql` module of the SQLAlchemy project. + +ARRAY, +BIGINT, +BIT, +DOUBLE_PRECISION, +INTEGER, +JSON, +TSVECTOR, +array, +json, +and pypostgresql +are several other callables with code examples from the same `sqlalchemy.dialects.postgresql` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / postgresql.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/postgresql.py) + +```python +# postgresql.py +import logging +import re + +from sqlalchemy import Column +from sqlalchemy import Numeric +from sqlalchemy import text +from sqlalchemy import types as sqltypes +from sqlalchemy.dialects.postgresql import BIGINT +~~from sqlalchemy.dialects.postgresql import ExcludeConstraint +from sqlalchemy.dialects.postgresql import INTEGER +from sqlalchemy.sql.expression import ColumnClause +from sqlalchemy.sql.expression import UnaryExpression +from sqlalchemy.types import NULLTYPE + +from .base import alter_column +from .base import alter_table +from .base import AlterColumn +from .base import ColumnComment +from .base import compiles +from .base import format_column_name +from .base import format_table_name +from .base import format_type +from .base import RenameTable +from .impl import DefaultImpl +from .. import util +from ..autogenerate import render +from ..operations import ops +from ..operations import schemaobj +from ..operations.base import BatchOperations +from ..operations.base import Operations +from ..util import compat +from ..util import sqla_compat + + + +## ... source file abbreviated to get to ExcludeConstraint examples ... + + + self.schema = schema + self._orig_constraint = _orig_constraint + self.kw = kw + + @classmethod + def from_constraint(cls, constraint): + constraint_table = sqla_compat._table_for_constraint(constraint) + + return cls( + constraint.name, + constraint_table.name, + [(expr, op) for expr, name, op in constraint._render_exprs], + where=constraint.where, + schema=constraint_table.schema, + _orig_constraint=constraint, + deferrable=constraint.deferrable, + initially=constraint.initially, + using=constraint.using, + ) + + def to_constraint(self, migration_context=None): + if self._orig_constraint is not None: + return self._orig_constraint + schema_obj = schemaobj.SchemaObjects(migration_context) + t = schema_obj.table(self.table_name, schema=self.schema) +~~ excl = ExcludeConstraint( + *self.elements, + name=self.constraint_name, + where=self.where, + **self.kw + ) + for expr, name, oper in excl._render_exprs: + t.append_column(Column(name, NULLTYPE)) + t.append_constraint(excl) + return excl + + @classmethod + def create_exclude_constraint( + cls, operations, constraint_name, table_name, *elements, **kw + ): + op = cls(constraint_name, table_name, elements, **kw) + return operations.invoke(op) + + @classmethod + def batch_create_exclude_constraint( + cls, operations, constraint_name, *elements, **kw + ): + kw["schema"] = operations.impl.schema + op = cls(constraint_name, operations.impl.table_name, elements, **kw) + return operations.invoke(op) + + +@render.renderers.dispatch_for(CreateExcludeConstraintOp) +def _add_exclude_constraint(autogen_context, op): + return _exclude_constraint(op.to_constraint(), autogen_context, alter=True) + + +~~@render._constraint_renderers.dispatch_for(ExcludeConstraint) +def _render_inline_exclude_constraint(constraint, autogen_context): + rendered = render._user_defined_render( + "exclude", constraint, autogen_context + ) + if rendered is not False: + return rendered + + return _exclude_constraint(constraint, autogen_context, False) + + +def _postgresql_autogenerate_prefix(autogen_context): + + imports = autogen_context.imports + if imports is not None: + imports.add("from sqlalchemy.dialects import postgresql") + return "postgresql." + + +def _exclude_constraint(constraint, autogen_context, alter): + opts = [] + + has_batch = autogen_context._has_batch + + if constraint.deferrable: + + +## ... source file continues with no further ExcludeConstraint examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-integer.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-integer.markdown new file mode 100644 index 000000000..0f16bc6c3 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-integer.markdown @@ -0,0 +1,130 @@ +title: sqlalchemy.dialects.postgresql INTEGER Example Code +category: page +slug: sqlalchemy-dialects-postgresql-integer-examples +sortorder: 500031012 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql INTEGER +meta: Python example code that shows how to use the INTEGER constant from the sqlalchemy.dialects.postgresql module of the SQLAlchemy project. + + +`INTEGER` is a constant within the `sqlalchemy.dialects.postgresql` module of the SQLAlchemy project. + +ARRAY, +BIGINT, +BIT, +DOUBLE_PRECISION, +ExcludeConstraint, +JSON, +TSVECTOR, +array, +json, +and pypostgresql +are several other callables with code examples from the same `sqlalchemy.dialects.postgresql` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / postgresql.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/postgresql.py) + +```python +# postgresql.py +import logging +import re + +from sqlalchemy import Column +from sqlalchemy import Numeric +from sqlalchemy import text +from sqlalchemy import types as sqltypes +from sqlalchemy.dialects.postgresql import BIGINT +from sqlalchemy.dialects.postgresql import ExcludeConstraint +~~from sqlalchemy.dialects.postgresql import INTEGER +from sqlalchemy.sql.expression import ColumnClause +from sqlalchemy.sql.expression import UnaryExpression +from sqlalchemy.types import NULLTYPE + +from .base import alter_column +from .base import alter_table +from .base import AlterColumn +from .base import ColumnComment +from .base import compiles +from .base import format_column_name +from .base import format_table_name +from .base import format_type +from .base import RenameTable +from .impl import DefaultImpl +from .. import util +from ..autogenerate import render +from ..operations import ops +from ..operations import schemaobj +from ..operations.base import BatchOperations +from ..operations.base import Operations +from ..util import compat +from ..util import sqla_compat + + + + +## ... source file abbreviated to get to INTEGER examples ... + + + schema=schema, + using=using, + existing_type=existing_type, + existing_server_default=existing_server_default, + existing_nullable=existing_nullable, + ) + ) + + super(PostgresqlImpl, self).alter_column( + table_name, + column_name, + nullable=nullable, + server_default=server_default, + name=name, + schema=schema, + autoincrement=autoincrement, + existing_type=existing_type, + existing_server_default=existing_server_default, + existing_nullable=existing_nullable, + existing_autoincrement=existing_autoincrement, + **kw + ) + + def autogen_column_reflect(self, inspector, table, column_info): + if column_info.get("default") and isinstance( +~~ column_info["type"], (INTEGER, BIGINT) + ): + seq_match = re.match( + r"nextval\('(.+?)'::regclass\)", column_info["default"] + ) + if seq_match: + info = sqla_compat._exec_on_inspector( + inspector, + text( + "select c.relname, a.attname " + "from pg_class as c join " + "pg_depend d on d.objid=c.oid and " + "d.classid='pg_class'::regclass and " + "d.refclassid='pg_class'::regclass " + "join pg_class t on t.oid=d.refobjid " + "join pg_attribute a on a.attrelid=t.oid and " + "a.attnum=d.refobjsubid " + "where c.relkind='S' and c.relname=:seqname" + ), + seqname=seq_match.group(1), + ).first() + if info: + seqname, colname = info + if colname == column_info["name"]: + log.info( + + +## ... source file continues with no further INTEGER examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-json.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-json.markdown new file mode 100644 index 000000000..e171fe189 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-json.markdown @@ -0,0 +1,87 @@ +title: sqlalchemy.dialects.postgresql JSON Example Code +category: page +slug: sqlalchemy-dialects-postgresql-json-examples +sortorder: 500031013 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql JSON +meta: Python example code that shows how to use the JSON constant from the sqlalchemy.dialects.postgresql module of the SQLAlchemy project. + + +`JSON` is a constant within the `sqlalchemy.dialects.postgresql` module of the SQLAlchemy project. + +ARRAY, +BIGINT, +BIT, +DOUBLE_PRECISION, +ExcludeConstraint, +INTEGER, +TSVECTOR, +array, +json, +and pypostgresql +are several other callables with code examples from the same `sqlalchemy.dialects.postgresql` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / types / json.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/types/json.py) + +```python +# json.py +from __future__ import absolute_import + +import six +import sqlalchemy as sa +from sqlalchemy.dialects.postgresql.base import ischema_names + +from ..exceptions import ImproperlyConfigured + +json = None +try: + import anyjson as json +except ImportError: + import json as json + +try: +~~ from sqlalchemy.dialects.postgresql import JSON + has_postgres_json = True +except ImportError: + class PostgresJSONType(sa.types.UserDefinedType): + def get_col_spec(self): + return 'json' + + ischema_names['json'] = PostgresJSONType + has_postgres_json = False + + +class JSONType(sa.types.TypeDecorator): + impl = sa.UnicodeText + + def __init__(self, *args, **kwargs): + if json is None: + raise ImproperlyConfigured( + 'JSONType needs anyjson package installed.' + ) + super(JSONType, self).__init__(*args, **kwargs) + + def load_dialect_impl(self, dialect): + if dialect.name == 'postgresql': + if has_postgres_json: + return dialect.type_descriptor(JSON()) + + +## ... source file continues with no further JSON examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-psycopg2-pgdialect-psycopg2.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-psycopg2-pgdialect-psycopg2.markdown new file mode 100644 index 000000000..c7b88b433 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-psycopg2-pgdialect-psycopg2.markdown @@ -0,0 +1,257 @@ +title: sqlalchemy.dialects.postgresql.psycopg2 PGDialect_psycopg2 Example Code +category: page +slug: sqlalchemy-dialects-postgresql-psycopg2-pgdialect-psycopg2-examples +sortorder: 500031019 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql.psycopg2 PGDialect_psycopg2 +meta: Example code for understanding how to use the PGDialect_psycopg2 class from the sqlalchemy.dialects.postgresql.psycopg2 module of the SQLAlchemy project. + + +`PGDialect_psycopg2` is a class within the `sqlalchemy.dialects.postgresql.psycopg2` module of the SQLAlchemy project. + + + +## Example 1 from Amazon Redshift SQLAlchemy Dialect +[Amazon Redshift SQLAlchemy Dialect](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +that can communicate with the [AWS Redshift](https://aws.amazon.com/redshift/) +data store. The SQL is essentially [PostgreSQL](/postgresql.html) +and requires [psycopg2](https://www.psycopg.org/) to properly +operate. This project and its code are open sourced under the +[MIT license](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/LICENSE). + +[**Amazon Redshift SQLAlchemy Dialect / sqlalchemy_redshift / dialect.py**](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/sqlalchemy_redshift/./dialect.py) + +```python +# dialect.py +import re +from collections import defaultdict, namedtuple + +from packaging.version import Version +import pkg_resources +import sqlalchemy as sa +from sqlalchemy import inspect +from sqlalchemy.dialects.postgresql.base import ( + PGCompiler, PGDDLCompiler, PGIdentifierPreparer, PGTypeCompiler +) +~~from sqlalchemy.dialects.postgresql.psycopg2 import PGDialect_psycopg2 +from sqlalchemy.engine import reflection +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.sql.expression import ( + BinaryExpression, BooleanClauseList, Delete +) +from sqlalchemy.types import ( + VARCHAR, NullType, SMALLINT, INTEGER, BIGINT, + DECIMAL, REAL, BOOLEAN, CHAR, DATE, TIMESTAMP) +from sqlalchemy.dialects.postgresql import DOUBLE_PRECISION + +from .commands import ( + CopyCommand, UnloadFromSelect, Format, Compression, Encoding, + CreateLibraryCommand, AlterTableAppendCommand, RefreshMaterializedView +) +from .ddl import ( + CreateMaterializedView, DropMaterializedView, get_table_attributes +) + +sa_version = Version(sa.__version__) + +try: + import alembic +except ImportError: + pass + + +## ... source file continues with no further PGDialect_psycopg2 examples... + +``` + + +## Example 2 from databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + +[**databases / databases / backends / aiopg.py**](https://github.com/encode/databases/blob/master/databases/backends/aiopg.py) + +```python +# aiopg.py +import getpass +import json +import logging +import typing +import uuid + +import aiopg +from aiopg.sa.engine import APGCompiler_psycopg2 +~~from sqlalchemy.dialects.postgresql.psycopg2 import PGDialect_psycopg2 +from sqlalchemy.engine.interfaces import Dialect, ExecutionContext +from sqlalchemy.engine.result import ResultMetaData, RowProxy +from sqlalchemy.sql import ClauseElement +from sqlalchemy.types import TypeEngine + +from databases.core import DatabaseURL +from databases.interfaces import ConnectionBackend, DatabaseBackend, TransactionBackend + +logger = logging.getLogger("databases") + + +class AiopgBackend(DatabaseBackend): + def __init__( + self, database_url: typing.Union[DatabaseURL, str], **options: typing.Any + ) -> None: + self._database_url = DatabaseURL(database_url) + self._options = options + self._dialect = self._get_dialect() + self._pool = None + + def _get_dialect(self) -> Dialect: +~~ dialect = PGDialect_psycopg2( + json_serializer=json.dumps, json_deserializer=lambda x: x + ) + dialect.statement_compiler = APGCompiler_psycopg2 + dialect.implicit_returning = True + dialect.supports_native_enum = True + dialect.supports_smallserial = True # 9.2+ + dialect._backslash_escapes = False + dialect.supports_sane_multi_rowcount = True # psycopg 2.0.9+ + dialect._has_native_hstore = True + dialect.supports_native_decimal = True + + return dialect + + def _get_connection_kwargs(self) -> dict: + url_options = self._database_url.options + + kwargs = {} + min_size = url_options.get("min_size") + max_size = url_options.get("max_size") + ssl = url_options.get("ssl") + + if min_size is not None: + kwargs["minsize"] = int(min_size) + if max_size is not None: + + +## ... source file continues with no further PGDialect_psycopg2 examples... + +``` + + +## Example 3 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / types / pg_composite.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/types/pg_composite.py) + +```python +# pg_composite.py +from collections import namedtuple + +import six +import sqlalchemy as sa +from sqlalchemy.dialects.postgresql import ARRAY +~~from sqlalchemy.dialects.postgresql.psycopg2 import PGDialect_psycopg2 +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.schema import _CreateDropBase +from sqlalchemy.sql.expression import FunctionElement +from sqlalchemy.types import ( + SchemaType, + to_instance, + TypeDecorator, + UserDefinedType +) + +from .. import ImproperlyConfigured + +psycopg2 = None +CompositeCaster = None +adapt = None +AsIs = None +register_adapter = None +try: + import psycopg2 + from psycopg2.extras import CompositeCaster + from psycopg2.extensions import adapt, AsIs, register_adapter +except ImportError: + pass + + + +## ... source file abbreviated to get to PGDialect_psycopg2 examples ... + + + bind.execute(CreateCompositeType(self)) + + def drop(self, bind=None, checkfirst=True): + if ( + checkfirst and + bind.dialect.has_type(bind, self.name, schema=self.schema) + ): + bind.execute(DropCompositeType(self)) + + +def register_psycopg2_composite(dbapi_connection, composite): + psycopg2.extras.register_composite( + composite.name, + dbapi_connection, + globally=True, + factory=composite.caster + ) + + def adapt_composite(value): + adapted = [ + adapt( + getattr(value, column.name) + if not isinstance(column.type, TypeDecorator) + else column.type.process_bind_param( + getattr(value, column.name), +~~ PGDialect_psycopg2() + ) + ) + for column in + composite.columns + ] + for value in adapted: + if hasattr(value, 'prepare'): + value.prepare(dbapi_connection) + values = [ + value.getquoted().decode(dbapi_connection.encoding) + if six.PY3 + else value.getquoted() + for value in adapted + ] + return AsIs("(%s)::%s" % (', '.join(values), composite.name)) + + register_adapter(composite.type_cls, adapt_composite) + + +def before_create(target, connection, **kw): + for name, composite in registered_composites.items(): + composite.create(connection, checkfirst=True) + register_psycopg2_composite( + connection.connection.connection, + + +## ... source file continues with no further PGDialect_psycopg2 examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-pypostgresql.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-pypostgresql.markdown new file mode 100644 index 000000000..71afdb182 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-pypostgresql.markdown @@ -0,0 +1,102 @@ +title: sqlalchemy.dialects.postgresql pypostgresql Example Code +category: page +slug: sqlalchemy-dialects-postgresql-pypostgresql-examples +sortorder: 500031015 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql pypostgresql +meta: Python example code that shows how to use the pypostgresql callable from the sqlalchemy.dialects.postgresql module of the SQLAlchemy project. + + +`pypostgresql` is a callable within the `sqlalchemy.dialects.postgresql` module of the SQLAlchemy project. + +ARRAY, +BIGINT, +BIT, +DOUBLE_PRECISION, +ExcludeConstraint, +INTEGER, +JSON, +TSVECTOR, +array, +and json +are several other callables with code examples from the same `sqlalchemy.dialects.postgresql` package. + +## Example 1 from databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + +[**databases / databases / backends / postgres.py**](https://github.com/encode/databases/blob/master/databases/backends/postgres.py) + +```python +# postgres.py +import logging +import typing +from collections.abc import Mapping + +import asyncpg +~~from sqlalchemy.dialects.postgresql import pypostgresql +from sqlalchemy.engine.interfaces import Dialect +from sqlalchemy.sql import ClauseElement +from sqlalchemy.sql.schema import Column +from sqlalchemy.types import TypeEngine + +from databases.core import LOG_EXTRA, DatabaseURL +from databases.interfaces import ConnectionBackend, DatabaseBackend, TransactionBackend + +logger = logging.getLogger("databases") + + +_result_processors = {} # type: dict + + +class PostgresBackend(DatabaseBackend): + def __init__( + self, database_url: typing.Union[DatabaseURL, str], **options: typing.Any + ) -> None: + self._database_url = DatabaseURL(database_url) + self._options = options + self._dialect = self._get_dialect() + self._pool = None + + def _get_dialect(self) -> Dialect: +~~ dialect = pypostgresql.dialect(paramstyle="pyformat") + + dialect.implicit_returning = True + dialect.supports_native_enum = True + dialect.supports_smallserial = True # 9.2+ + dialect._backslash_escapes = False + dialect.supports_sane_multi_rowcount = True # psycopg 2.0.9+ + dialect._has_native_hstore = True + dialect.supports_native_decimal = True + + return dialect + + def _get_connection_kwargs(self) -> dict: + url_options = self._database_url.options + + kwargs = {} + min_size = url_options.get("min_size") + max_size = url_options.get("max_size") + ssl = url_options.get("ssl") + + if min_size is not None: + kwargs["min_size"] = int(min_size) + if max_size is not None: + kwargs["max_size"] = int(max_size) + if ssl is not None: + + +## ... source file continues with no further pypostgresql examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-tsvector.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-tsvector.markdown new file mode 100644 index 000000000..2dc2df510 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql-tsvector.markdown @@ -0,0 +1,71 @@ +title: sqlalchemy.dialects.postgresql TSVECTOR Example Code +category: page +slug: sqlalchemy-dialects-postgresql-tsvector-examples +sortorder: 500031014 +toc: False +sidebartitle: sqlalchemy.dialects.postgresql TSVECTOR +meta: Python example code that shows how to use the TSVECTOR constant from the sqlalchemy.dialects.postgresql module of the SQLAlchemy project. + + +`TSVECTOR` is a constant within the `sqlalchemy.dialects.postgresql` module of the SQLAlchemy project. + +ARRAY, +BIGINT, +BIT, +DOUBLE_PRECISION, +ExcludeConstraint, +INTEGER, +JSON, +array, +json, +and pypostgresql +are several other callables with code examples from the same `sqlalchemy.dialects.postgresql` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / types / ts_vector.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/types/ts_vector.py) + +```python +# ts_vector.py +import sqlalchemy as sa +~~from sqlalchemy.dialects.postgresql import TSVECTOR + + +class TSVectorType(sa.types.TypeDecorator): + impl = TSVECTOR + + class comparator_factory(TSVECTOR.Comparator): + def match(self, other, **kwargs): + if 'postgresql_regconfig' not in kwargs: + if 'regconfig' in self.type.options: + kwargs['postgresql_regconfig'] = ( + self.type.options['regconfig'] + ) +~~ return TSVECTOR.Comparator.match(self, other, **kwargs) + + def __or__(self, other): + return self.op('||')(other) + + def __init__(self, *args, **kwargs): + self.columns = args + self.options = kwargs + super(TSVectorType, self).__init__() + + + +## ... source file continues with no further TSVECTOR examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql.markdown new file mode 100644 index 000000000..d6c77152a --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-postgresql.markdown @@ -0,0 +1,384 @@ +title: sqlalchemy.dialects postgresql Example Code +category: page +slug: sqlalchemy-dialects-postgresql-examples +sortorder: 500031004 +toc: False +sidebartitle: sqlalchemy.dialects postgresql +meta: Python example code that shows how to use the postgresql callable from the sqlalchemy.dialects module of the SQLAlchemy project. + + +`postgresql` is a callable within the `sqlalchemy.dialects` module of the SQLAlchemy project. + +mssql, +mysql, +oracle, +and sqlite +are several other callables with code examples from the same `sqlalchemy.dialects` package. + +## Example 1 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / types.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./types.py) + +```python +# types.py +import warnings + +from sqlalchemy.types import UserDefinedType, Integer +from sqlalchemy.sql import func +~~from sqlalchemy.dialects import postgresql +from sqlalchemy.dialects.postgresql.base import ischema_names + +try: + from .shape import to_shape + SHAPELY = True +except ImportError: + SHAPELY = False + + +from .comparator import BaseComparator, Comparator +from .elements import WKBElement, WKTElement, RasterElement, CompositeElement +from .exc import ArgumentError + + +class _GISType(UserDefinedType): + + name = None + + from_text = None + + as_binary = None + + comparator_factory = Comparator + + + +## ... source file abbreviated to get to postgresql examples ... + + + + def __init__(self, *args, **kwargs): + kwargs['geometry_type'] = None + kwargs['srid'] = -1 + super(Raster, self).__init__(*args, **kwargs) + self.extended = None + + +class CompositeType(UserDefinedType): + + typemap = {} + + class comparator_factory(UserDefinedType.Comparator): + def __getattr__(self, key): + try: + type_ = self.type.typemap[key] + except KeyError: + raise KeyError("Type '%s' doesn't have an attribute: '%s'" + % (self.type, key)) + + return CompositeElement(self.expr, key, type_) + + +class GeometryDump(CompositeType): + +~~ typemap = {'path': postgresql.ARRAY(Integer), 'geom': Geometry} + + +ischema_names['geometry'] = Geometry +ischema_names['geography'] = Geography +ischema_names['raster'] = Raster + + + +## ... source file continues with no further postgresql examples... + +``` + + +## Example 2 from marshmallow-sqlalchemy +[marshmallow-sqlalchemy](https://github.com/marshmallow-code/marshmallow-sqlalchemy) +([project documentation](https://marshmallow-sqlalchemy.readthedocs.io/en/latest/)) +is a code library that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) with the +[Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +data serialization tool. + +The marshmallow-sqlalchemy project is provided as open source under the +[MIT license](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/LICENSE). + +[**marshmallow-sqlalchemy / src/marshmallow_sqlalchemy / convert.py**](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/src/marshmallow_sqlalchemy/./convert.py) + +```python +# convert.py +import inspect +import functools +import warnings + +import uuid +import marshmallow as ma +from marshmallow import validate, fields +~~from sqlalchemy.dialects import postgresql, mysql, mssql +from sqlalchemy.orm import SynonymProperty +import sqlalchemy as sa + +from .exceptions import ModelConversionError +from .fields import Related, RelatedList + + +def _is_field(value): + return isinstance(value, type) and issubclass(value, fields.Field) + + +def _has_default(column): + return ( + column.default is not None + or column.server_default is not None + or _is_auto_increment(column) + ) + + +def _is_auto_increment(column): + return column.table is not None and column is column.table._autoincrement_column + + +def _postgres_array_factory(converter, data_type): + return functools.partial( + fields.List, converter._get_field_class_for_data_type(data_type.item_type) + ) + + +class ModelConverter: + + SQLA_TYPE_MAPPING = { + sa.Enum: fields.Field, + sa.JSON: fields.Raw, +~~ postgresql.BIT: fields.Integer, +~~ postgresql.OID: fields.Integer, +~~ postgresql.UUID: fields.UUID, +~~ postgresql.MACADDR: fields.String, +~~ postgresql.INET: fields.String, +~~ postgresql.CIDR: fields.String, +~~ postgresql.JSON: fields.Raw, +~~ postgresql.JSONB: fields.Raw, +~~ postgresql.HSTORE: fields.Raw, +~~ postgresql.ARRAY: _postgres_array_factory, +~~ postgresql.MONEY: fields.Decimal, +~~ postgresql.DATE: fields.Date, +~~ postgresql.TIME: fields.Time, + mysql.BIT: fields.Integer, + mysql.YEAR: fields.Integer, + mysql.SET: fields.List, + mysql.ENUM: fields.Field, + mysql.INTEGER: fields.Integer, + mysql.DATETIME: fields.DateTime, + mssql.BIT: fields.Integer, + } + DIRECTION_MAPPING = {"MANYTOONE": False, "MANYTOMANY": True, "ONETOMANY": True} + + def __init__(self, schema_cls=None): + self.schema_cls = schema_cls + + @property + def type_mapping(self): + if self.schema_cls: + return self.schema_cls.TYPE_MAPPING + else: + return ma.Schema.TYPE_MAPPING + + def fields_for_model( + self, + model, + *, + + +## ... source file continues with no further postgresql examples... + +``` + + +## Example 3 from sqlalchemy-datatables +[sqlalchemy-datatables](https://github.com/Pegase745/sqlalchemy-datatables) +([PyPI package information](https://pypi.org/project/sqlalchemy-datatables/)) +is a helper library that makes it easier to use [SQLAlchemy](/sqlalchemy.html) +with the jQuery [JavaScript](/javascript.html) +[DataTables](https://datatables.net/) plugin. This library is designed to +be [web framework](/web-frameworks.html) agnostic and provides code examples +for both [Flask](/flask.html) and [Pyramid](/pyramid.html). + +The project is built and maintained by +[Michel Nemnom (Pegase745)](https://github.com/Pegase745) and is open +sourced under the +[MIT license](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/LICENSE). + +[**sqlalchemy-datatables / datatables / datatables.py**](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/./datatables/datatables.py) + +```python +# datatables.py +from __future__ import absolute_import + +import math + +from sqlalchemy import Text, func, or_ +~~from sqlalchemy.dialects import mysql, postgresql, sqlite + +from datatables.clean_regex import clean_regex +from datatables.search_methods import SEARCH_METHODS + + +class DataTables: + + def __init__(self, request, query, columns, allow_regex_searches=False): + self.params = dict(request) + if 'sEcho' in self.params: + raise ValueError( + 'Legacy datatables not supported, upgrade to >=1.10') + self.query = query + self.columns = columns + self.results = None + self.allow_regex_searches = allow_regex_searches + + self.cardinality_filtered = 0 + + self.cardinality = 0 + + self.yadcf_params = [] + self.filter_expressions = [] + self.error = None + + +## ... source file abbreviated to get to postgresql examples ... + + + column_nr = int(self.params.get('order[{:d}][column]'.format(i))) + column = self.columns[column_nr] + direction = self.params.get('order[{:d}][dir]'.format(i)) + sort_expr = column.sqla_expr + if direction == 'asc': + sort_expr = sort_expr.asc() + elif direction == 'desc': + sort_expr = sort_expr.desc() + else: + raise ValueError( + 'Invalid order direction: {}'.format(direction)) + if column.nulls_order: + if column.nulls_order == 'nullsfirst': + sort_expr = sort_expr.nullsfirst() + elif column.nulls_order == 'nullslast': + sort_expr = sort_expr.nullslast() + else: + raise ValueError( + 'Invalid order direction: {}'.format(direction)) + + sort_expressions.append(sort_expr) + i += 1 + self.sort_expressions = sort_expressions + + def _get_regex_operator(self): +~~ if isinstance(self.query.session.bind.dialect, postgresql.dialect): + return '-' + elif isinstance(self.query.session.bind.dialect, mysql.dialect): + return 'REGEXP' + elif isinstance(self.query.session.bind.dialect, sqlite.dialect): + return 'REGEXP' + else: + raise NotImplementedError( + 'Regex searches are not implemented for this dialect') + + + +## ... source file continues with no further postgresql examples... + +``` + + +## Example 4 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / expressions.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./expressions.py) + +```python +# expressions.py +import sqlalchemy as sa +~~from sqlalchemy.dialects import postgresql +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.sql.expression import ColumnElement, FunctionElement +from sqlalchemy.sql.functions import GenericFunction + +from .functions.orm import quote + + +class array_get(FunctionElement): + name = 'array_get' + + +@compiles(array_get) +def compile_array_get(element, compiler, **kw): + args = list(element.clauses) + if len(args) != 2: + raise Exception( + "Function 'array_get' expects two arguments (%d given)." % + len(args) + ) + + if not hasattr(args[1], 'value') or not isinstance(args[1].value, int): + raise Exception( + "Second argument should be an integer." + ) + return '(%s)[%s]' % ( + compiler.process(args[0]), + sa.text(str(args[1].value + 1)) + ) + + +class row_to_json(GenericFunction): + name = 'row_to_json' +~~ type = postgresql.JSON + + +@compiles(row_to_json, 'postgresql') +def compile_row_to_json(element, compiler, **kw): + return "%s(%s)" % (element.name, compiler.process(element.clauses)) + + +class json_array_length(GenericFunction): + name = 'json_array_length' + type = sa.Integer + + +@compiles(json_array_length, 'postgresql') +def compile_json_array_length(element, compiler, **kw): + return "%s(%s)" % (element.name, compiler.process(element.clauses)) + + +class Asterisk(ColumnElement): + def __init__(self, selectable): + self.selectable = selectable + + +@compiles(Asterisk) +def compile_asterisk(element, compiler, **kw): + + +## ... source file continues with no further postgresql examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-sqlite-pysqlite.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-sqlite-pysqlite.markdown new file mode 100644 index 000000000..409d3af6f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-sqlite-pysqlite.markdown @@ -0,0 +1,85 @@ +title: sqlalchemy.dialects.sqlite pysqlite Example Code +category: page +slug: sqlalchemy-dialects-sqlite-pysqlite-examples +sortorder: 500031020 +toc: False +sidebartitle: sqlalchemy.dialects.sqlite pysqlite +meta: Python example code that shows how to use the pysqlite callable from the sqlalchemy.dialects.sqlite module of the SQLAlchemy project. + + +`pysqlite` is a callable within the `sqlalchemy.dialects.sqlite` module of the SQLAlchemy project. + + + +## Example 1 from databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + +[**databases / databases / backends / sqlite.py**](https://github.com/encode/databases/blob/master/databases/backends/sqlite.py) + +```python +# sqlite.py +import logging +import typing +import uuid + +import aiosqlite +~~from sqlalchemy.dialects.sqlite import pysqlite +from sqlalchemy.engine.interfaces import Dialect, ExecutionContext +from sqlalchemy.engine.result import ResultMetaData, RowProxy +from sqlalchemy.sql import ClauseElement +from sqlalchemy.types import TypeEngine + +from databases.core import LOG_EXTRA, DatabaseURL +from databases.interfaces import ConnectionBackend, DatabaseBackend, TransactionBackend + +logger = logging.getLogger("databases") + + +class SQLiteBackend(DatabaseBackend): + def __init__( + self, database_url: typing.Union[DatabaseURL, str], **options: typing.Any + ) -> None: + self._database_url = DatabaseURL(database_url) + self._options = options +~~ self._dialect = pysqlite.dialect(paramstyle="qmark") + self._dialect.supports_native_decimal = False + self._pool = SQLitePool(self._database_url, **self._options) + + async def connect(self) -> None: + pass + + async def disconnect(self) -> None: + pass + + def connection(self) -> "SQLiteConnection": + return SQLiteConnection(self._pool, self._dialect) + + +class SQLitePool: + def __init__(self, url: DatabaseURL, **options: typing.Any) -> None: + self._url = url + self._options = options + + async def acquire(self) -> aiosqlite.Connection: + connection = aiosqlite.connect( + database=self._url.database, isolation_level=None, **self._options + ) + await connection.__aenter__() + return connection + + +## ... source file continues with no further pysqlite examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-dialects-sqlite.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-sqlite.markdown new file mode 100644 index 000000000..fc8b66dfa --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-dialects-sqlite.markdown @@ -0,0 +1,216 @@ +title: sqlalchemy.dialects sqlite Example Code +category: page +slug: sqlalchemy-dialects-sqlite-examples +sortorder: 500031005 +toc: False +sidebartitle: sqlalchemy.dialects sqlite +meta: Python example code that shows how to use the sqlite callable from the sqlalchemy.dialects module of the SQLAlchemy project. + + +`sqlite` is a callable within the `sqlalchemy.dialects` module of the SQLAlchemy project. + +mssql, +mysql, +oracle, +and postgresql +are several other callables with code examples from the same `sqlalchemy.dialects` package. + +## Example 1 from sqlalchemy-datatables +[sqlalchemy-datatables](https://github.com/Pegase745/sqlalchemy-datatables) +([PyPI package information](https://pypi.org/project/sqlalchemy-datatables/)) +is a helper library that makes it easier to use [SQLAlchemy](/sqlalchemy.html) +with the jQuery [JavaScript](/javascript.html) +[DataTables](https://datatables.net/) plugin. This library is designed to +be [web framework](/web-frameworks.html) agnostic and provides code examples +for both [Flask](/flask.html) and [Pyramid](/pyramid.html). + +The project is built and maintained by +[Michel Nemnom (Pegase745)](https://github.com/Pegase745) and is open +sourced under the +[MIT license](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/LICENSE). + +[**sqlalchemy-datatables / datatables / datatables.py**](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/./datatables/datatables.py) + +```python +# datatables.py +from __future__ import absolute_import + +import math + +from sqlalchemy import Text, func, or_ +~~from sqlalchemy.dialects import mysql, postgresql, sqlite + +from datatables.clean_regex import clean_regex +from datatables.search_methods import SEARCH_METHODS + + +class DataTables: + + def __init__(self, request, query, columns, allow_regex_searches=False): + self.params = dict(request) + if 'sEcho' in self.params: + raise ValueError( + 'Legacy datatables not supported, upgrade to >=1.10') + self.query = query + self.columns = columns + self.results = None + self.allow_regex_searches = allow_regex_searches + + self.cardinality_filtered = 0 + + self.cardinality = 0 + + self.yadcf_params = [] + self.filter_expressions = [] + self.error = None + + +## ... source file abbreviated to get to sqlite examples ... + + + if direction == 'asc': + sort_expr = sort_expr.asc() + elif direction == 'desc': + sort_expr = sort_expr.desc() + else: + raise ValueError( + 'Invalid order direction: {}'.format(direction)) + if column.nulls_order: + if column.nulls_order == 'nullsfirst': + sort_expr = sort_expr.nullsfirst() + elif column.nulls_order == 'nullslast': + sort_expr = sort_expr.nullslast() + else: + raise ValueError( + 'Invalid order direction: {}'.format(direction)) + + sort_expressions.append(sort_expr) + i += 1 + self.sort_expressions = sort_expressions + + def _get_regex_operator(self): + if isinstance(self.query.session.bind.dialect, postgresql.dialect): + return '-' + elif isinstance(self.query.session.bind.dialect, mysql.dialect): + return 'REGEXP' +~~ elif isinstance(self.query.session.bind.dialect, sqlite.dialect): + return 'REGEXP' + else: + raise NotImplementedError( + 'Regex searches are not implemented for this dialect') + + + +## ... source file continues with no further sqlite examples... + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / types / password.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/types/password.py) + +```python +# password.py +import weakref + +import six +from sqlalchemy import types +~~from sqlalchemy.dialects import oracle, postgresql, sqlite +from sqlalchemy.ext.mutable import Mutable + +from ..exceptions import ImproperlyConfigured +from .scalar_coercible import ScalarCoercible + +passlib = None +try: + import passlib + from passlib.context import LazyCryptContext +except ImportError: + pass + + +class Password(Mutable, object): + + @classmethod + def coerce(cls, key, value): + if isinstance(value, Password): + return value + + if isinstance(value, (six.string_types, six.binary_type)): + return cls(value, secret=True) + + super(Password, cls).coerce(key, value) + + +## ... source file abbreviated to get to sqlite examples ... + + + + return self._max_length + + def calculate_max_length(self): + max_lengths = [1024] + for name in self.context.schemes(): + scheme = getattr(__import__('passlib.hash').hash, name) + length = 4 + len(scheme.name) + length += len(str(getattr(scheme, 'max_rounds', ''))) + length += (getattr(scheme, 'max_salt_size', 0) or 0) + length += getattr( + scheme, + 'encoded_checksum_size', + scheme.checksum_size + ) + max_lengths.append(length) + + return max(max_lengths) + + def load_dialect_impl(self, dialect): + if dialect.name == 'postgresql': + impl = postgresql.BYTEA(self.length) + elif dialect.name == 'oracle': + impl = oracle.RAW(self.length) + elif dialect.name == 'sqlite': +~~ impl = sqlite.BLOB(self.length) + else: + impl = types.VARBINARY(self.length) + return dialect.type_descriptor(impl) + + def process_bind_param(self, value, dialect): + if isinstance(value, Password): + if value.secret is not None: + return self._hash(value.secret).encode('utf8') + + return value.hash + + if isinstance(value, six.string_types): + return self._hash(value).encode('utf8') + + def process_result_value(self, value, dialect): + if value is not None: + return Password(value, self.context) + + def _hash(self, value): + return getattr(self.context, self.hashing_method)(value) + + def _coerce(self, value): + + if value is None: + + +## ... source file continues with no further sqlite examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-connection.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-connection.markdown new file mode 100644 index 000000000..16a6f8717 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-connection.markdown @@ -0,0 +1,282 @@ +title: sqlalchemy.engine Connection Example Code +category: page +slug: sqlalchemy-engine-connection-examples +sortorder: 500031021 +toc: False +sidebartitle: sqlalchemy.engine Connection +meta: Example code for understanding how to use the Connection class from the sqlalchemy.engine module of the SQLAlchemy project. + + +`Connection` is a class within the `sqlalchemy.engine` module of the SQLAlchemy project. + +Engine, +create_engine, +default, +and url +are several other callables with code examples from the same `sqlalchemy.engine` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / runtime / migration.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/runtime/migration.py) + +```python +# migration.py +from contextlib import contextmanager +import logging +import sys + +from sqlalchemy import Column +from sqlalchemy import literal_column +from sqlalchemy import MetaData +from sqlalchemy import PrimaryKeyConstraint +from sqlalchemy import String +from sqlalchemy import Table +~~from sqlalchemy.engine import Connection +from sqlalchemy.engine import url as sqla_url +from sqlalchemy.engine.strategies import MockEngineStrategy + +from .. import ddl +from .. import util +from ..util import sqla_compat +from ..util.compat import callable +from ..util.compat import EncodedIO + +log = logging.getLogger(__name__) + + +class _ProxyTransaction(object): + def __init__(self, migration_context): + self.migration_context = migration_context + + @property + def _proxied_transaction(self): + return self.migration_context._transaction + + def rollback(self): + self._proxied_transaction.rollback() + + def commit(self): + + +## ... source file abbreviated to get to Connection examples ... + + + log.info("Generating static SQL") + log.info( + "Will assume %s DDL.", + "transactional" + if self.impl.transactional_ddl + else "non-transactional", + ) + + @classmethod + def configure( + cls, + connection=None, + url=None, + dialect_name=None, + dialect=None, + environment_context=None, + dialect_opts=None, + opts=None, + ): + if opts is None: + opts = {} + if dialect_opts is None: + dialect_opts = {} + + if connection: +~~ if not isinstance(connection, Connection): + util.warn( + "'connection' argument to configure() is expected " + "to be a sqlalchemy.engine.Connection instance, " + "got %r" % connection, + stacklevel=3, + ) + + dialect = connection.dialect + elif url: + url = sqla_url.make_url(url) + dialect = url.get_dialect()(**dialect_opts) + elif dialect_name: + url = sqla_url.make_url("%s://" % dialect_name) + dialect = url.get_dialect()(**dialect_opts) + elif not dialect: + raise Exception("Connection, url, or dialect_name is required.") + + return MigrationContext(dialect, connection, opts, environment_context) + + @contextmanager + def autocommit_block(self): + _in_connection_transaction = self._in_connection_transaction() + + if self.impl.transactional_ddl: + + +## ... source file continues with no further Connection examples... + +``` + + +## Example 2 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / engine.py**](https://github.com/python-gino/gino/blob/master/src/gino/./engine.py) + +```python +# engine.py +import asyncio +import collections +import functools +import sys +import time +from contextvars import ContextVar + +from sqlalchemy.cutils import _distill_params +~~from sqlalchemy.engine import Engine, Connection +from sqlalchemy.sql import schema + +from .aiocontextvars import patch_asyncio +from .exceptions import MultipleResultsFound, NoResultFound +from .transaction import GinoTransaction + +patch_asyncio() + + +class _BaseDBAPIConnection: + _reset_agent = None + gino_conn = None + + def __init__(self, cursor_cls): + self._cursor_cls = cursor_cls + self._closed = False + + def commit(self): + pass + + def cursor(self): + return self._cursor_cls(self) + + @property + + +## ... source file abbreviated to get to Connection examples ... + + + +class _ReusingDBAPIConnection(_BaseDBAPIConnection): + def __init__(self, cursor_cls, root): + super().__init__(cursor_cls) + self._root = root + + @property + def raw_connection(self): + return self._root.raw_connection + + async def _acquire(self, timeout): + return await self._root.acquire(timeout=timeout) + + async def _release(self): + pass + + +class _bypass_no_param: + def keys(self): + return [] + + +_bypass_no_param = _bypass_no_param() + + +~~class _SAConnection(Connection): + def _execute_context(self, dialect, constructor, statement, parameters, *args): + if parameters == [_bypass_no_param]: + constructor = getattr( + self.dialect.execution_ctx_cls, + constructor.__name__ + "_prepared", + constructor, + ) + return super()._execute_context( + dialect, constructor, statement, parameters, *args + ) + + def _execute_baked_query(self, bq, multiparams, params): + elem = bq.query + if self._has_events or self.engine._has_events: + for fn in self.dispatch.before_execute: + _, multiparams, params = fn(self, elem, multiparams, params) + + distilled_params = _distill_params(multiparams, params) + + ret = self._execute_context( + self.dialect, + self.dialect.execution_ctx_cls._init_baked_query, + bq.compiled_sql, + distilled_params, + + +## ... source file abbreviated to get to Connection examples ... + + + + async def one(self, clause, *multiparams, **params): + async with self.acquire(reuse=True) as conn: + return await conn.one(clause, *multiparams, **params) + + async def scalar(self, clause, *multiparams, **params): + async with self.acquire(reuse=True) as conn: + return await conn.scalar(clause, *multiparams, **params) + + async def status(self, clause, *multiparams, **params): + async with self.acquire(reuse=True) as conn: + return await conn.status(clause, *multiparams, **params) + + def compile(self, clause, *multiparams, **params): + return self._dialect.compile(clause, *multiparams, **params) + + def transaction(self, *args, timeout=None, reuse=True, reusable=True, **kwargs): + return _TransactionContext( + self.acquire(timeout=timeout, reuse=reuse, reusable=reusable), + (args, kwargs), + ) + + def iterate(self, clause, *multiparams, **params): + connection = self.current_connection + if connection is None: +~~ raise ValueError("No Connection in context, please provide one") + return connection.iterate(clause, *multiparams, **params) + + def update_execution_options(self, **opt): + self._sa_engine.update_execution_options(**opt) + + async def _run_visitor(self, *args, **kwargs): + async with self.acquire(reuse=True) as conn: + await getattr(conn, "_run_visitor")(*args, **kwargs) + + def repr(self, color=False): + return self._pool.repr(color) + + def __repr__(self): + return self.repr() + + + +## ... source file continues with no further Connection examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-create-engine.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-create-engine.markdown new file mode 100644 index 000000000..e9c01dc95 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-create-engine.markdown @@ -0,0 +1,276 @@ +title: sqlalchemy.engine create_engine Example Code +category: page +slug: sqlalchemy-engine-create-engine-examples +sortorder: 500031023 +toc: False +sidebartitle: sqlalchemy.engine create_engine +meta: Python example code that shows how to use the create_engine callable from the sqlalchemy.engine module of the SQLAlchemy project. + + +`create_engine` is a callable within the `sqlalchemy.engine` module of the SQLAlchemy project. + +Connection, +Engine, +default, +and url +are several other callables with code examples from the same `sqlalchemy.engine` package. + +## Example 1 from PyHive +[PyHive](https://github.com/dropbox/PyHive) +([PyPI package information](https://pypi.org/project/PyHive/)) +is a set of [DB-API](https://www.python.org/dev/peps/pep-0249/) +and +[SQLAlchemy](/sqlalchemy.html) +interfaces that make it easier to use [Presto](https://prestodb.io/) +and [Apache Hive](http://hive.apache.org/) with Python. +[Dropbox's engineering team](https://www.dropbox.com/jobs/teams/engineering) +created this code library, open sourced it and put it out under +the [Apache 2.0 license](https://github.com/dropbox/PyHive/blob/master/LICENSE). + +[**PyHive / pyhive / tests / test_sqlalchemy_hive.py**](https://github.com/dropbox/PyHive/blob/master/pyhive/tests/test_sqlalchemy_hive.py) + +```python +# test_sqlalchemy_hive.py +from __future__ import absolute_import +from __future__ import unicode_literals +from builtins import str +from pyhive.sqlalchemy_hive import HiveDate +from pyhive.sqlalchemy_hive import HiveDecimal +from pyhive.sqlalchemy_hive import HiveTimestamp +from pyhive.tests.sqlalchemy_test_case import SqlAlchemyTestCase +from pyhive.tests.sqlalchemy_test_case import with_engine_connection +from sqlalchemy import types +~~from sqlalchemy.engine import create_engine +from sqlalchemy.schema import Column +from sqlalchemy.schema import MetaData +from sqlalchemy.schema import Table +import contextlib +import datetime +import decimal +import sqlalchemy.types +import unittest + +_ONE_ROW_COMPLEX_CONTENTS = [ + True, + 127, + 32767, + 2147483647, + 9223372036854775807, + 0.5, + 0.25, + 'a string', + datetime.datetime(1970, 1, 1), + b'123', + '[1,2]', + '{1:2,3:4}', + '{"a":1,"b":2}', + '{0:1}', + decimal.Decimal('0.1'), +] + + + + +class TestSqlAlchemyHive(unittest.TestCase, SqlAlchemyTestCase): +~~ def create_engine(self): +~~ return create_engine('hive://localhost:10000/default') + + @with_engine_connection + def test_dotted_column_names(self, engine, connection): + row = connection.execute('SELECT * FROM one_row').fetchone() + assert row.keys() == ['number_of_rows'] + assert 'number_of_rows' in row + assert row.number_of_rows == 1 + assert row['number_of_rows'] == 1 + assert getattr(row, 'one_row.number_of_rows') == 1 + assert row['one_row.number_of_rows'] == 1 + + @with_engine_connection + def test_dotted_column_names_raw(self, engine, connection): + row = connection.execution_options(hive_raw_colnames=True) \ + .execute('SELECT * FROM one_row').fetchone() + assert row.keys() == ['one_row.number_of_rows'] + assert 'number_of_rows' not in row + assert getattr(row, 'one_row.number_of_rows') == 1 + assert row['one_row.number_of_rows'] == 1 + + @with_engine_connection + def test_reflect_select(self, engine, connection): + one_row_complex = Table('one_row_complex', MetaData(bind=engine), autoload=True) + self.assertEqual(len(one_row_complex.c), 15) + + +## ... source file abbreviated to get to create_engine examples ... + + + self.assertIsInstance(one_row_complex.c.double.type, types.Float) + self.assertIsInstance(one_row_complex.c.string.type, types.String) + self.assertIsInstance(one_row_complex.c.timestamp.type, HiveTimestamp) + self.assertIsInstance(one_row_complex.c.binary.type, types.String) + self.assertIsInstance(one_row_complex.c.array.type, types.String) + self.assertIsInstance(one_row_complex.c.map.type, types.String) + self.assertIsInstance(one_row_complex.c.struct.type, types.String) + self.assertIsInstance(one_row_complex.c.union.type, types.String) + self.assertIsInstance(one_row_complex.c.decimal.type, HiveDecimal) + + @with_engine_connection + def test_type_map(self, engine, connection): + row = connection.execute('SELECT * FROM one_row_complex').fetchone() + self.assertListEqual(list(row), _ONE_ROW_COMPLEX_CONTENTS) + + @with_engine_connection + def test_reserved_words(self, engine, connection): + fake_table = Table('select', MetaData(bind=engine), Column('map', sqlalchemy.types.String)) + query = str(fake_table.select(fake_table.c.map == 'a')) + self.assertIn('`select`', query) + self.assertIn('`map`', query) + self.assertNotIn('"select"', query) + self.assertNotIn('"map"', query) + + def test_switch_database(self): +~~ engine = create_engine('hive://localhost:10000/pyhive_test_database') + try: + with contextlib.closing(engine.connect()) as connection: + self.assertIn( + ('dummy_table',), + connection.execute('SHOW TABLES').fetchall() + ) + connection.execute('USE default') + self.assertIn( + ('one_row',), + connection.execute('SHOW TABLES').fetchall() + ) + finally: + engine.dispose() + + @with_engine_connection + def test_lots_of_types(self, engine, connection): + types = [ + 'INT', 'CHAR', 'VARCHAR', 'NCHAR', 'TEXT', 'Text', 'FLOAT', + 'NUMERIC', 'DECIMAL', 'TIMESTAMP', 'DATETIME', 'CLOB', 'BLOB', + 'BOOLEAN', 'SMALLINT', 'DATE', 'TIME', + 'String', 'Integer', 'SmallInteger', + 'Numeric', 'Float', 'DateTime', 'Date', 'Time', 'LargeBinary', + 'Boolean', 'Unicode', 'UnicodeText', + ] + + +## ... source file continues with no further create_engine examples... + +``` + + +## Example 2 from sqlacodegen +[sqlacodegen](https://github.com/agronholm/sqlacodegen) +([PyPI package information](https://pypi.org/project/sqlacodegen/)) +is a tool for +reading from an existing [relational database](/databases.html) to +generate code to create [SQLAlchemy](/sqlalchemy.html) models based +on that database. The project is primarily written and maintained +by [Alex Grönholm (agronholm)](https://github.com/agronholm) and it +is open sourced under the +[MIT license](https://github.com/agronholm/sqlacodegen/blob/master/LICENSE). + +[**sqlacodegen / sqlacodegen / main.py**](https://github.com/agronholm/sqlacodegen/blob/master/sqlacodegen/./main.py) + +```python +# main.py +from __future__ import unicode_literals, division, print_function, absolute_import + +import argparse +import io +import sys + +import pkg_resources +~~from sqlalchemy.engine import create_engine +from sqlalchemy.schema import MetaData + +from sqlacodegen.codegen import CodeGenerator + + +def main(): + parser = argparse.ArgumentParser( + description='Generates SQLAlchemy model code from an existing database.') + parser.add_argument('url', nargs='?', help='SQLAlchemy url to the database') + parser.add_argument('--version', action='store_true', help="print the version number and exit") + parser.add_argument('--schema', help='load tables from an alternate schema') + parser.add_argument('--tables', help='tables to process (comma-separated, default: all)') + parser.add_argument('--noviews', action='store_true', help="ignore views") + parser.add_argument('--noindexes', action='store_true', help='ignore indexes') + parser.add_argument('--noconstraints', action='store_true', help='ignore constraints') + parser.add_argument('--nojoined', action='store_true', + help="don't autodetect joined table inheritance") + parser.add_argument('--noinflect', action='store_true', + help="don't try to convert tables names to singular form") + parser.add_argument('--noclasses', action='store_true', + help="don't generate classes, only tables") + parser.add_argument('--nocomments', action='store_true', help="don't render column comments") + parser.add_argument('--outfile', help='file to write output to (default: stdout)') + args = parser.parse_args() + + if args.version: + version = pkg_resources.get_distribution('sqlacodegen').parsed_version + print(version.public) + return + if not args.url: + print('You must supply a url\n', file=sys.stderr) + parser.print_help() + return + +~~ engine = create_engine(args.url) + metadata = MetaData(engine) + tables = args.tables.split(',') if args.tables else None + metadata.reflect(engine, args.schema, not args.noviews, tables) + + outfile = io.open(args.outfile, 'w', encoding='utf-8') if args.outfile else sys.stdout + generator = CodeGenerator(metadata, args.noindexes, args.noconstraints, args.nojoined, + args.noinflect, args.noclasses, nocomments=args.nocomments) + generator.render(outfile) + + + +## ... source file continues with no further create_engine examples... + +``` + + +## Example 3 from sqlalchemy-clickhouse +[sqlalchemy-clickhouse](https://github.com/cloudflare/sqlalchemy-clickhouse) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +for communicating with the open source [ClickHouse](https://clickhouse.tech/) +database management system. ClickHouse is column-oriented and therefore +better for some use cases and worse for others compared to a traditional +[relational database](/databases.html). + +The code for this project is open sourced under the +[MIT license](https://github.com/cloudflare/sqlalchemy-clickhouse/blob/master/LICENSE.txt) +while ClickHouse is provided as open source under the +[Apache License 2.0](https://github.com/ClickHouse/ClickHouse/blob/master/LICENSE). + +[**sqlalchemy-clickhouse / example.py**](https://github.com/cloudflare/sqlalchemy-clickhouse/blob/master/././example.py) + +```python +# example.py + +import connector +cursor = connector.connect('default').cursor() +cursor.execute('SELECT * FROM test LIMIT 10') +print(cursor.fetchone()) + +from sqlalchemy.dialects import registry +registry.register("clickhouse", "base", "dialect") + +from sqlalchemy import * +~~from sqlalchemy.engine import create_engine +from sqlalchemy.schema import * + +~~engine = create_engine('clickhouse://default:@localhost:8123/default') +logs = Table('test', MetaData(bind=engine), autoload=True) +print(select([func.count('*')], from_obj=logs).scalar()) + + + +## ... source file continues with no further create_engine examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-default-defaultdialect.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-default-defaultdialect.markdown new file mode 100644 index 000000000..c34744b19 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-default-defaultdialect.markdown @@ -0,0 +1,84 @@ +title: sqlalchemy.engine.default DefaultDialect Example Code +category: page +slug: sqlalchemy-engine-default-defaultdialect-examples +sortorder: 500031026 +toc: False +sidebartitle: sqlalchemy.engine.default DefaultDialect +meta: Example code for understanding how to use the DefaultDialect class from the sqlalchemy.engine.default module of the SQLAlchemy project. + + +`DefaultDialect` is a class within the `sqlalchemy.engine.default` module of the SQLAlchemy project. + + + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / autogenerate / api.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/autogenerate/api.py) + +```python +# api.py + ) + + compare._populate_migration_script(autogen_context, migration_script) + + return migration_script + + +def render_python_code( + up_or_down_op, + sqlalchemy_module_prefix="sa.", + alembic_module_prefix="op.", + render_as_batch=False, + imports=(), + render_item=None, + migration_context=None, +): + opts = { + "sqlalchemy_module_prefix": sqlalchemy_module_prefix, + "alembic_module_prefix": alembic_module_prefix, + "render_item": render_item, + "render_as_batch": render_as_batch, + } + + if migration_context is None: + from ..runtime.migration import MigrationContext +~~ from sqlalchemy.engine.default import DefaultDialect + + migration_context = MigrationContext.configure( +~~ dialect=DefaultDialect() + ) + + autogen_context = AutogenContext(migration_context, opts=opts) + autogen_context.imports = set(imports) + return render._indent( + render._render_cmd_body(up_or_down_op, autogen_context) + ) + + +def _render_migration_diffs(context, template_args): + + autogen_context = AutogenContext(context) + + upgrade_ops = ops.UpgradeOps([]) + compare._produce_net_changes(autogen_context, upgrade_ops) + + migration_script = ops.MigrationScript( + rev_id=None, + upgrade_ops=upgrade_ops, + downgrade_ops=upgrade_ops.reverse(), + ) + + render._render_python_into_templatevars( + autogen_context, migration_script, template_args + + +## ... source file continues with no further DefaultDialect examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-default.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-default.markdown new file mode 100644 index 000000000..ad195a668 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-default.markdown @@ -0,0 +1,120 @@ +title: sqlalchemy.engine default Example Code +category: page +slug: sqlalchemy-engine-default-examples +sortorder: 500031024 +toc: False +sidebartitle: sqlalchemy.engine default +meta: Python example code that shows how to use the default callable from the sqlalchemy.engine module of the SQLAlchemy project. + + +`default` is a callable within the `sqlalchemy.engine` module of the SQLAlchemy project. + +Connection, +Engine, +create_engine, +and url +are several other callables with code examples from the same `sqlalchemy.engine` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / testing / assertions.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/testing/assertions.py) + +```python +# assertions.py +from __future__ import absolute_import + +import re + +from sqlalchemy import util +~~from sqlalchemy.engine import default +from sqlalchemy.testing.assertions import _expect_warnings +from sqlalchemy.testing.assertions import eq_ # noqa +from sqlalchemy.testing.assertions import is_ # noqa +from sqlalchemy.testing.assertions import is_false # noqa +from sqlalchemy.testing.assertions import is_not_ # noqa +from sqlalchemy.testing.assertions import is_true # noqa +from sqlalchemy.testing.assertions import ne_ # noqa +from sqlalchemy.util import decorator + +from ..util.compat import py3k + + +def assert_raises(except_cls, callable_, *args, **kw): + try: + callable_(*args, **kw) + success = False + except except_cls: + success = True + + assert success, "Callable did not raise an exception" + + +def assert_raises_message(except_cls, msg, callable_, *args, **kwargs): + try: + + +## ... source file abbreviated to get to default examples ... + + + e, + ) + print(util.text_type(e).encode("utf-8")) + + +def eq_ignore_whitespace(a, b, msg=None): + + a = re.sub(r"^\s+?|\n", "", a) + a = re.sub(r" {2,}", " ", a) + b = re.sub(r"^\s+?|\n", "", b) + b = re.sub(r" {2,}", " ", b) + + if py3k: + b = re.sub(r"!U", "", b) + else: + b = re.sub(r"!U", "u", b) + + assert a == b, msg or "%r != %r" % (a, b) + + +_dialect_mods = {} + + +def _get_dialect(name): + if name is None or name == "default": +~~ return default.DefaultDialect() + else: + try: + dialect_mod = _dialect_mods[name] + except KeyError: + dialect_mod = getattr( + __import__("sqlalchemy.dialects.%s" % name).dialects, name + ) + _dialect_mods[name] = dialect_mod + d = dialect_mod.dialect() + if name == "postgresql": + d.implicit_returning = True + elif name == "mssql": + d.legacy_schema_aliasing = False + return d + + +def expect_warnings(*messages, **kw): + return _expect_warnings(Warning, messages, **kw) + + +def emits_python_deprecation_warning(*messages): + + @decorator + def decorate(fn, *args, **kw): + + +## ... source file continues with no further default examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-engine.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-engine.markdown new file mode 100644 index 000000000..67ded2f74 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-engine.markdown @@ -0,0 +1,240 @@ +title: sqlalchemy.engine Engine Example Code +category: page +slug: sqlalchemy-engine-engine-examples +sortorder: 500031022 +toc: False +sidebartitle: sqlalchemy.engine Engine +meta: Example code for understanding how to use the Engine class from the sqlalchemy.engine module of the SQLAlchemy project. + + +`Engine` is a class within the `sqlalchemy.engine` module of the SQLAlchemy project. + +Connection, +create_engine, +default, +and url +are several other callables with code examples from the same `sqlalchemy.engine` package. + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [SQLAlchemy](/sqlalchemy.html) and [Flask](/flask.html). +The application can be used as-is to run CTF events, or the code can be +modified for custom rules on hacking scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / CTFd / __init__.py**](https://github.com/CTFd/CTFd/blob/master/./CTFd/__init__.py) + +```python +# __init__.py +import datetime +import os +import sys +import weakref +from distutils.version import StrictVersion + +import jinja2 +from flask import Flask, Request +from flask_migrate import upgrade +from jinja2 import FileSystemLoader +from jinja2.sandbox import SandboxedEnvironment +from werkzeug.middleware.proxy_fix import ProxyFix +from werkzeug.utils import cached_property + +from CTFd import utils +from CTFd.plugins import init_plugins +from CTFd.utils.crypto import sha256 +from CTFd.utils.initialization import ( + init_events, + init_logs, + init_request_processors, + init_template_filters, + init_template_globals, +) +from CTFd.utils.migrations import create_database, migrations, stamp_latest_revision +from CTFd.utils.sessions import CachingSessionInterface +from CTFd.utils.updates import update_check + +__version__ = "3.0.0b2" + + +class CTFdRequest(Request): + @cached_property + def path(self): + return self.script_root + super(CTFdRequest, self).path + + +## ... source file abbreviated to get to Engine examples ... + + + } + ) + app.jinja_loader = jinja2.ChoiceLoader([app.theme_loader, app.plugin_loader]) + + from CTFd.models import ( # noqa: F401 + db, + Teams, + Solves, + Challenges, + Fails, + Flags, + Tags, + Files, + Tracking, + ) + + url = create_database() + + app.config["SQLALCHEMY_DATABASE_URI"] = str(url) + + db.init_app(app) + + migrations.init_app(app, db) + + if url.drivername.startswith("sqlite"): +~~ from sqlalchemy.engine import Engine + from sqlalchemy import event + +~~ @event.listens_for(Engine, "connect") + def set_sqlite_pragma(dbapi_connection, connection_record): + cursor = dbapi_connection.cursor() + cursor.execute("PRAGMA foreign_keys=ON") + cursor.close() + + db.create_all() + stamp_latest_revision() + else: + upgrade() + + from CTFd.models import ma + + ma.init_app(app) + + app.db = db + app.VERSION = __version__ + + from CTFd.cache import cache + + cache.init_app(app) + app.cache = cache + + reverse_proxy = app.config.get("REVERSE_PROXY") + if reverse_proxy: + + +## ... source file continues with no further Engine examples... + +``` + + +## Example 2 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / engine.py**](https://github.com/python-gino/gino/blob/master/src/gino/./engine.py) + +```python +# engine.py +import asyncio +import collections +import functools +import sys +import time +from contextvars import ContextVar + +from sqlalchemy.cutils import _distill_params +~~from sqlalchemy.engine import Engine, Connection +from sqlalchemy.sql import schema + +from .aiocontextvars import patch_asyncio +from .exceptions import MultipleResultsFound, NoResultFound +from .transaction import GinoTransaction + +patch_asyncio() + + +class _BaseDBAPIConnection: + _reset_agent = None + gino_conn = None + + def __init__(self, cursor_cls): + self._cursor_cls = cursor_cls + self._closed = False + + def commit(self): + pass + + def cursor(self): + return self._cursor_cls(self) + + @property + + +## ... source file abbreviated to get to Engine examples ... + + + return super()._execute_context( + dialect, constructor, statement, parameters, *args + ) + + def _execute_baked_query(self, bq, multiparams, params): + elem = bq.query + if self._has_events or self.engine._has_events: + for fn in self.dispatch.before_execute: + _, multiparams, params = fn(self, elem, multiparams, params) + + distilled_params = _distill_params(multiparams, params) + + ret = self._execute_context( + self.dialect, + self.dialect.execution_ctx_cls._init_baked_query, + bq.compiled_sql, + distilled_params, + bq, + distilled_params, + ) + if self._has_events or self.engine._has_events: + self.dispatch.after_execute(self, elem, multiparams, params, ret) + return ret + + +~~class _SAEngine(Engine): + _connection_cls = _SAConnection + + def __init__(self, dialect, **kwargs): + super().__init__(None, dialect, None, **kwargs) + + +class _AcquireContext: + __slots__ = ["_acquire", "_conn"] + + def __init__(self, acquire): + self._acquire = acquire + self._conn = None + + async def __aenter__(self): + self._conn = await self._acquire() + return self._conn + + async def __aexit__(self, exc_type, exc_val, exc_tb): + conn, self._conn = self._conn, None + await conn.release() + + def __await__(self): + return self._acquire().__await__() + + + +## ... source file continues with no further Engine examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-interfaces-executioncontext.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-interfaces-executioncontext.markdown new file mode 100644 index 000000000..ac853930f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-interfaces-executioncontext.markdown @@ -0,0 +1,68 @@ +title: sqlalchemy.engine.interfaces ExecutionContext Example Code +category: page +slug: sqlalchemy-engine-interfaces-executioncontext-examples +sortorder: 500031027 +toc: False +sidebartitle: sqlalchemy.engine.interfaces ExecutionContext +meta: Example code for understanding how to use the ExecutionContext class from the sqlalchemy.engine.interfaces module of the SQLAlchemy project. + + +`ExecutionContext` is a class within the `sqlalchemy.engine.interfaces` module of the SQLAlchemy project. + + + +## Example 1 from databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + +[**databases / databases / backends / sqlite.py**](https://github.com/encode/databases/blob/master/databases/backends/sqlite.py) + +```python +# sqlite.py +import logging +import typing +import uuid + +import aiosqlite +from sqlalchemy.dialects.sqlite import pysqlite +~~from sqlalchemy.engine.interfaces import Dialect, ExecutionContext +from sqlalchemy.engine.result import ResultMetaData, RowProxy +from sqlalchemy.sql import ClauseElement +from sqlalchemy.types import TypeEngine + +from databases.core import LOG_EXTRA, DatabaseURL +from databases.interfaces import ConnectionBackend, DatabaseBackend, TransactionBackend + +logger = logging.getLogger("databases") + + +class SQLiteBackend(DatabaseBackend): + def __init__( + self, database_url: typing.Union[DatabaseURL, str], **options: typing.Any + ) -> None: + self._database_url = DatabaseURL(database_url) + self._options = options + self._dialect = pysqlite.dialect(paramstyle="qmark") + self._dialect.supports_native_decimal = False + self._pool = SQLitePool(self._database_url, **self._options) + + async def connect(self) -> None: + pass + + async def disconnect(self) -> None: + + +## ... source file continues with no further ExecutionContext examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-result-resultmetadata.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-result-resultmetadata.markdown new file mode 100644 index 000000000..891d771ec --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-result-resultmetadata.markdown @@ -0,0 +1,166 @@ +title: sqlalchemy.engine.result ResultMetaData Example Code +category: page +slug: sqlalchemy-engine-result-resultmetadata-examples +sortorder: 500031028 +toc: False +sidebartitle: sqlalchemy.engine.result ResultMetaData +meta: Example code for understanding how to use the ResultMetaData class from the sqlalchemy.engine.result module of the SQLAlchemy project. + + +`ResultMetaData` is a class within the `sqlalchemy.engine.result` module of the SQLAlchemy project. + +RowProxy +is another callable from the `sqlalchemy.engine.result` package with code examples. + +## Example 1 from databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + +[**databases / databases / backends / sqlite.py**](https://github.com/encode/databases/blob/master/databases/backends/sqlite.py) + +```python +# sqlite.py +import logging +import typing +import uuid + +import aiosqlite +from sqlalchemy.dialects.sqlite import pysqlite +from sqlalchemy.engine.interfaces import Dialect, ExecutionContext +~~from sqlalchemy.engine.result import ResultMetaData, RowProxy +from sqlalchemy.sql import ClauseElement +from sqlalchemy.types import TypeEngine + +from databases.core import LOG_EXTRA, DatabaseURL +from databases.interfaces import ConnectionBackend, DatabaseBackend, TransactionBackend + +logger = logging.getLogger("databases") + + +class SQLiteBackend(DatabaseBackend): + def __init__( + self, database_url: typing.Union[DatabaseURL, str], **options: typing.Any + ) -> None: + self._database_url = DatabaseURL(database_url) + self._options = options + self._dialect = pysqlite.dialect(paramstyle="qmark") + self._dialect.supports_native_decimal = False + self._pool = SQLitePool(self._database_url, **self._options) + + async def connect(self) -> None: + pass + + async def disconnect(self) -> None: + pass + + +## ... source file abbreviated to get to ResultMetaData examples ... + + + def __init__(self, context: ExecutionContext): + self.context = context + + +class SQLiteConnection(ConnectionBackend): + def __init__(self, pool: SQLitePool, dialect: Dialect): + self._pool = pool + self._dialect = dialect + self._connection = None + + async def acquire(self) -> None: + assert self._connection is None, "Connection is already acquired" + self._connection = await self._pool.acquire() + + async def release(self) -> None: + assert self._connection is not None, "Connection is not acquired" + await self._pool.release(self._connection) + self._connection = None + + async def fetch_all(self, query: ClauseElement) -> typing.List[typing.Mapping]: + assert self._connection is not None, "Connection is not acquired" + query, args, context = self._compile(query) + + async with self._connection.execute(query, args) as cursor: + rows = await cursor.fetchall() +~~ metadata = ResultMetaData(context, cursor.description) + return [ + RowProxy(metadata, row, metadata._processors, metadata._keymap) + for row in rows + ] + + async def fetch_one(self, query: ClauseElement) -> typing.Optional[typing.Mapping]: + assert self._connection is not None, "Connection is not acquired" + query, args, context = self._compile(query) + + async with self._connection.execute(query, args) as cursor: + row = await cursor.fetchone() + if row is None: + return None +~~ metadata = ResultMetaData(context, cursor.description) + return RowProxy(metadata, row, metadata._processors, metadata._keymap) + + async def execute(self, query: ClauseElement) -> typing.Any: + assert self._connection is not None, "Connection is not acquired" + query, args, context = self._compile(query) + cursor = await self._connection.cursor() + try: + await cursor.execute(query, args) + if cursor.lastrowid == 0: + return cursor.rowcount + return cursor.lastrowid + finally: + await cursor.close() + + async def execute_many(self, queries: typing.List[ClauseElement]) -> None: + assert self._connection is not None, "Connection is not acquired" + for single_query in queries: + await self.execute(single_query) + + async def iterate( + self, query: ClauseElement + ) -> typing.AsyncGenerator[typing.Any, None]: + assert self._connection is not None, "Connection is not acquired" + query, args, context = self._compile(query) + cursor = await self._connection.cursor() + async with self._connection.execute(query, args) as cursor: +~~ metadata = ResultMetaData(context, cursor.description) + async for row in cursor: + yield RowProxy(metadata, row, metadata._processors, metadata._keymap) + + def transaction(self) -> TransactionBackend: + return SQLiteTransaction(self) + + def _compile( + self, query: ClauseElement + ) -> typing.Tuple[str, list, CompilationContext]: + compiled = query.compile(dialect=self._dialect) + args = [] + for key, raw_val in compiled.construct_params().items(): + if key in compiled._bind_processors: + val = compiled._bind_processors[key](raw_val) + else: + val = raw_val + args.append(val) + + execution_context = self._dialect.execution_ctx_cls() + execution_context.dialect = self._dialect + execution_context.result_column_struct = ( + compiled._result_columns, + compiled._ordered_columns, + compiled._textual_ordered_columns, + + +## ... source file continues with no further ResultMetaData examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-result-rowproxy.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-result-rowproxy.markdown new file mode 100644 index 000000000..03c84372a --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-result-rowproxy.markdown @@ -0,0 +1,166 @@ +title: sqlalchemy.engine.result RowProxy Example Code +category: page +slug: sqlalchemy-engine-result-rowproxy-examples +sortorder: 500031029 +toc: False +sidebartitle: sqlalchemy.engine.result RowProxy +meta: Example code for understanding how to use the RowProxy class from the sqlalchemy.engine.result module of the SQLAlchemy project. + + +`RowProxy` is a class within the `sqlalchemy.engine.result` module of the SQLAlchemy project. + +ResultMetaData +is another callable from the `sqlalchemy.engine.result` package with code examples. + +## Example 1 from databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + +[**databases / databases / backends / sqlite.py**](https://github.com/encode/databases/blob/master/databases/backends/sqlite.py) + +```python +# sqlite.py +import logging +import typing +import uuid + +import aiosqlite +from sqlalchemy.dialects.sqlite import pysqlite +from sqlalchemy.engine.interfaces import Dialect, ExecutionContext +~~from sqlalchemy.engine.result import ResultMetaData, RowProxy +from sqlalchemy.sql import ClauseElement +from sqlalchemy.types import TypeEngine + +from databases.core import LOG_EXTRA, DatabaseURL +from databases.interfaces import ConnectionBackend, DatabaseBackend, TransactionBackend + +logger = logging.getLogger("databases") + + +class SQLiteBackend(DatabaseBackend): + def __init__( + self, database_url: typing.Union[DatabaseURL, str], **options: typing.Any + ) -> None: + self._database_url = DatabaseURL(database_url) + self._options = options + self._dialect = pysqlite.dialect(paramstyle="qmark") + self._dialect.supports_native_decimal = False + self._pool = SQLitePool(self._database_url, **self._options) + + async def connect(self) -> None: + pass + + async def disconnect(self) -> None: + pass + + +## ... source file abbreviated to get to RowProxy examples ... + + + + +class SQLiteConnection(ConnectionBackend): + def __init__(self, pool: SQLitePool, dialect: Dialect): + self._pool = pool + self._dialect = dialect + self._connection = None + + async def acquire(self) -> None: + assert self._connection is None, "Connection is already acquired" + self._connection = await self._pool.acquire() + + async def release(self) -> None: + assert self._connection is not None, "Connection is not acquired" + await self._pool.release(self._connection) + self._connection = None + + async def fetch_all(self, query: ClauseElement) -> typing.List[typing.Mapping]: + assert self._connection is not None, "Connection is not acquired" + query, args, context = self._compile(query) + + async with self._connection.execute(query, args) as cursor: + rows = await cursor.fetchall() + metadata = ResultMetaData(context, cursor.description) + return [ +~~ RowProxy(metadata, row, metadata._processors, metadata._keymap) + for row in rows + ] + + async def fetch_one(self, query: ClauseElement) -> typing.Optional[typing.Mapping]: + assert self._connection is not None, "Connection is not acquired" + query, args, context = self._compile(query) + + async with self._connection.execute(query, args) as cursor: + row = await cursor.fetchone() + if row is None: + return None + metadata = ResultMetaData(context, cursor.description) +~~ return RowProxy(metadata, row, metadata._processors, metadata._keymap) + + async def execute(self, query: ClauseElement) -> typing.Any: + assert self._connection is not None, "Connection is not acquired" + query, args, context = self._compile(query) + cursor = await self._connection.cursor() + try: + await cursor.execute(query, args) + if cursor.lastrowid == 0: + return cursor.rowcount + return cursor.lastrowid + finally: + await cursor.close() + + async def execute_many(self, queries: typing.List[ClauseElement]) -> None: + assert self._connection is not None, "Connection is not acquired" + for single_query in queries: + await self.execute(single_query) + + async def iterate( + self, query: ClauseElement + ) -> typing.AsyncGenerator[typing.Any, None]: + assert self._connection is not None, "Connection is not acquired" + query, args, context = self._compile(query) + cursor = await self._connection.cursor() + async with self._connection.execute(query, args) as cursor: + metadata = ResultMetaData(context, cursor.description) + async for row in cursor: +~~ yield RowProxy(metadata, row, metadata._processors, metadata._keymap) + + def transaction(self) -> TransactionBackend: + return SQLiteTransaction(self) + + def _compile( + self, query: ClauseElement + ) -> typing.Tuple[str, list, CompilationContext]: + compiled = query.compile(dialect=self._dialect) + args = [] + for key, raw_val in compiled.construct_params().items(): + if key in compiled._bind_processors: + val = compiled._bind_processors[key](raw_val) + else: + val = raw_val + args.append(val) + + execution_context = self._dialect.execution_ctx_cls() + execution_context.dialect = self._dialect + execution_context.result_column_struct = ( + compiled._result_columns, + compiled._ordered_columns, + compiled._textual_ordered_columns, + ) + + + +## ... source file continues with no further RowProxy examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-strategies-enginestrategy.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-strategies-enginestrategy.markdown new file mode 100644 index 000000000..5453f8ae0 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-strategies-enginestrategy.markdown @@ -0,0 +1,71 @@ +title: sqlalchemy.engine.strategies EngineStrategy Example Code +category: page +slug: sqlalchemy-engine-strategies-enginestrategy-examples +sortorder: 500031030 +toc: False +sidebartitle: sqlalchemy.engine.strategies EngineStrategy +meta: Example code for understanding how to use the EngineStrategy class from the sqlalchemy.engine.strategies module of the SQLAlchemy project. + + +`EngineStrategy` is a class within the `sqlalchemy.engine.strategies` module of the SQLAlchemy project. + +MockEngineStrategy +is another callable from the `sqlalchemy.engine.strategies` package with code examples. + +## Example 1 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / strategies.py**](https://github.com/python-gino/gino/blob/master/src/gino/./strategies.py) + +```python +# strategies.py +import asyncio +from copy import copy + +from sqlalchemy.engine import url +from sqlalchemy import util +~~from sqlalchemy.engine.strategies import EngineStrategy + +from .engine import GinoEngine + + +~~class GinoStrategy(EngineStrategy): + + name = "gino" + engine_cls = GinoEngine + + async def create(self, name_or_url, loop=None, **kwargs): + engine_cls = self.engine_cls + u = url.make_url(name_or_url) + if loop is None: + loop = asyncio.get_event_loop() + if u.drivername in {"postgresql", "postgres"}: + u = copy(u) + u.drivername = "postgresql+asyncpg" + + dialect_cls = u.get_dialect() + + pop_kwarg = kwargs.pop + + dialect_args = {} + for k in util.get_cls_kwargs(dialect_cls).union( + getattr(dialect_cls, "init_kwargs", set()) + ): + if k in kwargs: + dialect_args[k] = pop_kwarg(k) + + + +## ... source file continues with no further EngineStrategy examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-strategies-mockenginestrategy.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-strategies-mockenginestrategy.markdown new file mode 100644 index 000000000..c77a9c45a --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-strategies-mockenginestrategy.markdown @@ -0,0 +1,69 @@ +title: sqlalchemy.engine.strategies MockEngineStrategy Example Code +category: page +slug: sqlalchemy-engine-strategies-mockenginestrategy-examples +sortorder: 500031031 +toc: False +sidebartitle: sqlalchemy.engine.strategies MockEngineStrategy +meta: Example code for understanding how to use the MockEngineStrategy class from the sqlalchemy.engine.strategies module of the SQLAlchemy project. + + +`MockEngineStrategy` is a class within the `sqlalchemy.engine.strategies` module of the SQLAlchemy project. + +EngineStrategy +is another callable from the `sqlalchemy.engine.strategies` package with code examples. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / runtime / migration.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/runtime/migration.py) + +```python +# migration.py +from contextlib import contextmanager +import logging +import sys + +from sqlalchemy import Column +from sqlalchemy import literal_column +from sqlalchemy import MetaData +from sqlalchemy import PrimaryKeyConstraint +from sqlalchemy import String +from sqlalchemy import Table +from sqlalchemy.engine import Connection +from sqlalchemy.engine import url as sqla_url +~~from sqlalchemy.engine.strategies import MockEngineStrategy + +from .. import ddl +from .. import util +from ..util import sqla_compat +from ..util.compat import callable +from ..util.compat import EncodedIO + +log = logging.getLogger(__name__) + + +class _ProxyTransaction(object): + def __init__(self, migration_context): + self.migration_context = migration_context + + @property + def _proxied_transaction(self): + return self.migration_context._transaction + + def rollback(self): + self._proxied_transaction.rollback() + + def commit(self): + self._proxied_transaction.commit() + + + +## ... source file continues with no further MockEngineStrategy examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-url-make-url.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-url-make-url.markdown new file mode 100644 index 000000000..b6f1e3f2e --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-url-make-url.markdown @@ -0,0 +1,351 @@ +title: sqlalchemy.engine.url make_url Example Code +category: page +slug: sqlalchemy-engine-url-make-url-examples +sortorder: 500031032 +toc: False +sidebartitle: sqlalchemy.engine.url make_url +meta: Python example code that shows how to use the make_url callable from the sqlalchemy.engine.url module of the SQLAlchemy project. + + +`make_url` is a callable within the `sqlalchemy.engine.url` module of the SQLAlchemy project. + + + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [SQLAlchemy](/sqlalchemy.html) and [Flask](/flask.html). +The application can be used as-is to run CTF events, or the code can be +modified for custom rules on hacking scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / tests / helpers.py**](https://github.com/CTFd/CTFd/blob/master/./tests/helpers.py) + +```python +# helpers.py +import datetime +import gc +import random +import string +import uuid +from collections import namedtuple +from unittest.mock import Mock, patch + +import requests +from flask.testing import FlaskClient +~~from sqlalchemy.engine.url import make_url +from sqlalchemy_utils import drop_database +from werkzeug.datastructures import Headers + +from CTFd import create_app +from CTFd.cache import cache, clear_standings +from CTFd.config import TestingConfig +from CTFd.models import ( + Awards, + ChallengeFiles, + Challenges, + Fails, + Files, + Flags, + Hints, + Notifications, + PageFiles, + Pages, + Solves, + Tags, + Teams, + Tokens, + Tracking, + Unlocks, + Users, + + +## ... source file abbreviated to get to make_url examples ... + + + if isinstance(headers, dict): + headers = Headers(headers) + headers.extend(api_key_headers) + kwargs["headers"] = headers + return super(CTFdTestClient, self).open(*args, **kwargs) + + +def create_ctfd( + ctf_name="CTFd", + ctf_description="CTF description", + name="admin", + email="admin@ctfd.io", + password="password", + user_mode="users", + setup=True, + enable_plugins=False, + application_root="/", + config=TestingConfig, +): + if enable_plugins: + config.SAFE_MODE = False + else: + config.SAFE_MODE = True + + config.APPLICATION_ROOT = application_root +~~ url = make_url(config.SQLALCHEMY_DATABASE_URI) + if url.database: + url.database = str(uuid.uuid4()) + config.SQLALCHEMY_DATABASE_URI = str(url) + + app = create_app(config) + app.test_client_class = CTFdTestClient + + if setup: + app = setup_ctfd( + app, + ctf_name=ctf_name, + ctf_description=ctf_description, + name=name, + email=email, + password=password, + user_mode=user_mode, + ) + return app + + +def setup_ctfd( + app, + ctf_name="CTFd", + ctf_description="CTF description", + + +## ... source file continues with no further make_url examples... + +``` + + +## Example 2 from flask-sqlalchemy +[flask-sqlalchemy](https://github.com/pallets/flask-sqlalchemy) +([project documentation](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) +and +[PyPI information](https://pypi.org/project/Flask-SQLAlchemy/)) is a +[Flask](/flask.html) extension that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) when building Flask apps. flask-sqlalchemy +provides helper functions that reduce the amount of common boilerplate +code that you have to frequently write yourself if you did not use this +library when combining Flask with SQLAlchemy. + +flask-sqlalchemy is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/pallets/flask-sqlalchemy/blob/master/LICENSE.rst). + +[**flask-sqlalchemy / src/flask_sqlalchemy / __init__.py**](https://github.com/pallets/flask-sqlalchemy/blob/master/src/flask_sqlalchemy/./__init__.py) + +```python +# __init__.py +import functools +import os +import sys +import warnings +from math import ceil +from operator import itemgetter +from threading import Lock +from time import perf_counter + +import sqlalchemy +from flask import _app_ctx_stack +from flask import abort +from flask import current_app +from flask import request +from flask.signals import Namespace +from sqlalchemy import event +from sqlalchemy import inspect +from sqlalchemy import orm +~~from sqlalchemy.engine.url import make_url +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.declarative import DeclarativeMeta +from sqlalchemy.orm.exc import UnmappedClassError +from sqlalchemy.orm.session import Session as SessionBase + +from .model import DefaultMeta +from .model import Model + +__version__ = "3.0.0.dev" + +_signals = Namespace() +models_committed = _signals.signal("models-committed") +before_models_committed = _signals.signal("before-models-committed") + + +def _make_table(db): + def _make_table(*args, **kwargs): + if len(args) > 1 and isinstance(args[1], db.Column): + args = (args[0], db.metadata) + args[1:] + info = kwargs.pop("info", None) or {} + info.setdefault("bind_key", None) + kwargs["info"] = info + return sqlalchemy.Table(*args, **kwargs) + + + +## ... source file abbreviated to get to make_url examples ... + + +class _EngineConnector: + def __init__(self, sa, app, bind=None): + self._sa = sa + self._app = app + self._engine = None + self._connected_for = None + self._bind = bind + self._lock = Lock() + + def get_uri(self): + if self._bind is None: + return self._app.config["SQLALCHEMY_DATABASE_URI"] + binds = self._app.config.get("SQLALCHEMY_BINDS") or () + assert ( + self._bind in binds + ), f"Bind {self._bind!r} is not configured in 'SQLALCHEMY_BINDS'." + return binds[self._bind] + + def get_engine(self): + with self._lock: + uri = self.get_uri() + echo = self._app.config["SQLALCHEMY_ECHO"] + if (uri, echo) == self._connected_for: + return self._engine + +~~ sa_url = make_url(uri) + options = self.get_options(sa_url, echo) + self._engine = rv = self._sa.create_engine(sa_url, options) + + if _record_queries(self._app): + _EngineDebuggingSignalEvents( + self._engine, self._app.import_name + ).register() + + self._connected_for = (uri, echo) + + return rv + + def get_options(self, sa_url, echo): + options = {} + + self._sa.apply_driver_hacks(self._app, sa_url, options) + + if echo: + options["echo"] = echo + + options.update(self._app.config["SQLALCHEMY_ENGINE_OPTIONS"]) + options.update(self._sa._engine_options) + return options + + + +## ... source file continues with no further make_url examples... + +``` + + +## Example 3 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / api.py**](https://github.com/python-gino/gino/blob/master/src/gino/./api.py) + +```python +# api.py +import weakref + +import sqlalchemy as sa +~~from sqlalchemy.engine.url import make_url, URL +from sqlalchemy.sql.base import Executable +from sqlalchemy.sql.schema import SchemaItem + +from . import json_support +from .crud import CRUDModel +from .declarative import declarative_base, declared_attr +from .exceptions import UninitializedError +from .schema import GinoSchemaVisitor, patch_schema + + +class GinoExecutor: + + __slots__ = ("_query",) + + def __init__(self, query): + self._query = query + + @property + def query(self): + return self._query + + def model(self, model): + if model is not None: + model = weakref.ref(model) + + +## ... source file abbreviated to get to make_url examples ... + + + if not hasattr(self, key) and key not in self.no_delegate: + setattr(self, key, getattr(mod, key)) + if ext: + if query_ext: + Executable.gino = property(self.query_executor) + if schema_ext: + SchemaItem.gino = property(self.schema_visitor) + patch_schema(self) + + @property + def Model(self): + return self._model + + @property + def bind(self): + if self._bind is None: + return _PlaceHolder(UninitializedError("Gino engine is not initialized.")) + return self._bind + + @bind.setter + def bind(self, bind): + self._bind = bind + + async def set_bind(self, bind, loop=None, **kwargs): + if isinstance(bind, str): +~~ bind = make_url(bind) + if isinstance(bind, URL): + from . import create_engine + + bind = await create_engine(bind, loop=loop, bakery=self._bakery, **kwargs) + self.bind = bind + return bind + + def pop_bind(self): + from .bakery import Bakery + + self._bakery = Bakery() + bind, self.bind = self.bind, None + return bind + + def with_bind(self, bind, loop=None, **kwargs): + return _BindContext(self, bind, loop, kwargs) + + def __await__(self): + async def init(): + await self.set_bind(self.bind) + return self + + return init().__await__() + + + +## ... source file continues with no further make_url examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-engine-url.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-engine-url.markdown new file mode 100644 index 000000000..01147201f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-engine-url.markdown @@ -0,0 +1,185 @@ +title: sqlalchemy.engine url Example Code +category: page +slug: sqlalchemy-engine-url-examples +sortorder: 500031025 +toc: False +sidebartitle: sqlalchemy.engine url +meta: Python example code that shows how to use the url callable from the sqlalchemy.engine module of the SQLAlchemy project. + + +`url` is a callable within the `sqlalchemy.engine` module of the SQLAlchemy project. + +Connection, +Engine, +create_engine, +and default +are several other callables with code examples from the same `sqlalchemy.engine` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / util / messaging.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/util/messaging.py) + +```python +# messaging.py +import logging +import sys +import textwrap +import warnings + +~~from sqlalchemy.engine import url + +from .compat import binary_type +from .compat import collections_abc +from .compat import py27 +from .compat import string_types + +log = logging.getLogger(__name__) + +if py27: + logging.getLogger("alembic").addHandler(logging.NullHandler()) + + +try: + import fcntl + import termios + import struct + + ioctl = fcntl.ioctl(0, termios.TIOCGWINSZ, struct.pack("HHHH", 0, 0, 0, 0)) + _h, TERMWIDTH, _hp, _wp = struct.unpack("HHHH", ioctl) + if TERMWIDTH <= 0: # can occur if running in emacs pseudo-tty + TERMWIDTH = None +except (ImportError, IOError): + TERMWIDTH = None + + + +## ... source file abbreviated to get to url examples ... + + + try: + stream.write(t) + except IOError: + break + + +def status(_statmsg, fn, *arg, **kw): + newline = kw.pop("newline", False) + msg(_statmsg + " ...", newline, True) + try: + ret = fn(*arg, **kw) + write_outstream(sys.stdout, " done\n") + return ret + except: + write_outstream(sys.stdout, " FAILED\n") + raise + + +def err(message): + log.error(message) + msg("FAILED: %s" % message) + sys.exit(-1) + + +def obfuscate_url_pw(u): +~~ u = url.make_url(u) + if u.password: + u.password = "XXXXX" + return str(u) + + +def warn(msg, stacklevel=2): + warnings.warn(msg, UserWarning, stacklevel=stacklevel) + + +def msg(msg, newline=True, flush=False): + if TERMWIDTH is None: + write_outstream(sys.stdout, msg) + if newline: + write_outstream(sys.stdout, "\n") + else: + lines = textwrap.wrap(msg, TERMWIDTH) + if len(lines) > 1: + for line in lines[0:-1]: + write_outstream(sys.stdout, " ", line, "\n") + write_outstream(sys.stdout, " ", lines[-1], ("\n" if newline else "")) + if flush: + sys.stdout.flush() + + + + +## ... source file continues with no further url examples... + +``` + + +## Example 2 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / strategies.py**](https://github.com/python-gino/gino/blob/master/src/gino/./strategies.py) + +```python +# strategies.py +import asyncio +from copy import copy + +~~from sqlalchemy.engine import url +from sqlalchemy import util +from sqlalchemy.engine.strategies import EngineStrategy + +from .engine import GinoEngine + + +class GinoStrategy(EngineStrategy): + + name = "gino" + engine_cls = GinoEngine + + async def create(self, name_or_url, loop=None, **kwargs): + engine_cls = self.engine_cls +~~ u = url.make_url(name_or_url) + if loop is None: + loop = asyncio.get_event_loop() + if u.drivername in {"postgresql", "postgres"}: + u = copy(u) + u.drivername = "postgresql+asyncpg" + + dialect_cls = u.get_dialect() + + pop_kwarg = kwargs.pop + + dialect_args = {} + for k in util.get_cls_kwargs(dialect_cls).union( + getattr(dialect_cls, "init_kwargs", set()) + ): + if k in kwargs: + dialect_args[k] = pop_kwarg(k) + + kwargs.pop("module", None) # unused + dbapi_args = {} + for k in util.get_func_kwargs(dialect_cls.dbapi): + if k in kwargs: + dbapi_args[k] = pop_kwarg(k) + dbapi = dialect_cls.dbapi(**dbapi_args) + dialect_args["dbapi"] = dbapi + + +## ... source file continues with no further url examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-events-schemaeventtarget.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-events-schemaeventtarget.markdown new file mode 100644 index 000000000..89499101a --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-events-schemaeventtarget.markdown @@ -0,0 +1,176 @@ +title: sqlalchemy.events SchemaEventTarget Example Code +category: page +slug: sqlalchemy-events-schemaeventtarget-examples +sortorder: 500031033 +toc: False +sidebartitle: sqlalchemy.events SchemaEventTarget +meta: Example code for understanding how to use the SchemaEventTarget class from the sqlalchemy.events module of the SQLAlchemy project. + + +`SchemaEventTarget` is a class within the `sqlalchemy.events` module of the SQLAlchemy project. + + + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / operations / batch.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/operations/batch.py) + +```python +# batch.py +from sqlalchemy import CheckConstraint +from sqlalchemy import Column +from sqlalchemy import ForeignKeyConstraint +from sqlalchemy import Index +from sqlalchemy import MetaData +from sqlalchemy import PrimaryKeyConstraint +from sqlalchemy import schema as sql_schema +from sqlalchemy import select +from sqlalchemy import Table +from sqlalchemy import types as sqltypes +~~from sqlalchemy.events import SchemaEventTarget +from sqlalchemy.util import OrderedDict +from sqlalchemy.util import topological + +from ..util import exc +from ..util.sqla_compat import _columns_for_constraint +from ..util.sqla_compat import _fk_is_self_referential +from ..util.sqla_compat import _is_type_bound +from ..util.sqla_compat import _remove_column_from_collection + + +class BatchOperationsImpl(object): + def __init__( + self, + operations, + table_name, + schema, + recreate, + copy_from, + table_args, + table_kwargs, + reflect_args, + reflect_kwargs, + naming_convention, + partial_reordering, + + +## ... source file abbreviated to get to SchemaEventTarget examples ... + + + self.table_kwargs = table_kwargs + self.temp_table_name = self._calc_temp_name(table.name) + self.new_table = None + + self.partial_reordering = partial_reordering # tuple of tuples + self.add_col_ordering = () # tuple of tuples + + self.column_transfers = OrderedDict( + (c.name, {"expr": c}) for c in self.table.c + ) + self.existing_ordering = list(self.column_transfers) + + self.reflected = reflected + self._grab_table_elements() + + @classmethod + def _calc_temp_name(cls, tablename): + return ("_alembic_tmp_%s" % tablename)[0:50] + + def _grab_table_elements(self): + schema = self.table.schema + self.columns = OrderedDict() + for c in self.table.c: + c_copy = c.copy(schema=schema) + c_copy.unique = c_copy.index = False +~~ if isinstance(c.type, SchemaEventTarget): + assert c_copy.type is not c.type + self.columns[c.name] = c_copy + self.named_constraints = {} + self.unnamed_constraints = [] + self.indexes = {} + self.new_indexes = {} + for const in self.table.constraints: + if _is_type_bound(const): + continue + elif self.reflected and isinstance(const, CheckConstraint): + pass + elif const.name: + self.named_constraints[const.name] = const + else: + self.unnamed_constraints.append(const) + + for idx in self.table.indexes: + self.indexes[idx.name] = idx + + for k in self.table.kwargs: + self.table_kwargs.setdefault(k, self.table.kwargs[k]) + + def _adjust_self_columns_for_partial_reordering(self): + pairs = set() + + +## ... source file abbreviated to get to SchemaEventTarget examples ... + + + try: + for idx in self._gather_indexes_from_both_tables(): + op_impl.create_index(idx) + finally: + self.new_table.name = self.temp_table_name + + def alter_column( + self, + table_name, + column_name, + nullable=None, + server_default=False, + name=None, + type_=None, + autoincrement=None, + **kw + ): + existing = self.columns[column_name] + existing_transfer = self.column_transfers[column_name] + if name is not None and name != column_name: + existing.name = name + existing_transfer["name"] = name + + if type_ is not None: + type_ = sqltypes.to_instance(type_) +~~ if isinstance(existing.type, SchemaEventTarget): + existing.type._create_events = ( + existing.type.create_constraint + ) = False + + self.impl.cast_for_batch_migrate( + existing, existing_transfer, type_ + ) + + existing.type = type_ + + + if nullable is not None: + existing.nullable = nullable + if server_default is not False: + if server_default is None: + existing.server_default = None + else: + sql_schema.DefaultClause(server_default)._set_parent(existing) + if autoincrement is not None: + existing.autoincrement = bool(autoincrement) + + def _setup_dependencies_for_add_column( + self, colname, insert_before, insert_after + ): + + +## ... source file continues with no further SchemaEventTarget examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-example-projects-code.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-example-projects-code.markdown index 910439fa7..13f311143 100644 --- a/content/pages/examples/sqlalchemy/sqlalchemy-example-projects-code.markdown +++ b/content/pages/examples/sqlalchemy/sqlalchemy-example-projects-code.markdown @@ -1,21 +1,51 @@ title: SQLAlchemy Example Projects and Code category: page -slug: sqlalchemy-projects-code-examples +slug: sqlalchemy-code-examples sortorder: 500030001 toc: False sidebartitle: SQLAlchemy Example Code meta: Python example projects and code that show how to use the SQLAlchemy object-relational mapper (ORM). -[SQLAlchemy](/sqlalchemy.html) is a Python library for interacting -with [databases](/databases.html) either through SQL or with an -[object-relational mapper (ORM)](/object-relational-mappers-orms.html). +## Example Open Source Projects +The following open source projects can serve as example code for you as +you build your own applications with SQLAlchemy. -SQLAlchemy logo. -This page describes projects that use SQLAlchemy to accomplish some -goal, such as data analysis, running a web application's back end, -or providing a [web API](/application-programming-interfaces.html). +### databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + + +### CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [SQLAlchemy](/sqlalchemy.html) and [Flask](/flask.html). +The application can be used as-is to run CTF events, or the code can be +modified for custom rules on hacking scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + + +### indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management that is +powered by [SQLAlchemy](/sqlalchemy.html) on the backend. The code +for this project is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). ### sandman2 diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-exc-argumenterror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-exc-argumenterror.markdown new file mode 100644 index 000000000..12e57d3a7 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-exc-argumenterror.markdown @@ -0,0 +1,108 @@ +title: sqlalchemy.exc ArgumentError Example Code +category: page +slug: sqlalchemy-exc-argumenterror-examples +sortorder: 500031034 +toc: False +sidebartitle: sqlalchemy.exc ArgumentError +meta: Example code for understanding how to use the ArgumentError class from the sqlalchemy.exc module of the SQLAlchemy project. + + +`ArgumentError` is a class within the `sqlalchemy.exc` module of the SQLAlchemy project. + +DataError, +DatabaseError, +IntegrityError, +InvalidRequestError, +NoInspectionAvailable, +NoSuchTableError, +OperationalError, +ProgrammingError, +and UnsupportedCompilationError +are several other callables with code examples from the same `sqlalchemy.exc` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / utils.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./utils.py) + +```python +# utils.py +import re +import warnings + +~~from sqlalchemy.exc import ArgumentError +from sqlalchemy.orm import class_mapper, object_mapper +from sqlalchemy.orm.exc import UnmappedClassError, UnmappedInstanceError + + +def get_session(context): + return context.get("session") + + +def get_query(model, context): + query = getattr(model, "query", None) + if not query: + session = get_session(context) + if not session: + raise Exception( + "A query in the model Base or a session in the schema is required for querying.\n" + "Read more http://docs.graphene-python.org/projects/sqlalchemy/en/latest/tips/#querying" + ) + query = session.query(model) + return query + + +def is_mapped_class(cls): + try: + class_mapper(cls) +~~ except (ArgumentError, UnmappedClassError): + return False + else: + return True + + +def is_mapped_instance(cls): + try: + object_mapper(cls) +~~ except (ArgumentError, UnmappedInstanceError): + return False + else: + return True + + +def to_type_name(name): + return "".join(part[:1].upper() + part[1:] for part in name.split("_")) + + +_re_enum_value_name_1 = re.compile("(.)([A-Z][a-z]+)") +_re_enum_value_name_2 = re.compile("([a-z0-9])([A-Z])") + + +def to_enum_value_name(name): + return _re_enum_value_name_2.sub( + r"\1_\2", _re_enum_value_name_1.sub(r"\1_\2", name) + ).upper() + + +class EnumValue(str): + + def __new__(cls, s, value): + return super(EnumValue, cls).__new__(cls, s) + + + +## ... source file continues with no further ArgumentError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-exc-databaseerror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-exc-databaseerror.markdown new file mode 100644 index 000000000..843f67e78 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-exc-databaseerror.markdown @@ -0,0 +1,134 @@ +title: sqlalchemy.exc DatabaseError Example Code +category: page +slug: sqlalchemy-exc-databaseerror-examples +sortorder: 500031036 +toc: False +sidebartitle: sqlalchemy.exc DatabaseError +meta: Example code for understanding how to use the DatabaseError class from the sqlalchemy.exc module of the SQLAlchemy project. + + +`DatabaseError` is a class within the `sqlalchemy.exc` module of the SQLAlchemy project. + +ArgumentError, +DataError, +IntegrityError, +InvalidRequestError, +NoInspectionAvailable, +NoSuchTableError, +OperationalError, +ProgrammingError, +and UnsupportedCompilationError +are several other callables with code examples from the same `sqlalchemy.exc` package. + +## Example 1 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management that is +powered by [SQLAlchemy](/sqlalchemy.html) on the backend. The code +for this project is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / web / rh.py**](https://github.com/indico/indico/blob/master/indico/web/rh.py) + +```python +# rh.py + +from __future__ import absolute_import, unicode_literals + +import cProfile +import inspect +import itertools +import os +import time +from functools import partial, wraps + +import jsonschema +from flask import current_app, g, redirect, request, session +~~from sqlalchemy.exc import DatabaseError +from sqlalchemy.orm.exc import NoResultFound +from werkzeug.exceptions import BadRequest, Forbidden, MethodNotAllowed, NotFound +from werkzeug.routing import BuildError +from werkzeug.wrappers import Response + +from indico.core import signals +from indico.core.config import config +from indico.core.db import db +from indico.core.db.sqlalchemy.core import handle_sqlalchemy_database_error +from indico.core.logger import Logger, sentry_set_tags +from indico.core.notifications import flush_email_queue, init_email_queue +from indico.util import fossilize +from indico.util.i18n import _ +from indico.util.locators import get_locator +from indico.util.signals import values_from_signal +from indico.web.flask.util import url_for +from indico.web.util import is_signed_url_valid + + +HTTP_VERBS = {'GET', 'PATCH', 'POST', 'PUT', 'DELETE'} +logger = Logger.get('rh') + + +class RH(object): + + +## ... source file abbreviated to get to DatabaseError examples ... + + + if request.method not in HTTP_VERBS: + raise BadRequest + + res = '' + g.rh = self + sentry_set_tags({'rh': self.__class__.__name__}) + + if self.EVENT_FEATURE is not None: + self._check_event_feature() + + logger.info('%s %s [IP=%s] [PID=%s] [UID=%r]', + request.method, request.relative_url, request.remote_addr, os.getpid(), session.get('_user_id')) + + try: + fossilize.clearCache() + init_email_queue() + self._check_csrf() + res = self._do_process() + signals.after_process.send() + + if self.commit: + db.session.commit() + flush_email_queue() + else: + db.session.rollback() +~~ except DatabaseError: + db.session.rollback() + handle_sqlalchemy_database_error() # this will re-raise an exception + except Exception: + db.session.rollback() + raise + logger.debug('Request successful') + + if res is None: + res = '' + + response = current_app.make_response(res) + if self.DENY_FRAMES: + response.headers['X-Frame-Options'] = 'DENY' + return response + + +class RHSimple(RH): + def __init__(self, func): + RH.__init__(self) + self.func = func + + def _process(self): + rv = self.func() + return rv + + +## ... source file continues with no further DatabaseError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-exc-dataerror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-exc-dataerror.markdown new file mode 100644 index 000000000..9e9ba71dd --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-exc-dataerror.markdown @@ -0,0 +1,75 @@ +title: sqlalchemy.exc DataError Example Code +category: page +slug: sqlalchemy-exc-dataerror-examples +sortorder: 500031035 +toc: False +sidebartitle: sqlalchemy.exc DataError +meta: Example code for understanding how to use the DataError class from the sqlalchemy.exc module of the SQLAlchemy project. + + +`DataError` is a class within the `sqlalchemy.exc` module of the SQLAlchemy project. + +ArgumentError, +DatabaseError, +IntegrityError, +InvalidRequestError, +NoInspectionAvailable, +NoSuchTableError, +OperationalError, +ProgrammingError, +and UnsupportedCompilationError +are several other callables with code examples from the same `sqlalchemy.exc` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / asserts.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./asserts.py) + +```python +# asserts.py +from decimal import Decimal + +import sqlalchemy as sa +from sqlalchemy.dialects.postgresql import ARRAY +~~from sqlalchemy.exc import DataError, IntegrityError + + +def _update_field(obj, field, value): + session = sa.orm.object_session(obj) + column = sa.inspect(obj.__class__).columns[field] + query = column.table.update().values(**{column.key: value}) + session.execute(query) + session.flush() + + +def _expect_successful_update(obj, field, value, reraise_exc): + try: + _update_field(obj, field, value) + except (reraise_exc) as e: + session = sa.orm.object_session(obj) + session.rollback() + assert False, str(e) + + +def _expect_failing_update(obj, field, value, expected_exc): + try: + _update_field(obj, field, value) + except expected_exc: + pass + + +## ... source file continues with no further DataError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-exc-integrityerror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-exc-integrityerror.markdown new file mode 100644 index 000000000..88658c4f4 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-exc-integrityerror.markdown @@ -0,0 +1,321 @@ +title: sqlalchemy.exc IntegrityError Example Code +category: page +slug: sqlalchemy-exc-integrityerror-examples +sortorder: 500031037 +toc: False +sidebartitle: sqlalchemy.exc IntegrityError +meta: Example code for understanding how to use the IntegrityError class from the sqlalchemy.exc module of the SQLAlchemy project. + + +`IntegrityError` is a class within the `sqlalchemy.exc` module of the SQLAlchemy project. + +ArgumentError, +DataError, +DatabaseError, +InvalidRequestError, +NoInspectionAvailable, +NoSuchTableError, +OperationalError, +ProgrammingError, +and UnsupportedCompilationError +are several other callables with code examples from the same `sqlalchemy.exc` package. + +## Example 1 from CTFd +[CTFd](https://github.com/CTFd/CTFd) +([homepage](https://ctfd.io/)) is a +[capture the flag (CTF) hacking web app](https://cybersecurity.att.com/blogs/security-essentials/capture-the-flag-ctf-what-is-it-for-a-newbie) +built with [SQLAlchemy](/sqlalchemy.html) and [Flask](/flask.html). +The application can be used as-is to run CTF events, or the code can be +modified for custom rules on hacking scenarios. CTFd is open sourced under the +[Apache License 2.0](https://github.com/CTFd/CTFd/blob/master/LICENSE). + +[**CTFd / CTFd / views.py**](https://github.com/CTFd/CTFd/blob/master/./CTFd/views.py) + +```python +# views.py +import os + +from flask import Blueprint, abort +from flask import current_app as app +from flask import redirect, render_template, request, send_file, session, url_for +from flask.helpers import safe_join +~~from sqlalchemy.exc import IntegrityError + +from CTFd.cache import cache +from CTFd.constants.config import ( + AccountVisibilityTypes, + ChallengeVisibilityTypes, + ConfigTypes, + RegistrationVisibilityTypes, + ScoreVisibilityTypes, +) +from CTFd.models import ( + Admins, + Files, + Notifications, + Pages, + Teams, + Users, + UserTokens, + db, +) +from CTFd.utils import config, get_config, set_config +from CTFd.utils import user as current_user +from CTFd.utils import validators +from CTFd.utils.config import is_setup +from CTFd.utils.config.pages import get_page + + +## ... source file abbreviated to get to IntegrityError examples ... + + + set_config( + "user_creation_email_subject", DEFAULT_USER_CREATION_EMAIL_SUBJECT + ) + set_config("user_creation_email_body", DEFAULT_USER_CREATION_EMAIL_BODY) + + set_config("password_reset_subject", DEFAULT_PASSWORD_RESET_SUBJECT) + set_config("password_reset_body", DEFAULT_PASSWORD_RESET_BODY) + + set_config( + "password_change_alert_subject", + "Password Change Confirmation for {ctf_name}", + ) + set_config( + "password_change_alert_body", + ( + "Your password for {ctf_name} has been changed.\n\n" + "If you didn't request a password change you can reset your password here: {url}" + ), + ) + + set_config("setup", True) + + try: + db.session.add(admin) + db.session.commit() +~~ except IntegrityError: + db.session.rollback() + + try: + db.session.add(page) + db.session.commit() +~~ except IntegrityError: + db.session.rollback() + + login_user(admin) + + db.session.close() + with app.app_context(): + cache.clear() + + return redirect(url_for("views.static_html")) + return render_template("setup.html", state=serialize(generate_nonce())) + return redirect(url_for("views.static_html")) + + +@views.route("/setup/integrations", methods=["GET", "POST"]) +def integrations(): + if is_admin() or is_setup() is False: + name = request.values.get("name") + state = request.values.get("state") + + try: + state = unserialize(state, max_age=3600) + except (BadSignature, BadTimeSignature): + state = False + except Exception: + + +## ... source file continues with no further IntegrityError examples... + +``` + + +## Example 2 from flask-base +[flask-base](https://github.com/hack4impact/flask-base) +([project documentation](http://hack4impact.github.io/flask-base/)) +provides boilerplate code for new [Flask](/flask.html) web apps. +The purpose of the boilerplate is to stitch together disparate +libraries that are commonly used in Flask projects, such as +[Redis](/redis.html) for fast caching and transient data storage, +[SendGrid](https://www.twilio.com/sendgrid) for transactional email, +[SQLAlchemy](/sqlalchemy.html) for persistent data storage through a +[relational database](/databases.html) backend, +[Flask-WTF](https://flask-wtf.readthedocs.io/) for form +handling and many others. + +flask-base is provided as open source under the +[MIT license](https://github.com/hack4impact/flask-base/blob/master/LICENSE.md). + +[**flask-base / app / models / user.py**](https://github.com/hack4impact/flask-base/blob/master/app/models/user.py) + +```python +# user.py +from flask import current_app +from flask_login import AnonymousUserMixin, UserMixin +from itsdangerous import TimedJSONWebSignatureSerializer as Serializer +from itsdangerous import BadSignature, SignatureExpired +from werkzeug.security import check_password_hash, generate_password_hash + +from .. import db, login_manager + + +class Permission: + GENERAL = 0x01 + ADMINISTER = 0xff + + +class Role(db.Model): + __tablename__ = 'roles' + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(64), unique=True) + index = db.Column(db.String(64)) + default = db.Column(db.Boolean, default=False, index=True) + permissions = db.Column(db.Integer) + users = db.relationship('User', backref='role', lazy='dynamic') + + @staticmethod + def insert_roles(): + roles = { + 'User': (Permission.GENERAL, 'main', True), + 'Administrator': ( + Permission.ADMINISTER, + 'admin', + False # grants all permissions + ) + } + for r in roles: + role = Role.query.filter_by(name=r).first() + + +## ... source file abbreviated to get to IntegrityError examples ... + + + new_email = data.get('new_email') + if new_email is None: + return False + if self.query.filter_by(email=new_email).first() is not None: + return False + self.email = new_email + db.session.add(self) + db.session.commit() + return True + + def reset_password(self, token, new_password): + s = Serializer(current_app.config['SECRET_KEY']) + try: + data = s.loads(token) + except (BadSignature, SignatureExpired): + return False + if data.get('reset') != self.id: + return False + self.password = new_password + db.session.add(self) + db.session.commit() + return True + + @staticmethod + def generate_fake(count=100, **kwargs): +~~ from sqlalchemy.exc import IntegrityError + from random import seed, choice + from faker import Faker + + fake = Faker() + roles = Role.query.all() + + seed() + for i in range(count): + u = User( + first_name=fake.first_name(), + last_name=fake.last_name(), + email=fake.email(), + password='password', + confirmed=True, + role=choice(roles), + **kwargs) + db.session.add(u) + try: + db.session.commit() +~~ except IntegrityError: + db.session.rollback() + + def __repr__(self): + return '' % self.full_name() + + +class AnonymousUser(AnonymousUserMixin): + def can(self, _): + return False + + def is_admin(self): + return False + + +login_manager.anonymous_user = AnonymousUser + + +@login_manager.user_loader +def load_user(user_id): + return User.query.get(int(user_id)) + + + +## ... source file continues with no further IntegrityError examples... + +``` + + +## Example 3 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / asserts.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./asserts.py) + +```python +# asserts.py +from decimal import Decimal + +import sqlalchemy as sa +from sqlalchemy.dialects.postgresql import ARRAY +~~from sqlalchemy.exc import DataError, IntegrityError + + +def _update_field(obj, field, value): + session = sa.orm.object_session(obj) + column = sa.inspect(obj.__class__).columns[field] + query = column.table.update().values(**{column.key: value}) + session.execute(query) + session.flush() + + +def _expect_successful_update(obj, field, value, reraise_exc): + try: + _update_field(obj, field, value) + except (reraise_exc) as e: + session = sa.orm.object_session(obj) + session.rollback() + assert False, str(e) + + +def _expect_failing_update(obj, field, value, expected_exc): + try: + _update_field(obj, field, value) + except expected_exc: + pass + + +## ... source file continues with no further IntegrityError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-exc-invalidrequesterror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-exc-invalidrequesterror.markdown new file mode 100644 index 000000000..e83fb9b45 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-exc-invalidrequesterror.markdown @@ -0,0 +1,265 @@ +title: sqlalchemy.exc InvalidRequestError Example Code +category: page +slug: sqlalchemy-exc-invalidrequesterror-examples +sortorder: 500031038 +toc: False +sidebartitle: sqlalchemy.exc InvalidRequestError +meta: Example code for understanding how to use the InvalidRequestError class from the sqlalchemy.exc module of the SQLAlchemy project. + + +`InvalidRequestError` is a class within the `sqlalchemy.exc` module of the SQLAlchemy project. + +ArgumentError, +DataError, +DatabaseError, +IntegrityError, +NoInspectionAvailable, +NoSuchTableError, +OperationalError, +ProgrammingError, +and UnsupportedCompilationError +are several other callables with code examples from the same `sqlalchemy.exc` package. + +## Example 1 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / declarative.py**](https://github.com/python-gino/gino/blob/master/src/gino/./declarative.py) + +```python +# declarative.py +import collections + +import sqlalchemy as sa +~~from sqlalchemy.exc import InvalidRequestError + +from . import json_support +from .exceptions import GinoException + + +class ColumnAttribute: + + def __init__(self, prop_name, column): + self.prop_name = prop_name + self.column = column + + def __get__(self, instance, owner): + if instance is None: + return self.column + else: + return instance.__values__.get(self.prop_name) + + def __set__(self, instance, value): + instance.__values__[self.prop_name] = value + + def __delete__(self, instance): + raise AttributeError("Cannot delete value.") + + + + +## ... source file abbreviated to get to InvalidRequestError examples ... + + + updates[k] = sub_cls.__attr_factory__(k, v) + elif isinstance(v, (sa.Index, sa.Constraint)): + inspected_args.append(v) + elif isinstance(v, json_support.JSONProperty): + updates[k] = v + if table_name is None: + return + sub_cls._column_name_map = column_name_map + + table_args = updates.get( + "__table_args__", getattr(sub_cls, "__table_args__", None) + ) + args, table_kw = (), {} + if isinstance(table_args, dict): + table_kw = table_args + elif isinstance(table_args, tuple) and table_args: + if isinstance(table_args[-1], dict): + args, table_kw = table_args[0:-1], table_args[-1] + else: + args = table_args + + args = (*columns, *inspected_args, *args) + for item in args: + try: + _table = getattr(item, "table", None) +~~ except InvalidRequestError: + _table = None + if _table is not None: + raise ValueError( + "{} is already attached to another table. Please do not " + "use the same item twice. A common mistake is defining " + "constraints and indices in a super class - we are working" + " on making it possible." + ) + rv = sa.Table(table_name, sub_cls.__metadata__, *args, **table_kw) + for k, v in updates.items(): + setattr(sub_cls, k, v) + + json_prop_names = set() + for each_cls in sub_cls.__mro__[::-1]: + for k, v in each_cls.__dict__.items(): + if isinstance(v, json_support.JSONProperty): + if not v.name: + v.name = k + json_prop_names.add(v.prop_name) + json_col = getattr( + sub_cls.__dict__.get(v.prop_name), "column", None + ) + if not isinstance(json_col, sa.Column) or not isinstance( + json_col.type, sa.JSON + + +## ... source file continues with no further InvalidRequestError examples... + +``` + + +## Example 2 from SQLAlchemy filters +[SQLAlchemy filters](https://github.com/juliotrigo/sqlalchemy-filters) + provides filtering, sorting and pagination for [SQLAlchemy](/sqlalchemy.html) + query objects, which is particularly useful when building + [web APIs](/application-programming-interfaces.html). SQLAlchemy filters + is open sourced under the + [Apache License version 2.0](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/LICENSE). + +[**SQLAlchemy filters / sqlalchemy_filters / models.py**](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/sqlalchemy_filters/./models.py) + +```python +# models.py +~~from sqlalchemy.exc import InvalidRequestError +from sqlalchemy.inspection import inspect +from sqlalchemy.orm.mapper import Mapper +from sqlalchemy.util import symbol +import types + +from .exceptions import BadQuery, FieldNotFound, BadSpec + + +class Field(object): + + def __init__(self, model, field_name): + self.model = model + self.field_name = field_name + + def get_sqlalchemy_field(self): + if self.field_name not in self._get_valid_field_names(): + raise FieldNotFound( + 'Model {} has no column `{}`.'.format( + self.model, self.field_name + ) + ) + sqlalchemy_field = getattr(self.model, self.field_name) + + if isinstance(sqlalchemy_field, types.MethodType): + + +## ... source file abbreviated to get to InvalidRequestError examples ... + + + +def get_model_class_by_name(registry, name): + for cls in registry.values(): + if getattr(cls, '__name__', None) == name: + return cls + + +def get_default_model(query): + query_models = get_query_models(query).values() + if len(query_models) == 1: + default_model, = iter(query_models) + else: + default_model = None + return default_model + + +def auto_join(query, *model_names): + query_models = get_query_models(query).values() + model_registry = list(query_models)[-1]._decl_class_registry + + for name in model_names: + model = get_model_class_by_name(model_registry, name) + if model not in get_query_models(query).values(): + try: + query = query.join(model) +~~ except InvalidRequestError: + pass # can't be autojoined + return query + + + +## ... source file continues with no further InvalidRequestError examples... + +``` + + +## Example 3 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / utilities.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./utilities.py) + +```python +# utilities.py + +import csv +import linecache +import warnings +import yaml +from collections import OrderedDict + +from sqlalchemy.orm.collections import InstrumentedList +~~from sqlalchemy.exc import InvalidRequestError as SA_InvalidRequestError +from sqlalchemy.exc import UnsupportedCompilationError as SA_UnsupportedCompilationError + +from validator_collection import validators, checkers +from validator_collection.errors import NotAnIterableError + +from sqlathanor._compat import json, is_py2, is_py36, is_py35, dict as dict_ +from sqlathanor.errors import InvalidFormatError, UnsupportedSerializationError, \ + UnsupportedDeserializationError, MaximumNestingExceededError, \ + MaximumNestingExceededWarning, DeserializationError, CSVStructureError + +UTILITY_COLUMNS = [ + 'metadata', + 'primary_key_value', + '_decl_class_registry', + '_sa_instance_state', + '_sa_class_manager' +] + +def bool_to_tuple(input): + + if input is True: + input = (True, True) + elif not input: + input = (False, False) + + +## ... source file continues with no further InvalidRequestError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-exc-noinspectionavailable.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-exc-noinspectionavailable.markdown new file mode 100644 index 000000000..f4aeef522 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-exc-noinspectionavailable.markdown @@ -0,0 +1,130 @@ +title: sqlalchemy.exc NoInspectionAvailable Example Code +category: page +slug: sqlalchemy-exc-noinspectionavailable-examples +sortorder: 500031039 +toc: False +sidebartitle: sqlalchemy.exc NoInspectionAvailable +meta: Example code for understanding how to use the NoInspectionAvailable class from the sqlalchemy.exc module of the SQLAlchemy project. + + +`NoInspectionAvailable` is a class within the `sqlalchemy.exc` module of the SQLAlchemy project. + +ArgumentError, +DataError, +DatabaseError, +IntegrityError, +InvalidRequestError, +NoSuchTableError, +OperationalError, +ProgrammingError, +and UnsupportedCompilationError +are several other callables with code examples from the same `sqlalchemy.exc` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / foreign_keys.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/foreign_keys.py) + +```python +# foreign_keys.py +from collections import defaultdict +from itertools import groupby + +import sqlalchemy as sa +~~from sqlalchemy.exc import NoInspectionAvailable +from sqlalchemy.orm import object_session +from sqlalchemy.schema import ForeignKeyConstraint, MetaData, Table + +from ..query_chain import QueryChain +from .database import has_index +from .orm import get_column_key, get_mapper, get_tables + + +def get_foreign_key_values(fk, obj): + return dict( + ( + fk.constraint.columns.values()[index].key, + getattr(obj, element.column.key) + ) + for + index, element + in + enumerate(fk.constraint.elements) + ) + + +def group_foreign_keys(foreign_keys): + foreign_keys = sorted( + foreign_keys, key=lambda key: key.constraint.table.name + + +## ... source file abbreviated to get to NoInspectionAvailable examples ... + + + else: + ( + session.query(mapper.class_) + .filter_by(**old_values) + .update( + new_values, + 'evaluate' + ) + ) + + +def dependent_objects(obj, foreign_keys=None): + if foreign_keys is None: + foreign_keys = get_referencing_foreign_keys(obj) + + session = object_session(obj) + + chain = QueryChain([]) + classes = obj.__class__._decl_class_registry + + for table, keys in group_foreign_keys(foreign_keys): + keys = list(keys) + for class_ in classes.values(): + try: + mapper = sa.inspect(class_) +~~ except NoInspectionAvailable: + continue + parent_mapper = mapper.inherits + if ( + table in mapper.tables and + not (parent_mapper and table in parent_mapper.tables) + ): + query = session.query(class_).filter( + sa.or_(*_get_criteria(keys, class_, obj)) + ) + chain.queries.append(query) + return chain + + +def _get_criteria(keys, class_, obj): + criteria = [] + visited_constraints = [] + for key in keys: + if key.constraint in visited_constraints: + continue + visited_constraints.append(key.constraint) + + subcriteria = [] + for index, column in enumerate(key.constraint.columns): + foreign_column = ( + + +## ... source file continues with no further NoInspectionAvailable examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-exc-nosuchtableerror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-exc-nosuchtableerror.markdown new file mode 100644 index 000000000..78b91dcc6 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-exc-nosuchtableerror.markdown @@ -0,0 +1,80 @@ +title: sqlalchemy.exc NoSuchTableError Example Code +category: page +slug: sqlalchemy-exc-nosuchtableerror-examples +sortorder: 500031040 +toc: False +sidebartitle: sqlalchemy.exc NoSuchTableError +meta: Example code for understanding how to use the NoSuchTableError class from the sqlalchemy.exc module of the SQLAlchemy project. + + +`NoSuchTableError` is a class within the `sqlalchemy.exc` module of the SQLAlchemy project. + +ArgumentError, +DataError, +DatabaseError, +IntegrityError, +InvalidRequestError, +NoInspectionAvailable, +OperationalError, +ProgrammingError, +and UnsupportedCompilationError +are several other callables with code examples from the same `sqlalchemy.exc` package. + +## Example 1 from PyHive +[PyHive](https://github.com/dropbox/PyHive) +([PyPI package information](https://pypi.org/project/PyHive/)) +is a set of [DB-API](https://www.python.org/dev/peps/pep-0249/) +and +[SQLAlchemy](/sqlalchemy.html) +interfaces that make it easier to use [Presto](https://prestodb.io/) +and [Apache Hive](http://hive.apache.org/) with Python. +[Dropbox's engineering team](https://www.dropbox.com/jobs/teams/engineering) +created this code library, open sourced it and put it out under +the [Apache 2.0 license](https://github.com/dropbox/PyHive/blob/master/LICENSE). + +[**PyHive / pyhive / tests / sqlalchemy_test_case.py**](https://github.com/dropbox/PyHive/blob/master/pyhive/tests/sqlalchemy_test_case.py) + +```python +# sqlalchemy_test_case.py +from __future__ import absolute_import +from __future__ import unicode_literals + +import abc +import contextlib +import functools + +import pytest +import sqlalchemy +from builtins import object +from future.utils import with_metaclass +~~from sqlalchemy.exc import NoSuchTableError +from sqlalchemy.schema import Index +from sqlalchemy.schema import MetaData +from sqlalchemy.schema import Table +from sqlalchemy.sql import expression + + +def with_engine_connection(fn): + @functools.wraps(fn) + def wrapped_fn(self, *args, **kwargs): + engine = self.create_engine() + try: + with contextlib.closing(engine.connect()) as connection: + fn(self, engine, connection, *args, **kwargs) + finally: + engine.dispose() + return wrapped_fn + + +class SqlAlchemyTestCase(with_metaclass(abc.ABCMeta, object)): + @with_engine_connection + def test_basic_query(self, engine, connection): + rows = connection.execute('SELECT * FROM one_row').fetchall() + self.assertEqual(len(rows), 1) + self.assertEqual(rows[0].number_of_rows, 1) # number_of_rows is the column name + + +## ... source file continues with no further NoSuchTableError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-exc-operationalerror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-exc-operationalerror.markdown new file mode 100644 index 000000000..2e41ec0f7 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-exc-operationalerror.markdown @@ -0,0 +1,205 @@ +title: sqlalchemy.exc OperationalError Example Code +category: page +slug: sqlalchemy-exc-operationalerror-examples +sortorder: 500031041 +toc: False +sidebartitle: sqlalchemy.exc OperationalError +meta: Example code for understanding how to use the OperationalError class from the sqlalchemy.exc module of the SQLAlchemy project. + + +`OperationalError` is a class within the `sqlalchemy.exc` module of the SQLAlchemy project. + +ArgumentError, +DataError, +DatabaseError, +IntegrityError, +InvalidRequestError, +NoInspectionAvailable, +NoSuchTableError, +ProgrammingError, +and UnsupportedCompilationError +are several other callables with code examples from the same `sqlalchemy.exc` package. + +## Example 1 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management that is +powered by [SQLAlchemy](/sqlalchemy.html) on the backend. The code +for this project is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / web / errors.py**](https://github.com/indico/indico/blob/master/indico/web/errors.py) + +```python +# errors.py + +from __future__ import absolute_import, unicode_literals + +import traceback +from uuid import uuid4 + +from flask import g, jsonify, render_template, request, session +from itsdangerous import BadData +~~from sqlalchemy.exc import OperationalError +from werkzeug.exceptions import Forbidden, HTTPException + +from indico.core.errors import NoReportError +from indico.legacy.common.cache import GenericCache +from indico.web.util import get_request_info +from indico.web.views import WPError + + +def render_error(exc, title, message, code, standalone=False): + _save_error(exc, title, message) + if _need_json_response(): + return _jsonify_error(exc, title, message, code) + elif standalone: + return render_template('standalone_error.html', error_message=title, error_description=message), code + else: + try: + return WPError(title, message).getHTML(), code +~~ except OperationalError: + return render_error(exc, title, message, code, standalone=True) + + +def load_error_data(uuid): + return GenericCache('errors').get(uuid) + + +def _save_error(exc, title, message): + if 'saved_error_uuid' in g: + return + if not _is_error_reportable(exc): + return + g.saved_error_uuid = uuid = unicode(uuid4()) + tb = traceback.format_exc() + data = {'title': title, + 'message': message, + 'request_info': get_request_info(), + 'traceback': tb, + 'sentry_event_id': g.get('sentry_event_id')} + GenericCache('errors').set(uuid, data, 7200) + + +def _need_json_response(): + return request.is_xhr or request.is_json + + +## ... source file continues with no further OperationalError examples... + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / database.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/database.py) + +```python +# database.py +import itertools +import os +from collections.abc import Mapping, Sequence +from copy import copy + +import sqlalchemy as sa +from sqlalchemy.engine.url import make_url +~~from sqlalchemy.exc import OperationalError, ProgrammingError + +from ..utils import starts_with +from .orm import quote + + +def escape_like(string, escape_char='*'): + return ( + string + .replace(escape_char, escape_char * 2) + .replace('%', escape_char + '%') + .replace('_', escape_char + '_') + ) + + +def json_sql(value, scalars_to_json=True): + scalar_convert = sa.text + if scalars_to_json: + def scalar_convert(a): + return sa.func.to_json(sa.text(a)) + + if isinstance(value, Mapping): + return sa.func.json_build_object( + *( + json_sql(v, scalars_to_json=False) + + +## ... source file abbreviated to get to OperationalError examples ... + + + text = "SELECT 1 FROM pg_database WHERE datname='%s'" % database + return bool(get_scalar_result(engine, text)) + + elif engine.dialect.name == 'mysql': + text = ("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA " + "WHERE SCHEMA_NAME = '%s'" % database) + return bool(get_scalar_result(engine, text)) + + elif engine.dialect.name == 'sqlite': + if database: + return database == ':memory:' or sqlite_file_exists(database) + else: + return True + + else: + engine.dispose() + engine = None + text = 'SELECT 1' + try: + url.database = database + engine = sa.create_engine(url) + result = engine.execute(text) + result.close() + return True + +~~ except (ProgrammingError, OperationalError): + return False + finally: + if engine is not None: + engine.dispose() + + +def create_database(url, encoding='utf8', template=None): + + url = copy(make_url(url)) + + database = url.database + + if url.drivername.startswith('postgres'): + url.database = 'postgres' + elif url.drivername.startswith('mssql'): + url.database = 'master' + elif not url.drivername.startswith('sqlite'): + url.database = None + + if url.drivername == 'mssql+pyodbc': + engine = sa.create_engine(url, connect_args={'autocommit': True}) + elif url.drivername == 'postgresql+pg8000': + engine = sa.create_engine(url, isolation_level='AUTOCOMMIT') + else: + + +## ... source file continues with no further OperationalError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-exc-programmingerror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-exc-programmingerror.markdown new file mode 100644 index 000000000..bed152bfa --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-exc-programmingerror.markdown @@ -0,0 +1,133 @@ +title: sqlalchemy.exc ProgrammingError Example Code +category: page +slug: sqlalchemy-exc-programmingerror-examples +sortorder: 500031042 +toc: False +sidebartitle: sqlalchemy.exc ProgrammingError +meta: Example code for understanding how to use the ProgrammingError class from the sqlalchemy.exc module of the SQLAlchemy project. + + +`ProgrammingError` is a class within the `sqlalchemy.exc` module of the SQLAlchemy project. + +ArgumentError, +DataError, +DatabaseError, +IntegrityError, +InvalidRequestError, +NoInspectionAvailable, +NoSuchTableError, +OperationalError, +and UnsupportedCompilationError +are several other callables with code examples from the same `sqlalchemy.exc` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / database.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/database.py) + +```python +# database.py +import itertools +import os +from collections.abc import Mapping, Sequence +from copy import copy + +import sqlalchemy as sa +from sqlalchemy.engine.url import make_url +~~from sqlalchemy.exc import OperationalError, ProgrammingError + +from ..utils import starts_with +from .orm import quote + + +def escape_like(string, escape_char='*'): + return ( + string + .replace(escape_char, escape_char * 2) + .replace('%', escape_char + '%') + .replace('_', escape_char + '_') + ) + + +def json_sql(value, scalars_to_json=True): + scalar_convert = sa.text + if scalars_to_json: + def scalar_convert(a): + return sa.func.to_json(sa.text(a)) + + if isinstance(value, Mapping): + return sa.func.json_build_object( + *( + json_sql(v, scalars_to_json=False) + + +## ... source file abbreviated to get to ProgrammingError examples ... + + + text = "SELECT 1 FROM pg_database WHERE datname='%s'" % database + return bool(get_scalar_result(engine, text)) + + elif engine.dialect.name == 'mysql': + text = ("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA " + "WHERE SCHEMA_NAME = '%s'" % database) + return bool(get_scalar_result(engine, text)) + + elif engine.dialect.name == 'sqlite': + if database: + return database == ':memory:' or sqlite_file_exists(database) + else: + return True + + else: + engine.dispose() + engine = None + text = 'SELECT 1' + try: + url.database = database + engine = sa.create_engine(url) + result = engine.execute(text) + result.close() + return True + +~~ except (ProgrammingError, OperationalError): + return False + finally: + if engine is not None: + engine.dispose() + + +def create_database(url, encoding='utf8', template=None): + + url = copy(make_url(url)) + + database = url.database + + if url.drivername.startswith('postgres'): + url.database = 'postgres' + elif url.drivername.startswith('mssql'): + url.database = 'master' + elif not url.drivername.startswith('sqlite'): + url.database = None + + if url.drivername == 'mssql+pyodbc': + engine = sa.create_engine(url, connect_args={'autocommit': True}) + elif url.drivername == 'postgresql+pg8000': + engine = sa.create_engine(url, isolation_level='AUTOCOMMIT') + else: + + +## ... source file continues with no further ProgrammingError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-exc-unsupportedcompilationerror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-exc-unsupportedcompilationerror.markdown new file mode 100644 index 000000000..0ba77b319 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-exc-unsupportedcompilationerror.markdown @@ -0,0 +1,82 @@ +title: sqlalchemy.exc UnsupportedCompilationError Example Code +category: page +slug: sqlalchemy-exc-unsupportedcompilationerror-examples +sortorder: 500031043 +toc: False +sidebartitle: sqlalchemy.exc UnsupportedCompilationError +meta: Example code for understanding how to use the UnsupportedCompilationError class from the sqlalchemy.exc module of the SQLAlchemy project. + + +`UnsupportedCompilationError` is a class within the `sqlalchemy.exc` module of the SQLAlchemy project. + +ArgumentError, +DataError, +DatabaseError, +IntegrityError, +InvalidRequestError, +NoInspectionAvailable, +NoSuchTableError, +OperationalError, +and ProgrammingError +are several other callables with code examples from the same `sqlalchemy.exc` package. + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / utilities.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./utilities.py) + +```python +# utilities.py + +import csv +import linecache +import warnings +import yaml +from collections import OrderedDict + +from sqlalchemy.orm.collections import InstrumentedList +from sqlalchemy.exc import InvalidRequestError as SA_InvalidRequestError +~~from sqlalchemy.exc import UnsupportedCompilationError as SA_UnsupportedCompilationError + +from validator_collection import validators, checkers +from validator_collection.errors import NotAnIterableError + +from sqlathanor._compat import json, is_py2, is_py36, is_py35, dict as dict_ +from sqlathanor.errors import InvalidFormatError, UnsupportedSerializationError, \ + UnsupportedDeserializationError, MaximumNestingExceededError, \ + MaximumNestingExceededWarning, DeserializationError, CSVStructureError + +UTILITY_COLUMNS = [ + 'metadata', + 'primary_key_value', + '_decl_class_registry', + '_sa_instance_state', + '_sa_class_manager' +] + +def bool_to_tuple(input): + + if input is True: + input = (True, True) + elif not input: + input = (False, False) + elif not isinstance(input, tuple) or len(input) > 2: + + +## ... source file continues with no further UnsupportedCompilationError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-ext-associationproxy-associationproxy.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-ext-associationproxy-associationproxy.markdown new file mode 100644 index 000000000..9d9345d54 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-ext-associationproxy-associationproxy.markdown @@ -0,0 +1,71 @@ +title: sqlalchemy.ext.associationproxy AssociationProxy Example Code +category: page +slug: sqlalchemy-ext-associationproxy-associationproxy-examples +sortorder: 500031045 +toc: False +sidebartitle: sqlalchemy.ext.associationproxy AssociationProxy +meta: Example code for understanding how to use the AssociationProxy class from the sqlalchemy.ext.associationproxy module of the SQLAlchemy project. + + +`AssociationProxy` is a class within the `sqlalchemy.ext.associationproxy` module of the SQLAlchemy project. + + + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / declarative / _base_configuration_mixin.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/declarative/_base_configuration_mixin.py) + +```python +# _base_configuration_mixin.py + + +import inspect as inspect_ +from collections import OrderedDict + +from sqlalchemy.inspection import inspect +from sqlalchemy.exc import InvalidRequestError +~~from sqlalchemy.ext.associationproxy import AssociationProxy +from validator_collection import checkers + +from sqlathanor._compat import dict as dict_ +from sqlathanor.attributes import AttributeConfiguration, validate_serialization_config, \ + BLANK_ON_SERIALIZE +from sqlathanor.errors import ConfigurationError, UnsupportedSerializationError + + +class ConfigurationMixin(object): + + @classmethod + def _get_instance_attributes(cls, + include_private = False, + exclude_methods = True): + base_attributes = dir(cls) + instance_attributes = [] + for key in base_attributes: + if key.startswith('__'): + continue + + if key.startswith('_') and not key.startswith('__') and not include_private: + continue + + try: + + +## ... source file continues with no further AssociationProxy examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-ext-automap-automap-base.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-ext-automap-automap-base.markdown new file mode 100644 index 000000000..9de2f69eb --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-ext-automap-automap-base.markdown @@ -0,0 +1,171 @@ +title: sqlalchemy.ext.automap automap_base Example Code +category: page +slug: sqlalchemy-ext-automap-automap-base-examples +sortorder: 500031046 +toc: False +sidebartitle: sqlalchemy.ext.automap automap_base +meta: Python example code that shows how to use the automap_base callable from the sqlalchemy.ext.automap module of the SQLAlchemy project. + + +`automap_base` is a callable within the `sqlalchemy.ext.automap` module of the SQLAlchemy project. + + + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / automap.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./automap.py) + +```python +# automap.py + + +import sqlalchemy + +try: +~~ from sqlalchemy.ext.automap import automap_base as SA_automap_base + SUPPORTS_AUTOMAP = True +except ImportError: + SUPPORTS_AUTOMAP = False + SA_automap_base = bool + +from validator_collection import checkers + +from sqlathanor import BaseModel +from sqlathanor.errors import SQLAlchemySupportError + + +~~def automap_base(declarative_base = None, + **kwargs): + + if not SUPPORTS_AUTOMAP: + raise SQLAlchemySupportError( + 'automap is only available in SQLAlchemy v.0.9.1 and higher, ' + \ + 'but you are using %s. Please upgrade.' % sqlalchemy.__version__ + ) + + if declarative_base is None: + cls = BaseModel + elif isinstance(declarative_base, BaseModel) or declarative_base == BaseModel: + cls = declarative_base + elif isinstance(declarative_base, tuple): + for item in declarative_base: + if item == BaseModel or isinstance(item, BaseModel): + cls = declarative_base + break + else: + cls = kwargs.pop('cls', None) + if cls is None and checkers.is_iterable(declarative_base): + class_list = [BaseModel] + class_list.extend([x for x in declarative_base]) + elif cls is None and not checkers.is_iterable(declarative_base): + class_list = [BaseModel, declarative_base] + + +## ... source file continues with no further automap_base examples... + +``` + + +## Example 2 from sandman2 +[sandman2](https://github.com/jeffknupp/sandman2) +([project documentation](https://sandman2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/sandman2/)) +is a code library for automatically generating +[RESTful APIs](/application-programming-interfaces.html) from +existing database schemas. This approach is handy for solving +straightforward situations where you want to put an abstraction +layer between one or more applications and your +[relational database](/databases.html) to prevent or reduce +direct database access. + +The sandman2 project is provided under the +[Apache License 2.0](https://github.com/jeffknupp/sandman2/blob/master/LICENSE). + +[**sandman2 / sandman2 / model.py**](https://github.com/jeffknupp/sandman2/blob/master/sandman2/./model.py) + +```python +# model.py + +import datetime +from decimal import Decimal + +from sqlalchemy.inspection import inspect +from flask_sqlalchemy import SQLAlchemy # pylint: disable=import-error,no-name-in-module +~~from sqlalchemy.ext.automap import automap_base +from sqlalchemy.ext.declarative import declarative_base + +db = SQLAlchemy() + +class Model(object): + + + __url__ = None + + __version__ = '1' + + __methods__ = { + 'GET', + 'POST', + 'PUT', + 'PATCH', + 'DELETE', + 'HEAD', + 'OPTIONS' + } + + @classmethod + def required(cls): + columns = [] + + +## ... source file abbreviated to get to automap_base examples ... + + + instance = getattr(self, relationship.key) + if instance: + link_dict[str(relationship.key)] = instance.resource_uri() + return link_dict + + def resource_uri(self): + return self.__url__ + '/' + str(getattr(self, self.primary_key())) + + def update(self, attributes): + for attribute in attributes: + setattr(self, attribute, attributes[attribute]) + return self + + @classmethod + def description(cls): + + description = {} + for column in cls.__table__.columns: # pylint: disable=no-member + column_description = str(column.type) + if not column.nullable: + column_description += ' (required)' + description[column.name] = column_description + return description + +DeclarativeModel = declarative_base(cls=(db.Model, Model)) +~~AutomapModel = automap_base(DeclarativeModel) + + + +## ... source file continues with no further automap_base examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-ext-compiler-compiles.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-ext-compiler-compiles.markdown new file mode 100644 index 000000000..b4ea0a99b --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-ext-compiler-compiles.markdown @@ -0,0 +1,446 @@ +title: sqlalchemy.ext.compiler compiles Example Code +category: page +slug: sqlalchemy-ext-compiler-compiles-examples +sortorder: 500031047 +toc: False +sidebartitle: sqlalchemy.ext.compiler compiles +meta: Python example code that shows how to use the compiles callable from the sqlalchemy.ext.compiler module of the SQLAlchemy project. + + +`compiles` is a callable within the `sqlalchemy.ext.compiler` module of the SQLAlchemy project. + + + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / util / sqla_compat.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/util/sqla_compat.py) + +```python +# sqla_compat.py +import re + +from sqlalchemy import __version__ +from sqlalchemy import inspect +from sqlalchemy import schema +from sqlalchemy import sql +from sqlalchemy import types as sqltypes +~~from sqlalchemy.ext.compiler import compiles +from sqlalchemy.schema import CheckConstraint +from sqlalchemy.schema import Column +from sqlalchemy.schema import ForeignKeyConstraint +from sqlalchemy.sql.elements import quoted_name +from sqlalchemy.sql.expression import _BindParamClause +from sqlalchemy.sql.expression import _TextClause as TextClause +from sqlalchemy.sql.visitors import traverse + +from . import compat + + +def _safe_int(value): + try: + return int(value) + except: + return value + + +_vers = tuple( + [_safe_int(x) for x in re.findall(r"(\d+|[abc]\d)", __version__)] +) +sqla_110 = _vers >= (1, 1, 0) +sqla_1115 = _vers >= (1, 1, 15) +sqla_120 = _vers >= (1, 2, 0) + + +## ... source file abbreviated to get to compiles examples ... + + + if isinstance(text_, compat.string_types): + c = Column(text_, sqltypes.NULLTYPE) + table.append_column(c) + return c + elif isinstance(text_, TextClause): + return _textual_index_element(table, text_) + else: + raise ValueError("String or text() construct expected") + + +class _textual_index_element(sql.ColumnElement): + + __visit_name__ = "_textual_idx_element" + + def __init__(self, table, text): + self.table = table + self.text = text + self.key = text.text + self.fake_column = schema.Column(self.text.text, sqltypes.NULLTYPE) + table.append_column(self.fake_column) + + def get_children(self): + return [self.fake_column] + + +~~@compiles(_textual_index_element) +def _render_textual_index_column(element, compiler, **kw): + return compiler.process(element.text, **kw) + + +class _literal_bindparam(_BindParamClause): + pass + + +~~@compiles(_literal_bindparam) +def _render_literal_bindparam(element, compiler, **kw): + return compiler.render_literal_bindparam(element, **kw) + + +def _get_index_expressions(idx): + return list(idx.expressions) + + +def _get_index_column_names(idx): + return [getattr(exp, "name", None) for exp in _get_index_expressions(idx)] + + +def _column_kwargs(col): + if sqla_13: + return col.kwargs + else: + return {} + + +def _get_constraint_final_name(constraint, dialect): + if constraint.name is None: + return None + elif sqla_14: + return dialect.identifier_preparer.format_constraint( + + +## ... source file continues with no further compiles examples... + +``` + + +## Example 2 from Amazon Redshift SQLAlchemy Dialect +[Amazon Redshift SQLAlchemy Dialect](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +that can communicate with the [AWS Redshift](https://aws.amazon.com/redshift/) +data store. The SQL is essentially [PostgreSQL](/postgresql.html) +and requires [psycopg2](https://www.psycopg.org/) to properly +operate. This project and its code are open sourced under the +[MIT license](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/LICENSE). + +[**Amazon Redshift SQLAlchemy Dialect / sqlalchemy_redshift / dialect.py**](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/sqlalchemy_redshift/./dialect.py) + +```python +# dialect.py +import re +from collections import defaultdict, namedtuple + +from packaging.version import Version +import pkg_resources +import sqlalchemy as sa +from sqlalchemy import inspect +from sqlalchemy.dialects.postgresql.base import ( + PGCompiler, PGDDLCompiler, PGIdentifierPreparer, PGTypeCompiler +) +from sqlalchemy.dialects.postgresql.psycopg2 import PGDialect_psycopg2 +from sqlalchemy.engine import reflection +~~from sqlalchemy.ext.compiler import compiles +from sqlalchemy.sql.expression import ( + BinaryExpression, BooleanClauseList, Delete +) +from sqlalchemy.types import ( + VARCHAR, NullType, SMALLINT, INTEGER, BIGINT, + DECIMAL, REAL, BOOLEAN, CHAR, DATE, TIMESTAMP) +from sqlalchemy.dialects.postgresql import DOUBLE_PRECISION + +from .commands import ( + CopyCommand, UnloadFromSelect, Format, Compression, Encoding, + CreateLibraryCommand, AlterTableAppendCommand, RefreshMaterializedView +) +from .ddl import ( + CreateMaterializedView, DropMaterializedView, get_table_attributes +) + +sa_version = Version(sa.__version__) + +try: + import alembic +except ImportError: + pass +else: + from alembic.ddl import postgresql + + from alembic.ddl.base import RenameTable +~~ compiles(RenameTable, 'redshift')(postgresql.visit_rename_table) + + if Version(alembic.__version__) >= Version('1.0.6'): + from alembic.ddl.base import ColumnComment +~~ compiles(ColumnComment, 'redshift')(postgresql.visit_column_comment) + + class RedshiftImpl(postgresql.PostgresqlImpl): + __dialect__ = 'redshift' + +__all__ = ( + 'SMALLINT', + 'INTEGER', + 'BIGINT', + 'DECIMAL', + 'REAL', + 'BOOLEAN', + 'CHAR', + 'DATE', + 'TIMESTAMP', + 'VARCHAR', + 'DOUBLE_PRECISION', + 'TIMESTAMPTZ', + + 'CopyCommand', 'UnloadFromSelect', 'RedshiftDialect', 'Compression', + 'Encoding', 'Format', 'CreateLibraryCommand', 'AlterTableAppendCommand', + 'RefreshMaterializedView', + + 'CreateMaterializedView', 'DropMaterializedView' +) + + +## ... source file continues with no further compiles examples... + +``` + + +## Example 3 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / functions.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./functions.py) + +```python +# functions.py +import re + +from sqlalchemy import inspect +from sqlalchemy.sql import functions +from sqlalchemy.sql.elements import ColumnElement +~~from sqlalchemy.ext.compiler import compiles + +from . import types +from . import elements + + +class TableRowElement(ColumnElement): + def __init__(self, selectable): + self.selectable = selectable + + @property + def _from_objects(self): + return [self.selectable] + + +class ST_AsGeoJSON(functions.GenericFunction): + + name = "ST_AsGeoJSON" + + def __init__(self, *args, **kwargs): + expr = kwargs.pop('expr', None) + args = list(args) + if expr is not None: + args = [expr] + args + for idx, element in enumerate(args): + + +## ... source file abbreviated to get to compiles examples ... + + + attributes['type'] = type_ + + type_str = '{0}.{1}'.format(type_.__module__, type_.__name__) + docs.append('Return type: :class:`{0}`.'.format(type_str)) + + if len(docs) != 0: + attributes['__doc__'] = '\n\n'.join(docs) + + globals()[name] = type(name, (GenericFunction,), attributes) + + + + +_SQLITE_FUNCTIONS = { + "ST_GeomFromEWKT": "GeomFromEWKT", + "ST_GeomFromEWKB": "GeomFromEWKB", + "ST_AsBinary": "AsBinary", + "ST_AsEWKB": "AsEWKB", + "ST_AsGeoJSON": "AsGeoJSON", +} + + +def _compiles_default(cls): + def _compile_default(element, compiler, **kw): + return "{}({})".format(cls, compiler.process(element.clauses, **kw)) +~~ compiles(globals()[cls])(_compile_default) + + +def _compiles_sqlite(cls, fn): + def _compile_sqlite(element, compiler, **kw): + return "{}({})".format(fn, compiler.process(element.clauses, **kw)) +~~ compiles(globals()[cls], "sqlite")(_compile_sqlite) + + +for cls, fn in _SQLITE_FUNCTIONS.items(): + _compiles_default(cls) + _compiles_sqlite(cls, fn) + + if element.extended: + func_name = element.geom_from_extended_version + func_args = [element.data] + else: + func_name = element.geom_from + func_args = [element.data, element.srid] + args[idx] = getattr(functions.func, func_name)(*func_args) + else: + try: + insp = inspect(element) + if hasattr(insp, "selectable"): + args[idx] = TableRowElement(insp.selectable) + except Exception: + continue + + functions.GenericFunction.__init__(self, *args, **kwargs) + + __doc__ = ( + 'Return the geometry as a GeoJSON "geometry" object, or the row as a ' + 'GeoJSON feature" object (PostGIS 3 only). (Cf GeoJSON specifications RFC ' + '7946). 2D and 3D Geometries are both supported. GeoJSON only support SFS ' + '1.1 geometry types (no curve support for example). ' + 'See https://postgis.net/docs/ST_AsGeoJSON.html') + + +~~@compiles(TableRowElement) +def _compile_table_row_thing(element, compiler, **kw): + + compiled = compiler.process(list(element.selectable.columns)[0], **kw) + + schema = getattr(element.selectable, "schema", "") + name = element.selectable.name + pattern = r"(.?%s.?\.)?(.?%s.?)\." % (schema, name) + m = re.match(pattern, compiled) + if m: + return m.group(2) + + return compiled.split(".")[0] + + +class GenericFunction(functions.GenericFunction): + + _register = False + + def __init__(self, *args, **kwargs): + expr = kwargs.pop('expr', None) + args = list(args) + if expr is not None: + args = [expr] + args + for idx, elem in enumerate(args): + + +## ... source file continues with no further compiles examples... + +``` + + +## Example 4 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / expressions.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./expressions.py) + +```python +# expressions.py +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql +~~from sqlalchemy.ext.compiler import compiles +from sqlalchemy.sql.expression import ColumnElement, FunctionElement +from sqlalchemy.sql.functions import GenericFunction + +from .functions.orm import quote + + +class array_get(FunctionElement): + name = 'array_get' + + +~~@compiles(array_get) +def compile_array_get(element, compiler, **kw): + args = list(element.clauses) + if len(args) != 2: + raise Exception( + "Function 'array_get' expects two arguments (%d given)." % + len(args) + ) + + if not hasattr(args[1], 'value') or not isinstance(args[1].value, int): + raise Exception( + "Second argument should be an integer." + ) + return '(%s)[%s]' % ( + compiler.process(args[0]), + sa.text(str(args[1].value + 1)) + ) + + +class row_to_json(GenericFunction): + name = 'row_to_json' + type = postgresql.JSON + + +~~@compiles(row_to_json, 'postgresql') +def compile_row_to_json(element, compiler, **kw): + return "%s(%s)" % (element.name, compiler.process(element.clauses)) + + +class json_array_length(GenericFunction): + name = 'json_array_length' + type = sa.Integer + + +~~@compiles(json_array_length, 'postgresql') +def compile_json_array_length(element, compiler, **kw): + return "%s(%s)" % (element.name, compiler.process(element.clauses)) + + +class Asterisk(ColumnElement): + def __init__(self, selectable): + self.selectable = selectable + + +~~@compiles(Asterisk) +def compile_asterisk(element, compiler, **kw): + return '%s.*' % quote(compiler.dialect, element.selectable.name) + + + +## ... source file continues with no further compiles examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-ext-compiler.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-ext-compiler.markdown new file mode 100644 index 000000000..5891c82d8 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-ext-compiler.markdown @@ -0,0 +1,259 @@ +title: sqlalchemy.ext compiler Example Code +category: page +slug: sqlalchemy-ext-compiler-examples +sortorder: 500031044 +toc: False +sidebartitle: sqlalchemy.ext compiler +meta: Python example code that shows how to use the compiler callable from the sqlalchemy.ext module of the SQLAlchemy project. + + +`compiler` is a callable within the `sqlalchemy.ext` module of the SQLAlchemy project. + + + +## Example 1 from Amazon Redshift SQLAlchemy Dialect +[Amazon Redshift SQLAlchemy Dialect](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +that can communicate with the [AWS Redshift](https://aws.amazon.com/redshift/) +data store. The SQL is essentially [PostgreSQL](/postgresql.html) +and requires [psycopg2](https://www.psycopg.org/) to properly +operate. This project and its code are open sourced under the +[MIT license](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/LICENSE). + +[**Amazon Redshift SQLAlchemy Dialect / sqlalchemy_redshift / commands.py**](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/sqlalchemy_redshift/./commands.py) + +```python +# commands.py +import enum +import numbers +import re +import warnings +try: + from collections.abc import Iterable +except ImportError: + from collections import Iterable + +import sqlalchemy as sa +from sqlalchemy import exc as sa_exc +~~from sqlalchemy.ext import compiler as sa_compiler +from sqlalchemy.sql import expression as sa_expression + + + +ACCESS_KEY_ID_RE = re.compile('[A-Z0-9]{20}') +SECRET_ACCESS_KEY_RE = re.compile('[A-Za-z0-9/+=]{40}') +TOKEN_RE = re.compile('[A-Za-z0-9/+=]+') +AWS_ACCOUNT_ID_RE = re.compile('[0-9]{12}') +IAM_ROLE_NAME_RE = re.compile('[A-Za-z0-9+=,.@-_]{1,64}') + + +def _process_aws_credentials(access_key_id=None, secret_access_key=None, + session_token=None, aws_account_id=None, + iam_role_name=None): + + if (access_key_id is not None and secret_access_key is not None and + aws_account_id is not None and iam_role_name is not None): + raise TypeError( + 'Either access key based credentials or role based credentials ' + 'should be specified, but not both' + ) + + credentials = None + + + +## ... source file abbreviated to get to compiler examples ... + + + if ignore_extra and fill_target: + raise ValueError( + '"ignore_extra" cannot be used with "fill_target".') + + self.source = source + self.target = target + self.ignore_extra = ignore_extra + self.fill_target = fill_target + + +@sa_compiler.compiles(AlterTableAppendCommand) +def visit_alter_table_append_command(element, compiler, **kw): + if element.ignore_extra: + fill_option = 'IGNOREEXTRA' + elif element.fill_target: + fill_option = 'FILLTARGET' + else: + fill_option = '' + + query_text = \ + 'ALTER TABLE {target} APPEND FROM {source} {fill_option}'.format( +~~ target=compiler.preparer.format_table(element.target), +~~ source=compiler.preparer.format_table(element.source), + fill_option=fill_option, + ) +~~ return compiler.process(sa.text(query_text), **kw) + + +class UnloadFromSelect(_ExecutableClause): + + def __init__(self, select, unload_location, access_key_id=None, + secret_access_key=None, session_token=None, + aws_account_id=None, iam_role_name=None, + manifest=False, delimiter=None, fixed_width=None, + encrypted=False, gzip=False, add_quotes=False, null=None, + escape=False, allow_overwrite=False, parallel=True, + header=False, region=None, max_file_size=None, + format=None): + + if delimiter is not None and len(delimiter) != 1: + raise ValueError( + '"delimiter" parameter must be a single character' + ) + + if header and fixed_width is not None: + raise ValueError( + "'header' cannot be used with 'fixed_width'" + ) + + credentials = _process_aws_credentials( + + +## ... source file abbreviated to get to compiler examples ... + + + if element.max_error is not None: + parameters.append('MAXERROR AS :error_count') + bindparams.append(sa.bindparam( + 'error_count', + value=element.max_error, + type_=sa.Integer, + )) + + if element.no_load: + parameters.append('NOLOAD') + + if element.stat_update: + parameters.append('STATUPDATE ON') + elif element.stat_update is not None: + parameters.append('STATUPDATE OFF') + + if element.region is not None: + parameters.append('REGION :region') + bindparams.append(sa.bindparam( + 'region', + value=element.region, + type_=sa.String + )) + + columns = ' (%s)' % ', '.join( +~~ compiler.preparer.format_column(column) for column in element.columns + ) if element.columns else '' + + qs = qs.format( +~~ table=compiler.preparer.format_table(element.table), + columns=columns, + format=format_, + parameters='\n'.join(parameters) + ) + +~~ return compiler.process(sa.text(qs).bindparams(*bindparams), **kw) + + +class CreateLibraryCommand(_ExecutableClause): + def __init__(self, library_name, location, access_key_id=None, + secret_access_key=None, session_token=None, + aws_account_id=None, iam_role_name=None, replace=False, + region=None): + self.library_name = library_name + self.location = location + self.credentials = _process_aws_credentials( + access_key_id=access_key_id, + secret_access_key=secret_access_key, + session_token=session_token, + aws_account_id=aws_account_id, + iam_role_name=iam_role_name, + ) + self.replace = replace + self.region = region + + +@sa_compiler.compiles(CreateLibraryCommand) +def visit_create_library_command(element, compiler, **kw): + query = """ + CREATE {or_replace} LIBRARY {name} + + +class AlterTableAppendCommand(_ExecutableClause): + def __init__(self, source, target, ignore_extra=False, fill_target=False): + + +## ... source file continues with no further compiler examples... + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / view.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./view.py) + +```python +# view.py +import sqlalchemy as sa +~~from sqlalchemy.ext import compiler +from sqlalchemy.schema import DDLElement, PrimaryKeyConstraint + + +class CreateView(DDLElement): + def __init__(self, name, selectable, materialized=False): + self.name = name + self.selectable = selectable + self.materialized = materialized + + +@compiler.compiles(CreateView) +def compile_create_materialized_view(element, compiler, **kw): + return 'CREATE {}VIEW {} AS {}'.format( + 'MATERIALIZED ' if element.materialized else '', + element.name, +~~ compiler.sql_compiler.process(element.selectable, literal_binds=True), + ) + + +class DropView(DDLElement): + def __init__(self, name, materialized=False, cascade=True): + self.name = name + self.materialized = materialized + self.cascade = cascade + + +@compiler.compiles(DropView) +def compile_drop_materialized_view(element, compiler, **kw): + return 'DROP {}VIEW IF EXISTS {} {}'.format( + 'MATERIALIZED ' if element.materialized else '', + element.name, + 'CASCADE' if element.cascade else '' + ) + + +def create_table_from_selectable( + name, + selectable, + indexes=None, + metadata=None, + + +## ... source file continues with no further compiler examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-ext-declarative-declarative-base.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-ext-declarative-declarative-base.markdown new file mode 100644 index 000000000..d072faea6 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-ext-declarative-declarative-base.markdown @@ -0,0 +1,464 @@ +title: sqlalchemy.ext.declarative declarative_base Example Code +category: page +slug: sqlalchemy-ext-declarative-declarative-base-examples +sortorder: 500031049 +toc: False +sidebartitle: sqlalchemy.ext.declarative declarative_base +meta: Python example code that shows how to use the declarative_base callable from the sqlalchemy.ext.declarative module of the SQLAlchemy project. + + +`declarative_base` is a callable within the `sqlalchemy.ext.declarative` module of the SQLAlchemy project. + +DeclarativeMeta +is another callable from the `sqlalchemy.ext.declarative` package with code examples. + +## Example 1 from flask-sqlalchemy +[flask-sqlalchemy](https://github.com/pallets/flask-sqlalchemy) +([project documentation](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) +and +[PyPI information](https://pypi.org/project/Flask-SQLAlchemy/)) is a +[Flask](/flask.html) extension that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) when building Flask apps. flask-sqlalchemy +provides helper functions that reduce the amount of common boilerplate +code that you have to frequently write yourself if you did not use this +library when combining Flask with SQLAlchemy. + +flask-sqlalchemy is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/pallets/flask-sqlalchemy/blob/master/LICENSE.rst). + +[**flask-sqlalchemy / src/flask_sqlalchemy / __init__.py**](https://github.com/pallets/flask-sqlalchemy/blob/master/src/flask_sqlalchemy/./__init__.py) + +```python +# __init__.py +import functools +import os +import sys +import warnings +from math import ceil +from operator import itemgetter +from threading import Lock +from time import perf_counter + +import sqlalchemy +from flask import _app_ctx_stack +from flask import abort +from flask import current_app +from flask import request +from flask.signals import Namespace +from sqlalchemy import event +from sqlalchemy import inspect +from sqlalchemy import orm +from sqlalchemy.engine.url import make_url +~~from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.declarative import DeclarativeMeta +from sqlalchemy.orm.exc import UnmappedClassError +from sqlalchemy.orm.session import Session as SessionBase + +from .model import DefaultMeta +from .model import Model + +__version__ = "3.0.0.dev" + +_signals = Namespace() +models_committed = _signals.signal("models-committed") +before_models_committed = _signals.signal("before-models-committed") + + +def _make_table(db): + def _make_table(*args, **kwargs): + if len(args) > 1 and isinstance(args[1], db.Column): + args = (args[0], db.metadata) + args[1:] + info = kwargs.pop("info", None) or {} + info.setdefault("bind_key", None) + kwargs["info"] = info + return sqlalchemy.Table(*args, **kwargs) + + return _make_table + + +## ... source file abbreviated to get to declarative_base examples ... + + + _include_sqlalchemy(self, query_class) + + if app is not None: + self.init_app(app) + + @property + def metadata(self): + + return self.Model.metadata + + def create_scoped_session(self, options=None): + + if options is None: + options = {} + + scopefunc = options.pop("scopefunc", _app_ctx_stack.__ident_func__) + options.setdefault("query_cls", self.Query) + return orm.scoped_session(self.create_session(options), scopefunc=scopefunc) + + def create_session(self, options): + + return orm.sessionmaker(class_=SignallingSession, db=self, **options) + + def make_declarative_base(self, model, metadata=None): + if not isinstance(model, DeclarativeMeta): +~~ model = declarative_base( + cls=model, name="Model", metadata=metadata, metaclass=DefaultMeta + ) + + if metadata is not None and model.metadata is not metadata: + model.metadata = metadata + + if not getattr(model, "query_class", None): + model.query_class = self.Query + + model.query = _QueryProperty(self) + return model + + def init_app(self, app): + + if not ( + app.config.get("SQLALCHEMY_DATABASE_URI") + or app.config.get("SQLALCHEMY_BINDS") + ): + raise RuntimeError( + "Either SQLALCHEMY_DATABASE_URI or SQLALCHEMY_BINDS needs to be set." + ) + + app.config.setdefault("SQLALCHEMY_DATABASE_URI", None) + app.config.setdefault("SQLALCHEMY_BINDS", None) + + +## ... source file continues with no further declarative_base examples... + +``` + + +## Example 2 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / tests / models.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/tests/models.py) + +```python +# models.py +from __future__ import absolute_import + +import enum + +from sqlalchemy import (Column, Date, Enum, ForeignKey, Integer, String, Table, + func, select) +~~from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import column_property, composite, mapper, relationship + +PetKind = Enum("cat", "dog", name="pet_kind") + + +class HairKind(enum.Enum): + LONG = 'long' + SHORT = 'short' + + +~~Base = declarative_base() + +association_table = Table( + "association", + Base.metadata, + Column("pet_id", Integer, ForeignKey("pets.id")), + Column("reporter_id", Integer, ForeignKey("reporters.id")), +) + + +class Editor(Base): + __tablename__ = "editors" + editor_id = Column(Integer(), primary_key=True) + name = Column(String(100)) + + +class Pet(Base): + __tablename__ = "pets" + id = Column(Integer(), primary_key=True) + name = Column(String(30)) + pet_kind = Column(PetKind, nullable=False) + hair_kind = Column(Enum(HairKind, name="hair_kind"), nullable=False) + reporter_id = Column(Integer(), ForeignKey("reporters.id")) + + + + +## ... source file continues with no further declarative_base examples... + +``` + + +## Example 3 from sqlalchemy-datatables +[sqlalchemy-datatables](https://github.com/Pegase745/sqlalchemy-datatables) +([PyPI package information](https://pypi.org/project/sqlalchemy-datatables/)) +is a helper library that makes it easier to use [SQLAlchemy](/sqlalchemy.html) +with the jQuery [JavaScript](/javascript.html) +[DataTables](https://datatables.net/) plugin. This library is designed to +be [web framework](/web-frameworks.html) agnostic and provides code examples +for both [Flask](/flask.html) and [Pyramid](/pyramid.html). + +The project is built and maintained by +[Michel Nemnom (Pegase745)](https://github.com/Pegase745) and is open +sourced under the +[MIT license](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/LICENSE). + +[**sqlalchemy-datatables / tests / models.py**](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/./tests/models.py) + +```python +# models.py +import datetime + +from sqlalchemy import Column, Date, DateTime, ForeignKey, Integer, String, func +~~from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import backref, relationship + +~~Base = declarative_base() + + +class User(Base): + + __tablename__ = 'users' + + id = Column(Integer, primary_key=True) + name = Column(String, unique=True) + created_at = Column(DateTime, default=datetime.datetime.utcnow) + birthday = Column(Date) + address = relationship('Address', uselist=False, backref=backref('user')) + + def __unicode__(self): + return '%s' % self.name + + def __repr__(self): + return '<%s#%s>' % (self.__class__.__name__, self.id) + + @hybrid_property + def dummy(self): + return self.name[0:3] + + @dummy.expression + def dummy(cls): + + +## ... source file continues with no further declarative_base examples... + +``` + + +## Example 4 from SQLAlchemy Mixins +[SQLAlchemy Mixins](https://github.com/absent1706/sqlalchemy-mixins) +([PyPI package information](https://pypi.org/project/sqlalchemy-mixins/)) +is a collection of +[mixins](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful) +useful for extending [SQLAlchemy](/sqlalchemy.html) and simplifying +your [database](/databases.html)-interacting code for some common +use cases. SQLAlchemy Mixins is open sourced under the +[MIT license](https://github.com/absent1706/sqlalchemy-mixins/blob/master/LICENSE.txt). + +[**SQLAlchemy Mixins / sqlalchemy_mixins / inspection.py**](https://github.com/absent1706/sqlalchemy-mixins/blob/master/sqlalchemy_mixins/./inspection.py) + +```python +# inspection.py +from sqlalchemy import inspect +~~from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method +from sqlalchemy.orm import RelationshipProperty + +from .utils import classproperty + + +~~Base = declarative_base() + + +class InspectionMixin(Base): + __abstract__ = True + + @classproperty + def columns(cls): + return inspect(cls).columns.keys() + + @classproperty + def primary_keys_full(cls): + mapper = cls.__mapper__ + return [ + mapper.get_property_by_column(column) + for column in mapper.primary_key + ] + + @classproperty + def primary_keys(cls): + return [pk.key for pk in cls.primary_keys_full] + + @classproperty + def relations(cls): + return [c.key for c in cls.__mapper__.iterate_properties + + +## ... source file continues with no further declarative_base examples... + +``` + + +## Example 5 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / declarative / declarative_base.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/declarative/declarative_base.py) + +```python +# declarative_base.py + + +~~from sqlalchemy.ext.declarative import declarative_base as SA_declarative_base +from validator_collection import checkers + +from sqlathanor.declarative.base_model import BaseModel + + +~~def declarative_base(cls = BaseModel, **kwargs): + if isinstance(cls, tuple): + class_list = [x for x in cls] + class_list.insert(0, BaseModel) + cls = (x for x in class_list) + elif checkers.is_iterable(cls): + class_list = [BaseModel] + class_list.extend(cls) + cls = (x for x in class_list) + + return SA_declarative_base(cls = cls, **kwargs) + + +def as_declarative(**kw): + def decorate(cls): + kw['cls'] = cls + kw['name'] = cls.__name__ +~~ return declarative_base(**kw) + + return decorate + + + +## ... source file continues with no further declarative_base examples... + +``` + + +## Example 6 from sandman2 +[sandman2](https://github.com/jeffknupp/sandman2) +([project documentation](https://sandman2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/sandman2/)) +is a code library for automatically generating +[RESTful APIs](/application-programming-interfaces.html) from +existing database schemas. This approach is handy for solving +straightforward situations where you want to put an abstraction +layer between one or more applications and your +[relational database](/databases.html) to prevent or reduce +direct database access. + +The sandman2 project is provided under the +[Apache License 2.0](https://github.com/jeffknupp/sandman2/blob/master/LICENSE). + +[**sandman2 / sandman2 / model.py**](https://github.com/jeffknupp/sandman2/blob/master/sandman2/./model.py) + +```python +# model.py + +import datetime +from decimal import Decimal + +from sqlalchemy.inspection import inspect +from flask_sqlalchemy import SQLAlchemy # pylint: disable=import-error,no-name-in-module +from sqlalchemy.ext.automap import automap_base +~~from sqlalchemy.ext.declarative import declarative_base + +db = SQLAlchemy() + +class Model(object): + + + __url__ = None + + __version__ = '1' + + __methods__ = { + 'GET', + 'POST', + 'PUT', + 'PATCH', + 'DELETE', + 'HEAD', + 'OPTIONS' + } + + @classmethod + def required(cls): + columns = [] + for column in cls.__table__.columns: # pylint: disable=no-member + + +## ... source file abbreviated to get to declarative_base examples ... + + + if 'collection' not in relationship.key: + instance = getattr(self, relationship.key) + if instance: + link_dict[str(relationship.key)] = instance.resource_uri() + return link_dict + + def resource_uri(self): + return self.__url__ + '/' + str(getattr(self, self.primary_key())) + + def update(self, attributes): + for attribute in attributes: + setattr(self, attribute, attributes[attribute]) + return self + + @classmethod + def description(cls): + + description = {} + for column in cls.__table__.columns: # pylint: disable=no-member + column_description = str(column.type) + if not column.nullable: + column_description += ' (required)' + description[column.name] = column_description + return description + +~~DeclarativeModel = declarative_base(cls=(db.Model, Model)) +AutomapModel = automap_base(DeclarativeModel) + + + +## ... source file continues with no further declarative_base examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-ext-declarative-declarativemeta.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-ext-declarative-declarativemeta.markdown new file mode 100644 index 000000000..f71998164 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-ext-declarative-declarativemeta.markdown @@ -0,0 +1,188 @@ +title: sqlalchemy.ext.declarative DeclarativeMeta Example Code +category: page +slug: sqlalchemy-ext-declarative-declarativemeta-examples +sortorder: 500031048 +toc: False +sidebartitle: sqlalchemy.ext.declarative DeclarativeMeta +meta: Example code for understanding how to use the DeclarativeMeta class from the sqlalchemy.ext.declarative module of the SQLAlchemy project. + + +`DeclarativeMeta` is a class within the `sqlalchemy.ext.declarative` module of the SQLAlchemy project. + +declarative_base +is another callable from the `sqlalchemy.ext.declarative` package with code examples. + +## Example 1 from flask-sqlalchemy +[flask-sqlalchemy](https://github.com/pallets/flask-sqlalchemy) +([project documentation](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) +and +[PyPI information](https://pypi.org/project/Flask-SQLAlchemy/)) is a +[Flask](/flask.html) extension that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) when building Flask apps. flask-sqlalchemy +provides helper functions that reduce the amount of common boilerplate +code that you have to frequently write yourself if you did not use this +library when combining Flask with SQLAlchemy. + +flask-sqlalchemy is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/pallets/flask-sqlalchemy/blob/master/LICENSE.rst). + +[**flask-sqlalchemy / src/flask_sqlalchemy / __init__.py**](https://github.com/pallets/flask-sqlalchemy/blob/master/src/flask_sqlalchemy/./__init__.py) + +```python +# __init__.py +import functools +import os +import sys +import warnings +from math import ceil +from operator import itemgetter +from threading import Lock +from time import perf_counter + +import sqlalchemy +from flask import _app_ctx_stack +from flask import abort +from flask import current_app +from flask import request +from flask.signals import Namespace +from sqlalchemy import event +from sqlalchemy import inspect +from sqlalchemy import orm +from sqlalchemy.engine.url import make_url +from sqlalchemy.ext.declarative import declarative_base +~~from sqlalchemy.ext.declarative import DeclarativeMeta +from sqlalchemy.orm.exc import UnmappedClassError +from sqlalchemy.orm.session import Session as SessionBase + +from .model import DefaultMeta +from .model import Model + +__version__ = "3.0.0.dev" + +_signals = Namespace() +models_committed = _signals.signal("models-committed") +before_models_committed = _signals.signal("before-models-committed") + + +def _make_table(db): + def _make_table(*args, **kwargs): + if len(args) > 1 and isinstance(args[1], db.Column): + args = (args[0], db.metadata) + args[1:] + info = kwargs.pop("info", None) or {} + info.setdefault("bind_key", None) + kwargs["info"] = info + return sqlalchemy.Table(*args, **kwargs) + + return _make_table + + + +## ... source file abbreviated to get to DeclarativeMeta examples ... + + + self._engine_options = engine_options or {} + _include_sqlalchemy(self, query_class) + + if app is not None: + self.init_app(app) + + @property + def metadata(self): + + return self.Model.metadata + + def create_scoped_session(self, options=None): + + if options is None: + options = {} + + scopefunc = options.pop("scopefunc", _app_ctx_stack.__ident_func__) + options.setdefault("query_cls", self.Query) + return orm.scoped_session(self.create_session(options), scopefunc=scopefunc) + + def create_session(self, options): + + return orm.sessionmaker(class_=SignallingSession, db=self, **options) + + def make_declarative_base(self, model, metadata=None): +~~ if not isinstance(model, DeclarativeMeta): + model = declarative_base( + cls=model, name="Model", metadata=metadata, metaclass=DefaultMeta + ) + + if metadata is not None and model.metadata is not metadata: + model.metadata = metadata + + if not getattr(model, "query_class", None): + model.query_class = self.Query + + model.query = _QueryProperty(self) + return model + + def init_app(self, app): + + if not ( + app.config.get("SQLALCHEMY_DATABASE_URI") + or app.config.get("SQLALCHEMY_BINDS") + ): + raise RuntimeError( + "Either SQLALCHEMY_DATABASE_URI or SQLALCHEMY_BINDS needs to be set." + ) + + app.config.setdefault("SQLALCHEMY_DATABASE_URI", None) + + +## ... source file continues with no further DeclarativeMeta examples... + +``` + + +## Example 2 from marshmallow-sqlalchemy +[marshmallow-sqlalchemy](https://github.com/marshmallow-code/marshmallow-sqlalchemy) +([project documentation](https://marshmallow-sqlalchemy.readthedocs.io/en/latest/)) +is a code library that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) with the +[Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +data serialization tool. + +The marshmallow-sqlalchemy project is provided as open source under the +[MIT license](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/LICENSE). + +[**marshmallow-sqlalchemy / src/marshmallow_sqlalchemy / schema / sqlalchemy_schema.py**](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/src/marshmallow_sqlalchemy/schema/sqlalchemy_schema.py) + +```python +# sqlalchemy_schema.py +from marshmallow.fields import Field +from marshmallow.schema import Schema, SchemaMeta, SchemaOpts +import sqlalchemy as sa +~~from sqlalchemy.ext.declarative import DeclarativeMeta + +from ..convert import ModelConverter +from ..exceptions import IncorrectSchemaTypeError +from .load_instance_mixin import LoadInstanceMixin + + +class SQLAlchemyAutoField(Field): + def __init__(self, *, column_name=None, model=None, table=None, field_kwargs): + super().__init__() + + if model and table: + raise ValueError("Cannot pass both `model` and `table` options.") + + self.column_name = column_name + self.model = model + self.table = table + self.field_kwargs = field_kwargs + + def create_field(self, schema_opts, column_name, converter): + model = self.model or schema_opts.model + if model: + return converter.field_for(model, column_name, **self.field_kwargs) + else: + table = self.table if self.table is not None else schema_opts.table + + +## ... source file continues with no further DeclarativeMeta examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-ext-hybrid-hybrid-method.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-ext-hybrid-hybrid-method.markdown new file mode 100644 index 000000000..5d5a0b2fb --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-ext-hybrid-hybrid-method.markdown @@ -0,0 +1,117 @@ +title: sqlalchemy.ext.hybrid hybrid_method Example Code +category: page +slug: sqlalchemy-ext-hybrid-hybrid-method-examples +sortorder: 500031050 +toc: False +sidebartitle: sqlalchemy.ext.hybrid hybrid_method +meta: Python example code that shows how to use the hybrid_method callable from the sqlalchemy.ext.hybrid module of the SQLAlchemy project. + + +`hybrid_method` is a callable within the `sqlalchemy.ext.hybrid` module of the SQLAlchemy project. + +HYBRID_PROPERTY, +hybrid_method, +and hybrid_property +are several other callables with code examples from the same `sqlalchemy.ext.hybrid` package. + +## Example 1 from SQLAlchemy Mixins +[SQLAlchemy Mixins](https://github.com/absent1706/sqlalchemy-mixins) +([PyPI package information](https://pypi.org/project/sqlalchemy-mixins/)) +is a collection of +[mixins](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful) +useful for extending [SQLAlchemy](/sqlalchemy.html) and simplifying +your [database](/databases.html)-interacting code for some common +use cases. SQLAlchemy Mixins is open sourced under the +[MIT license](https://github.com/absent1706/sqlalchemy-mixins/blob/master/LICENSE.txt). + +[**SQLAlchemy Mixins / sqlalchemy_mixins / tests / test_smartquery.py**](https://github.com/absent1706/sqlalchemy-mixins/blob/master/sqlalchemy_mixins/tests/test_smartquery.py) + +```python +# test_smartquery.py +import unittest +import datetime + +import sqlalchemy as sa +from sqlalchemy import create_engine +from sqlalchemy import event +from sqlalchemy.ext.declarative import declarative_base +~~from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method +from sqlalchemy.orm import Session +from sqlalchemy_mixins import SmartQueryMixin, smart_query +from sqlalchemy_mixins.eagerload import JOINED, SUBQUERY + +Base = declarative_base() +engine = create_engine('sqlite:///:memory:', echo=False) + +sess = Session(engine) + + +class BaseModel(Base, SmartQueryMixin): + __abstract__ = True + pass + + +class User(BaseModel): + __tablename__ = 'user' + __repr_attrs__ = ['name'] + id = sa.Column(sa.Integer, primary_key=True) + name = sa.Column(sa.String) + + posts = sa.orm.relationship('Post') + comments = sa.orm.relationship('Comment') + + +class Post(BaseModel): + __tablename__ = 'post' + id = sa.Column(sa.Integer, primary_key=True) + body = sa.Column(sa.String) + user_id = sa.Column(sa.Integer, sa.ForeignKey('user.id')) + archived = sa.Column(sa.Boolean, default=False) + + user = sa.orm.relationship('User') + comments = sa.orm.relationship('Comment') + + @hybrid_property + def public(self): + return not self.archived + + @public.expression + def public(cls): + return -cls.archived + +~~ @hybrid_method + def is_commented_by_user(cls, user, mapper=None): + mapper = mapper or cls + return mapper.comments.any(Comment.user_id == user.id) + +~~ @hybrid_method + def is_public(cls, value, mapper=None): + mapper = mapper or cls + return mapper.public == value + + +class Comment(BaseModel): + __tablename__ = 'comment' + __repr_attrs__ = ['body'] + id = sa.Column(sa.Integer, primary_key=True) + body = sa.Column(sa.String) + user_id = sa.Column(sa.Integer, sa.ForeignKey('user.id')) + post_id = sa.Column(sa.Integer, sa.ForeignKey('post.id')) + rating = sa.Column(sa.Integer) + created_at = sa.Column(sa.DateTime) + + user = sa.orm.relationship('User') + post = sa.orm.relationship('Post') + + +class BaseTest(unittest.TestCase): + def setUp(self): + sess.rollback() + + BaseModel.set_session(None) + + +## ... source file continues with no further hybrid_method examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-ext-hybrid-hybrid-property.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-ext-hybrid-hybrid-property.markdown new file mode 100644 index 000000000..4d0a62b1c --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-ext-hybrid-hybrid-property.markdown @@ -0,0 +1,106 @@ +title: sqlalchemy.ext.hybrid hybrid_property Example Code +category: page +slug: sqlalchemy-ext-hybrid-hybrid-property-examples +sortorder: 500031051 +toc: False +sidebartitle: sqlalchemy.ext.hybrid hybrid_property +meta: Python example code that shows how to use the hybrid_property callable from the sqlalchemy.ext.hybrid module of the SQLAlchemy project. + + +`hybrid_property` is a callable within the `sqlalchemy.ext.hybrid` module of the SQLAlchemy project. + +HYBRID_METHOD, +hybrid_method, +and hybrid_property +are several other callables with code examples from the same `sqlalchemy.ext.hybrid` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / i18n.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./i18n.py) + +```python +# i18n.py +import inspect + +import six +import sqlalchemy as sa +from sqlalchemy.ext.compiler import compiles +~~from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.sql.expression import ColumnElement + +from .exceptions import ImproperlyConfigured + +try: + import babel + import babel.dates +except ImportError: + babel = None + + +def get_locale(): + try: + return babel.Locale('en') + except AttributeError: + raise ImproperlyConfigured( + 'Could not load get_locale function using Babel. Either ' + 'install Babel or make a similar function and override it ' + 'in this module.' + ) + + +if six.PY2: + def get_args_count(func): + + +## ... source file abbreviated to get to hybrid_property examples ... + + + return getattr(obj, attr.key)[default_locale] + except (TypeError, KeyError): + return self.default_value + return getter + + def setter_factory(self, attr): + def setter(obj, value): + if getattr(obj, attr.key) is None: + setattr(obj, attr.key, {}) + locale = cast_locale(obj, self.current_locale, attr) + getattr(obj, attr.key)[locale] = value + return setter + + def expr_factory(self, attr): + def expr(cls): + cls_attr = getattr(cls, attr.key) + current_locale = cast_locale_expr(cls, self.current_locale, attr) + default_locale = cast_locale_expr(cls, self.default_locale, attr) + return sa.func.coalesce( + cls_attr[current_locale], + cls_attr[default_locale] + ) + return expr + + def __call__(self, attr): +~~ return hybrid_property( + fget=self.getter_factory(attr), + fset=self.setter_factory(attr), + expr=self.expr_factory(attr) + ) + + + +## ... source file continues with no further hybrid_property examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-ext-mutable-mutable.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-ext-mutable-mutable.markdown new file mode 100644 index 000000000..f2e7c2607 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-ext-mutable-mutable.markdown @@ -0,0 +1,80 @@ +title: sqlalchemy.ext.mutable Mutable Example Code +category: page +slug: sqlalchemy-ext-mutable-mutable-examples +sortorder: 500031052 +toc: False +sidebartitle: sqlalchemy.ext.mutable Mutable +meta: Example code for understanding how to use the Mutable class from the sqlalchemy.ext.mutable module of the SQLAlchemy project. + + +`Mutable` is a class within the `sqlalchemy.ext.mutable` module of the SQLAlchemy project. + + + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / types / password.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/types/password.py) + +```python +# password.py +import weakref + +import six +from sqlalchemy import types +from sqlalchemy.dialects import oracle, postgresql, sqlite +~~from sqlalchemy.ext.mutable import Mutable + +from ..exceptions import ImproperlyConfigured +from .scalar_coercible import ScalarCoercible + +passlib = None +try: + import passlib + from passlib.context import LazyCryptContext +except ImportError: + pass + + +~~class Password(Mutable, object): + + @classmethod + def coerce(cls, key, value): + if isinstance(value, Password): + return value + + if isinstance(value, (six.string_types, six.binary_type)): + return cls(value, secret=True) + + super(Password, cls).coerce(key, value) + + def __init__(self, value, context=None, secret=False): + self.hash = value if not secret else None + + self.secret = value if secret else None + + if isinstance(self.hash, six.text_type): + self.hash = self.hash.encode('utf8') + + self.context = weakref.proxy(context) if context is not None else None + + def __eq__(self, value): + if self.hash is None or value is None: + return self.hash is value + + +## ... source file continues with no further Mutable examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-extensions-plug-ins.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-extensions-plug-ins.markdown index 8ddfbe31b..c24866e5f 100644 --- a/content/pages/examples/sqlalchemy/sqlalchemy-extensions-plug-ins.markdown +++ b/content/pages/examples/sqlalchemy/sqlalchemy-extensions-plug-ins.markdown @@ -29,6 +29,16 @@ database schema changes. The Alembic project is open sourced under the [MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). +### Amazon Redshift SQLAlchemy Dialect +[Amazon Redshift SQLAlchemy Dialect](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +that can communicate with the [AWS Redshift](https://aws.amazon.com/redshift/) +data store. The SQL is essentially [PostgreSQL](/postgresql.html) +and requires [psycopg2](https://www.psycopg.org/) to properly +operate. This project and its code are open sourced under the +[MIT license](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/LICENSE). + + ### flask-base [flask-base](https://github.com/hack4impact/flask-base) ([project documentation](http://hack4impact.github.io/flask-base/)) @@ -39,7 +49,7 @@ libraries that are commonly used in Flask projects, such as [SendGrid](https://www.twilio.com/sendgrid) for transactional email, [SQLAlchemy](/sqlalchemy.html) for persistent data storage through a [relational database](/databases.html) back end, -[Flask-WTF](https://flask-wtf.readthedocs.io/en/stable/) for form +[Flask-WTF](https://flask-wtf.readthedocs.io/) for form handling, and many others. flask-base is provided as open source under the @@ -61,6 +71,18 @@ flask-sqlalchemy is provided as open source under the [BSD 3-Clause "New" or "Revised" License](https://github.com/pallets/flask-sqlalchemy/blob/master/LICENSE.rst). +### GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + + ### GINO [GINO](https://github.com/fantix/gino) ([project documentation](https://python-gino.readthedocs.io/en/latest/) @@ -74,6 +96,21 @@ with asynchronously-run code, for example, an application written with GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). +### graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + + ### marshmallow-sqlalchemy [marshmallow-sqlalchemy](https://github.com/marshmallow-code/marshmallow-sqlalchemy) ([project documentation](https://marshmallow-sqlalchemy.readthedocs.io/en/latest/) @@ -88,13 +125,87 @@ The marshmallow-sqlalchemy project is provided as open source under the [MIT license](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/LICENSE). +### PyHive +[PyHive](https://github.com/dropbox/PyHive) +([PyPI package information](https://pypi.org/project/PyHive/)) +is a set of [DB-API](https://www.python.org/dev/peps/pep-0249/) +and +[SQLAlchemy](/sqlalchemy.html) +interfaces that make it easier to use [Presto](https://prestodb.io/) +and [Apache Hive](http://hive.apache.org/) with Python. +[Dropbox's engineering team](https://www.dropbox.com/jobs/teams/engineering) +created this code library, open sourced it and put it out under +the [Apache 2.0 license](https://github.com/dropbox/PyHive/blob/master/LICENSE). + + +### sqlacodegen +[sqlacodegen](https://github.com/agronholm/sqlacodegen) +([PyPI package information](https://pypi.org/project/sqlacodegen/)) +is a tool for +reading from an existing [relational database](/databases.html) to +generate code to create [SQLAlchemy](/sqlalchemy.html) models based +on that database. The project is primarily written and maintained +by [Alex Grönholm (agronholm)](https://github.com/agronholm) and it +is open sourced under the +[MIT license](https://github.com/agronholm/sqlacodegen/blob/master/LICENSE). + + +### sqlalchemy-clickhouse +[sqlalchemy-clickhouse](https://github.com/cloudflare/sqlalchemy-clickhouse) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +for communicating with the open source [ClickHouse](https://clickhouse.tech/) +database management system. ClickHouse is column-oriented and therefore +better for some use cases and worse for others compared to a traditional +[relational database](/databases.html). + +The code for this project is open sourced under the +[MIT license](https://github.com/cloudflare/sqlalchemy-clickhouse/blob/master/LICENSE.txt) +while ClickHouse is provided as open source under the +[Apache License 2.0](https://github.com/ClickHouse/ClickHouse/blob/master/LICENSE). + + +### sqlalchemy-datatables +[sqlalchemy-datatables](https://github.com/Pegase745/sqlalchemy-datatables) +([PyPI package information](https://pypi.org/project/sqlalchemy-datatables/)) +is a helper library that makes it easier to use [SQLAlchemy](/sqlalchemy.html) +with the jQuery [JavaScript](/javascript.html) +[DataTables](https://datatables.net/) plugin. This library is designed to +be [web framework](/web-frameworks.html) agnostic and provides code examples +for both [Flask](/flask.html) and [Pyramid](/pyramid.html). + +The project is built and maintained by +[Michel Nemnom (Pegase745)](https://github.com/Pegase745) and is open +sourced under the +[MIT license](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/LICENSE). + + +### SQLAlchemy filters +[SQLAlchemy filters](https://github.com/juliotrigo/sqlalchemy-filters) +provides filtering, sorting and pagination for [SQLAlchemy](/sqlalchemy.html) +query objects, which is particularly useful when building +[web APIs](/application-programming-interfaces.html). SQLAlchemy filters +is open sourced under the +[Apache License version 2.0](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/LICENSE). + + +### SQLAlchemy Mixins +[SQLAlchemy Mixins](https://github.com/absent1706/sqlalchemy-mixins) +([PyPI package information](https://pypi.org/project/sqlalchemy-mixins/)) +is a collection of +[mixins](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful) +useful for extending [SQLAlchemy](/sqlalchemy.html) and simplifying +your [database](/databases.html)-interacting code for some common +use cases. SQLAlchemy Mixins is open sourced under the +[MIT license](https://github.com/absent1706/sqlalchemy-mixins/blob/master/LICENSE.txt). + + ### sqlalchemy-utils [sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) ([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) and [PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) is a code library with various helper functions and new data types -that make it easier to use [SQLAlchemy](/sqlachemy.html) when building +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building projects that involve more specific storage requirements such as [currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). The wide array of @@ -102,3 +213,33 @@ The wide array of includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +### SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + + +### wtforms-alchemy +[wtforms-alchemy](git@github.com:kvesteri/wtforms-alchemy.git) +([documentation](https://wtforms-alchemy.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/WTForms-Alchemy/)) +is a [WTForms](https://wtforms.readthedocs.io/en/2.2.1/) extension toolkit +for easier creation of [SQLAlchemy](/sqlalchemy.html) model based forms. +While this project primarily focuses on proper form handling, it also +has many good examples of how to use various parts of SQLAlchemy in +its code base. The project is provided as open source under the +[MIT license](https://github.com/kvesteri/wtforms-alchemy/blob/master/LICENSE). + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-inspection-inspect.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-inspection-inspect.markdown new file mode 100644 index 000000000..38d636930 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-inspection-inspect.markdown @@ -0,0 +1,348 @@ +title: sqlalchemy.inspection inspect Example Code +category: page +slug: sqlalchemy-inspection-inspect-examples +sortorder: 500031053 +toc: False +sidebartitle: sqlalchemy.inspection inspect +meta: Python example code that shows how to use the inspect callable from the sqlalchemy.inspection module of the SQLAlchemy project. + + +`inspect` is a callable within the `sqlalchemy.inspection` module of the SQLAlchemy project. + + + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / tests / test_converter.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/tests/test_converter.py) + +```python +# test_converter.py +import enum + +import pytest +from sqlalchemy import Column, func, select, types +from sqlalchemy.dialects import postgresql +from sqlalchemy.ext.declarative import declarative_base +~~from sqlalchemy.inspection import inspect +from sqlalchemy.orm import column_property, composite +from sqlalchemy_utils import ChoiceType, JSONType, ScalarListType + +import graphene +from graphene.relay import Node +from graphene.types.datetime import DateTime +from graphene.types.json import JSONString + +from ..converter import (convert_sqlalchemy_column, + convert_sqlalchemy_composite, + convert_sqlalchemy_relationship) +from ..fields import (UnsortedSQLAlchemyConnectionField, + default_connection_field_factory) +from ..registry import Registry, get_global_registry +from ..types import SQLAlchemyObjectType +from .models import Article, CompositeFullName, Pet, Reporter + + +def mock_resolver(): + pass + + +def get_field(sqlalchemy_type, **column_kwargs): + class Model(declarative_base()): + __tablename__ = 'model' + id_ = Column(types.Integer, primary_key=True) + column = Column(sqlalchemy_type, doc="Custom Help Text", **column_kwargs) + +~~ column_prop = inspect(Model).column_attrs['column'] + return convert_sqlalchemy_column(column_prop, get_global_registry(), mock_resolver) + + +def get_field_from_column(column_): + class Model(declarative_base()): + __tablename__ = 'model' + id_ = Column(types.Integer, primary_key=True) + column = column_ + +~~ column_prop = inspect(Model).column_attrs['column'] + return convert_sqlalchemy_column(column_prop, get_global_registry(), mock_resolver) + + +def test_should_unknown_sqlalchemy_field_raise_exception(): + re_err = "Don't know how to convert the SQLAlchemy field" + with pytest.raises(Exception, match=re_err): + get_field(getattr(types, 'LargeBinary', types.Binary)()) + + +def test_should_date_convert_string(): + assert get_field(types.Date()).type == graphene.String + + +def test_should_datetime_convert_datetime(): + assert get_field(types.DateTime()).type == DateTime + + +def test_should_time_convert_string(): + assert get_field(types.Time()).type == graphene.String + + +def test_should_string_convert_string(): + assert get_field(types.String()).type == graphene.String + + + +## ... source file continues with no further inspect examples... + +``` + + +## Example 2 from SQLAlchemy filters +[SQLAlchemy filters](https://github.com/juliotrigo/sqlalchemy-filters) + provides filtering, sorting and pagination for [SQLAlchemy](/sqlalchemy.html) + query objects, which is particularly useful when building + [web APIs](/application-programming-interfaces.html). SQLAlchemy filters + is open sourced under the + [Apache License version 2.0](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/LICENSE). + +[**SQLAlchemy filters / sqlalchemy_filters / models.py**](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/sqlalchemy_filters/./models.py) + +```python +# models.py +from sqlalchemy.exc import InvalidRequestError +~~from sqlalchemy.inspection import inspect +from sqlalchemy.orm.mapper import Mapper +from sqlalchemy.util import symbol +import types + +from .exceptions import BadQuery, FieldNotFound, BadSpec + + +class Field(object): + + def __init__(self, model, field_name): + self.model = model + self.field_name = field_name + + def get_sqlalchemy_field(self): + if self.field_name not in self._get_valid_field_names(): + raise FieldNotFound( + 'Model {} has no column `{}`.'.format( + self.model, self.field_name + ) + ) + sqlalchemy_field = getattr(self.model, self.field_name) + + if isinstance(sqlalchemy_field, types.MethodType): + sqlalchemy_field = sqlalchemy_field() + + return sqlalchemy_field + + def _get_valid_field_names(self): +~~ inspect_mapper = inspect(self.model) + columns = inspect_mapper.columns + orm_descriptors = inspect_mapper.all_orm_descriptors + + column_names = columns.keys() + hybrid_names = [ + key for key, item in orm_descriptors.items() + if _is_hybrid_property(item) or _is_hybrid_method(item) + ] + + return set(column_names) | set(hybrid_names) + + +def _is_hybrid_property(orm_descriptor): + return orm_descriptor.extension_type == symbol('HYBRID_PROPERTY') + + +def _is_hybrid_method(orm_descriptor): + return orm_descriptor.extension_type == symbol('HYBRID_METHOD') + + +def get_query_models(query): + models = [col_desc['entity'] for col_desc in query.column_descriptions] + models.extend(mapper.class_ for mapper in query._join_entities) + + + +## ... source file continues with no further inspect examples... + +``` + + +## Example 3 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / declarative / _primary_key_mixin.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/declarative/_primary_key_mixin.py) + +```python +# _primary_key_mixin.py + + +~~from sqlalchemy.inspection import inspect + +class PrimaryKeyMixin(object): + + def _check_is_model_instance(self): + return True + + @classmethod + def get_primary_key_columns(cls): +~~ return inspect(cls).primary_key + + @classmethod + def get_primary_key_column_names(cls): + return [str(x.name) for x in cls.get_primary_key_columns()] + + @property + def primary_key_value(self): +~~ if not inspect(self).has_identity or not inspect(self).identity: + return None + +~~ primary_keys = inspect(self).identity + + if len(primary_keys) == 1: + return primary_keys[0] + + return primary_keys + + + +## ... source file continues with no further inspect examples... + +``` + + +## Example 4 from sandman2 +[sandman2](https://github.com/jeffknupp/sandman2) +([project documentation](https://sandman2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/sandman2/)) +is a code library for automatically generating +[RESTful APIs](/application-programming-interfaces.html) from +existing database schemas. This approach is handy for solving +straightforward situations where you want to put an abstraction +layer between one or more applications and your +[relational database](/databases.html) to prevent or reduce +direct database access. + +The sandman2 project is provided under the +[Apache License 2.0](https://github.com/jeffknupp/sandman2/blob/master/LICENSE). + +[**sandman2 / sandman2 / model.py**](https://github.com/jeffknupp/sandman2/blob/master/sandman2/./model.py) + +```python +# model.py + +import datetime +from decimal import Decimal + +~~from sqlalchemy.inspection import inspect +from flask_sqlalchemy import SQLAlchemy # pylint: disable=import-error,no-name-in-module +from sqlalchemy.ext.automap import automap_base +from sqlalchemy.ext.declarative import declarative_base + +db = SQLAlchemy() + +class Model(object): + + + __url__ = None + + __version__ = '1' + + __methods__ = { + 'GET', + 'POST', + 'PUT', + 'PATCH', + 'DELETE', + 'HEAD', + 'OPTIONS' + } + + @classmethod + + +## ... source file abbreviated to get to inspect examples ... + + + for column in cls.__table__.columns: # pylint: disable=no-member + if column.nullable: + columns.append(column.name) + return columns + + @classmethod + def primary_key(cls): + return list( + cls.__table__.primary_key.columns)[ # pylint: disable=no-member + 0].key + + def to_dict(self): + result_dict = {} + for column in self.__table__.columns.keys(): # pylint: disable=no-member + value = result_dict[column] = getattr(self, column, None) + if isinstance(value, Decimal): + result_dict[column] = float(result_dict[column]) + elif isinstance(value, datetime.datetime): + result_dict[column] = value.isoformat() + elif isinstance(value, datetime.time): + result_dict[column] = value.strftime("%H:%M:%S") + return result_dict + + def links(self): + link_dict = {'self': self.resource_uri()} +~~ for relationship in inspect( # pylint: disable=maybe-no-member + self.__class__).relationships: + if 'collection' not in relationship.key: + instance = getattr(self, relationship.key) + if instance: + link_dict[str(relationship.key)] = instance.resource_uri() + return link_dict + + def resource_uri(self): + return self.__url__ + '/' + str(getattr(self, self.primary_key())) + + def update(self, attributes): + for attribute in attributes: + setattr(self, attribute, attributes[attribute]) + return self + + @classmethod + def description(cls): + + description = {} + for column in cls.__table__.columns: # pylint: disable=no-member + column_description = str(column.type) + if not column.nullable: + column_description += ' (required)' + description[column.name] = column_description + + +## ... source file continues with no further inspect examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-aliased.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-aliased.markdown new file mode 100644 index 000000000..23fc7388e --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-aliased.markdown @@ -0,0 +1,123 @@ +title: sqlalchemy.orm aliased Example Code +category: page +slug: sqlalchemy-orm-aliased-examples +sortorder: 500031061 +toc: False +sidebartitle: sqlalchemy.orm aliased +meta: Python example code that shows how to use the aliased callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`aliased` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from SQLAlchemy Mixins +[SQLAlchemy Mixins](https://github.com/absent1706/sqlalchemy-mixins) +([PyPI package information](https://pypi.org/project/sqlalchemy-mixins/)) +is a collection of +[mixins](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful) +useful for extending [SQLAlchemy](/sqlalchemy.html) and simplifying +your [database](/databases.html)-interacting code for some common +use cases. SQLAlchemy Mixins is open sourced under the +[MIT license](https://github.com/absent1706/sqlalchemy-mixins/blob/master/LICENSE.txt). + +[**SQLAlchemy Mixins / sqlalchemy_mixins / smartquery.py**](https://github.com/absent1706/sqlalchemy-mixins/blob/master/sqlalchemy_mixins/./smartquery.py) + +```python +# smartquery.py +try: + from typing import List +except ImportError: # pragma: no cover + pass + +from collections import OrderedDict + +import sqlalchemy +from sqlalchemy import asc, desc, inspect +~~from sqlalchemy.orm import aliased, contains_eager +from sqlalchemy.orm.util import AliasedClass +from sqlalchemy.sql import operators, extract + +from .eagerload import _flatten_schema, _eager_expr_from_flat_schema, \ + EagerLoadMixin +from .inspection import InspectionMixin +from .utils import classproperty + +RELATION_SPLITTER = '___' +OPERATOR_SPLITTER = '__' + +DESC_PREFIX = '-' + + +def _parse_path_and_make_aliases(entity, entity_path, attrs, aliases): + relations = {} + for attr in attrs: + if RELATION_SPLITTER in attr: + relation_name, nested_attr = attr.split(RELATION_SPLITTER, 1) + if relation_name in relations: + relations[relation_name].append(nested_attr) + else: + relations[relation_name] = [nested_attr] + + for relation_name, nested_attrs in relations.items(): + path = entity_path + RELATION_SPLITTER + relation_name \ + if entity_path else relation_name + if relation_name not in entity.relations: + raise KeyError("Incorrect path `{}`: " + "{} doesnt have `{}` relationship " + .format(path, entity, relation_name)) + relationship = getattr(entity, relation_name) +~~ alias = aliased(relationship.property.mapper.class_) + aliases[path] = alias, relationship + _parse_path_and_make_aliases(alias, path, nested_attrs, aliases) + + +def smart_query(query, filters=None, sort_attrs=None, schema=None): + if not filters: + filters = {} + if not sort_attrs: + sort_attrs = [] + if not schema: + schema = {} + + root_cls = query._entity_zero().class_ # for example, User or Post + attrs = list(filters.keys()) + \ + list(map(lambda s: s.lstrip(DESC_PREFIX), sort_attrs)) + aliases = OrderedDict({}) + _parse_path_and_make_aliases(root_cls, '', attrs, aliases) + + loaded_paths = [] + for path, al in aliases.items(): + relationship_path = path.replace(RELATION_SPLITTER, '.') + query = query.outerjoin(al[0], al[1]) \ + .options(contains_eager(relationship_path, alias=al[0])) + loaded_paths.append(relationship_path) + + +## ... source file continues with no further aliased examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes-flag-modified.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes-flag-modified.markdown new file mode 100644 index 000000000..3c9860072 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes-flag-modified.markdown @@ -0,0 +1,126 @@ +title: sqlalchemy.orm.attributes flag_modified Example Code +category: page +slug: sqlalchemy-orm-attributes-flag-modified-examples +sortorder: 500031078 +toc: False +sidebartitle: sqlalchemy.orm.attributes flag_modified +meta: Python example code that shows how to use the flag_modified callable from the sqlalchemy.orm.attributes module of the SQLAlchemy project. + + +`flag_modified` is a callable within the `sqlalchemy.orm.attributes` module of the SQLAlchemy project. + +InstrumentedAttribute +and +QueryableAttribute +are a couple of other callables within the `sqlalchemy.orm.attributes` package that also have code examples. + +## Example 1 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management that is +powered by [SQLAlchemy](/sqlalchemy.html) on the backend. The code +for this project is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / core / emails.py**](https://github.com/indico/indico/blob/master/indico/core/emails.py) + +```python +# emails.py + +from __future__ import absolute_import, unicode_literals + +import cPickle +import os +import tempfile +from datetime import date + +import click +from celery.exceptions import MaxRetriesExceededError, Retry +~~from sqlalchemy.orm.attributes import flag_modified + +from indico.core.celery import celery +from indico.core.config import config +from indico.core.db import db +from indico.core.logger import Logger +from indico.util.date_time import now_utc +from indico.util.emails.backend import EmailBackend +from indico.util.emails.message import EmailMessage +from indico.util.string import truncate + + +logger = Logger.get('emails') +MAX_TRIES = 10 +DELAYS = [30, 60, 120, 300, 600, 1800, 3600, 3600, 7200] + + +@celery.task(name='send_email', bind=True, max_retries=None) +def send_email_task(task, email, log_entry=None): + attempt = task.request.retries + 1 + try: + do_send_email(email, log_entry, _from_task=True) + except Exception as exc: + delay = (DELAYS + [0])[task.request.retries] if not config.DEBUG else 1 + try: + + +## ... source file abbreviated to get to flag_modified examples ... + + + db.session.commit() + + +def do_send_email(email, log_entry=None, _from_task=False): + with EmailBackend(timeout=config.SMTP_TIMEOUT) as conn: + msg = EmailMessage(subject=email['subject'], body=email['body'], from_email=email['from'], + to=email['to'], cc=email['cc'], bcc=email['bcc'], reply_to=email['reply_to'], + attachments=email['attachments'], connection=conn) + if not msg.to: + msg.extra_headers['To'] = 'Undisclosed-recipients:;' + if email['html']: + msg.content_subtype = 'html' + msg.send() + if not _from_task: + logger.info('Sent email "%s"', truncate(email['subject'], 100)) + if log_entry: + update_email_log_state(log_entry) + + +def update_email_log_state(log_entry, failed=False): + if failed: + log_entry.data['state'] = 'failed' + else: + log_entry.data['state'] = 'sent' + log_entry.data['sent_dt'] = now_utc(False).isoformat() +~~ flag_modified(log_entry, 'data') + + +def store_failed_email(email, log_entry=None): + prefix = 'failed-email-{}-'.format(date.today().isoformat()) + fd, name = tempfile.mkstemp(prefix=prefix, dir=config.TEMP_DIR) + with os.fdopen(fd, 'wb') as f: + cPickle.dump((email, log_entry.id if log_entry else None), f) + return name + + +def resend_failed_email(path): + from indico.modules.events.logs import EventLogEntry + with open(path, 'rb') as f: + email, log_entry_id = cPickle.load(f) + log_entry = EventLogEntry.get(log_entry_id) if log_entry_id is not None else None + do_send_email(email, log_entry) + db.session.commit() + os.remove(path) + return email + + +def resend_failed_emails_cmd(paths): + for path in paths: + email = resend_failed_email(path) + + +## ... source file continues with no further flag_modified examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes-instrumentedattribute.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes-instrumentedattribute.markdown new file mode 100644 index 000000000..1283d4c51 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes-instrumentedattribute.markdown @@ -0,0 +1,242 @@ +title: sqlalchemy.orm.attributes InstrumentedAttribute Example Code +category: page +slug: sqlalchemy-orm-attributes-instrumentedattribute-examples +sortorder: 500031076 +toc: False +sidebartitle: sqlalchemy.orm.attributes InstrumentedAttribute +meta: Example code for understanding how to use the InstrumentedAttribute class from the sqlalchemy.orm.attributes module of the SQLAlchemy project. + + +`InstrumentedAttribute` is a class within the `sqlalchemy.orm.attributes` module of the SQLAlchemy project. + +QueryableAttribute +and +flag_modified +are a couple of other callables within the `sqlalchemy.orm.attributes` package that also have code examples. + +## Example 1 from SQLAlchemy Mixins +[SQLAlchemy Mixins](https://github.com/absent1706/sqlalchemy-mixins) +([PyPI package information](https://pypi.org/project/sqlalchemy-mixins/)) +is a collection of +[mixins](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful) +useful for extending [SQLAlchemy](/sqlalchemy.html) and simplifying +your [database](/databases.html)-interacting code for some common +use cases. SQLAlchemy Mixins is open sourced under the +[MIT license](https://github.com/absent1706/sqlalchemy-mixins/blob/master/LICENSE.txt). + +[**SQLAlchemy Mixins / sqlalchemy_mixins / eagerload.py**](https://github.com/absent1706/sqlalchemy-mixins/blob/master/sqlalchemy_mixins/./eagerload.py) + +```python +# eagerload.py +try: + from typing import List +except ImportError: # pragma: no cover + pass + +from sqlalchemy.orm import joinedload +from sqlalchemy.orm import subqueryload +~~from sqlalchemy.orm.attributes import InstrumentedAttribute + +from .session import SessionMixin + +JOINED = 'joined' +SUBQUERY = 'subquery' + + +def eager_expr(schema): + flat_schema = _flatten_schema(schema) + return _eager_expr_from_flat_schema(flat_schema) + + +def _flatten_schema(schema): + def _flatten(schema, parent_path, result): + for path, value in schema.items(): +~~ if isinstance(path, InstrumentedAttribute): + path = path.key + + if isinstance(value, tuple): + join_method, inner_schema = value[0], value[1] + elif isinstance(value, dict): + join_method, inner_schema = JOINED, value + else: + join_method, inner_schema = value, None + + full_path = parent_path + '.' + path if parent_path else path + result[full_path] = join_method + + if inner_schema: + _flatten(inner_schema, full_path, result) + + result = {} + _flatten(schema, '', result) + return result + + +def _eager_expr_from_flat_schema(flat_schema): + result = [] + for path, join_method in flat_schema.items(): + if join_method == JOINED: + + +## ... source file continues with no further InstrumentedAttribute examples... + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / path.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./path.py) + +```python +# path.py +import sqlalchemy as sa +~~from sqlalchemy.orm.attributes import InstrumentedAttribute +from sqlalchemy.util.langhelpers import symbol + +from .utils import str_coercible + + +@str_coercible +class Path(object): + def __init__(self, path, separator='.'): + if isinstance(path, Path): + self.path = path.path + else: + self.path = path + self.separator = separator + + @property + def parts(self): + return self.path.split(self.separator) + + def __iter__(self): + for part in self.parts: + yield part + + def __len__(self): + return len(self.parts) + + +## ... source file abbreviated to get to InstrumentedAttribute examples ... + + + return "%s('%s')" % (self.__class__.__name__, self.path) + + def index(self, element): + return self.parts.index(element) + + def __getitem__(self, slice): + result = self.parts[slice] + if isinstance(result, list): + return self.__class__( + self.separator.join(result), + separator=self.separator + ) + return result + + def __eq__(self, other): + return self.path == other.path and self.separator == other.separator + + def __ne__(self, other): + return not (self == other) + + def __unicode__(self): + return self.path + + +def get_attr(mixed, attr): +~~ if isinstance(mixed, InstrumentedAttribute): + return getattr( + mixed.property.mapper.class_, + attr + ) + else: + return getattr(mixed, attr) + + +@str_coercible +class AttrPath(object): + def __init__(self, class_, path): + self.class_ = class_ + self.path = Path(path) + self.parts = [] + last_attr = class_ + for value in self.path: + last_attr = get_attr(last_attr, value) + self.parts.append(last_attr) + + def __iter__(self): + for part in self.parts: + yield part + + def __invert__(self): + + +## ... source file continues with no further InstrumentedAttribute examples... + +``` + + +## Example 3 from WTForms-Alchemy +[wtforms-alchemy](git@github.com:kvesteri/wtforms-alchemy.git) +([documentation](https://wtforms-alchemy.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/WTForms-Alchemy/)) +is a [WTForms](https://wtforms.readthedocs.io/en/2.2.1/) extension toolkit +for easier creation of [SQLAlchemy](/sqlalchemy.html) model based forms. +While this project primarily focuses on proper form handling, it also +has many good examples of how to use various parts of SQLAlchemy in +its code base. The project is provided as open source under the +[MIT license](https://github.com/kvesteri/wtforms-alchemy/blob/master/LICENSE). + +[**WTForms-Alchemy / wtforms_alchemy / validators.py**](https://github.com/kvesteri/wtforms-alchemy/blob/master/wtforms_alchemy/./validators.py) + +```python +# validators.py +from collections.abc import Iterable, Mapping + +import six +from sqlalchemy import Column +~~from sqlalchemy.orm.attributes import InstrumentedAttribute +from wtforms import ValidationError + + +class Unique(object): + field_flags = ('unique', ) + + def __init__(self, column, get_session=None, message=None): + self.column = column + self.message = message + self.get_session = get_session + + @property + def query(self): + self._check_for_session(self.model) + if self.get_session: + return self.get_session().query(self.model) + elif hasattr(self.model, 'query'): + return getattr(self.model, 'query') + else: + raise Exception( + 'Validator requires either get_session or Flask-SQLAlchemy' + ' styled query parameter' + ) + + + +## ... source file continues with no further InstrumentedAttribute examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes-queryableattribute.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes-queryableattribute.markdown new file mode 100644 index 000000000..6cddccc55 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes-queryableattribute.markdown @@ -0,0 +1,69 @@ +title: sqlalchemy.orm.attributes QueryableAttribute Example Code +category: page +slug: sqlalchemy-orm-attributes-queryableattribute-examples +sortorder: 500031077 +toc: False +sidebartitle: sqlalchemy.orm.attributes QueryableAttribute +meta: Example code for understanding how to use the QueryableAttribute class from the sqlalchemy.orm.attributes module of the SQLAlchemy project. + + +`QueryableAttribute` is a class within the `sqlalchemy.orm.attributes` module of the SQLAlchemy project. + +InstrumentedAttribute +and +flag_modified +are a couple of other callables within the `sqlalchemy.orm.attributes` package that also have code examples. + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / attributes.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./attributes.py) + +```python +# attributes.py + + +~~from sqlalchemy.orm.attributes import QueryableAttribute as SA_QueryableAttribute +from sqlalchemy import util + +from validator_collection import validators, checkers + +from sqlathanor._serialization_support import SerializationMixin +from sqlathanor.utilities import bool_to_tuple, callable_to_dict + + +BLANK_ON_SERIALIZE = { + 'csv': None, + 'json': None, + 'yaml': None, + 'dict': None +} + + +class AttributeConfiguration(SerializationMixin): + + def __init__(self, + *args, + **kwargs): + object.__setattr__(self, '_dict_proxy', {}) + self._current = -1 + self._name = None + + +## ... source file continues with no further QueryableAttribute examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes.markdown new file mode 100644 index 000000000..a03177b3f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-attributes.markdown @@ -0,0 +1,175 @@ +title: sqlalchemy.orm attributes Example Code +category: page +slug: sqlalchemy-orm-attributes-examples +sortorder: 500031062 +toc: False +sidebartitle: sqlalchemy.orm attributes +meta: Python example code that shows how to use the attributes callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`attributes` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / generic.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./generic.py) + +```python +# generic.py +from collections.abc import Iterable + +import six +import sqlalchemy as sa +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import attributes, class_mapper, ColumnProperty +from sqlalchemy.orm.interfaces import MapperProperty, PropComparator +from sqlalchemy.orm.session import _state_session +from sqlalchemy.util import set_creation_order + +from .exceptions import ImproperlyConfigured +from .functions import identity + + +class GenericAttributeImpl(attributes.ScalarAttributeImpl): +~~ def get(self, state, dict_, passive=attributes.PASSIVE_OFF): + if self.key in dict_: + return dict_[self.key] + + session = _state_session(state) + if session is None: + return None + + discriminator = self.get_state_discriminator(state) + target_class = state.class_._decl_class_registry.get(discriminator) + + if target_class is None: + return None + + id = self.get_state_id(state) + + +## ... source file abbreviated to get to attributes examples ... + + + self.property = prop + self._parententity = parentmapper + + def __eq__(self, other): + discriminator = six.text_type(type(other).__name__) + q = self.property._discriminator_col == discriminator + other_id = identity(other) + for index, id in enumerate(self.property._id_cols): + q &= id == other_id[index] + return q + + def __ne__(self, other): + return -(self == other) + + def is_type(self, other): + mapper = sa.inspect(other) + class_names = [six.text_type(other.__name__)] + class_names.extend([ + six.text_type(submapper.class_.__name__) + for submapper in mapper._inheriting_mappers + ]) + + return self.property._discriminator_col.in_(class_names) + + def instrument_class(self, mapper): +~~ attributes.register_attribute( + mapper.class_, + self.key, + comparator=self.Comparator(self, mapper), + parententity=mapper, + doc=self.doc, + impl_class=GenericAttributeImpl, + parent_token=self + ) + + +def generic_relationship(*args, **kwargs): + return GenericRelationshipProperty(*args, **kwargs) + + + target = session.query(target_class).get(id) + + return target + + def get_state_discriminator(self, state): + discriminator = self.parent_token.discriminator + if isinstance(discriminator, hybrid_property): + return getattr(state.obj(), discriminator.__name__) + else: + return state.attrs[discriminator.key].value + + def get_state_id(self, state): + return tuple(state.attrs[id.key].value for id in self.parent_token.id) + + def set(self, state, dict_, initiator, +~~ passive=attributes.PASSIVE_OFF, + check_old=None, + pop=False): + + dict_[self.key] = initiator + + if initiator is None: + for id in self.parent_token.id: + dict_[id.key] = None + dict_[self.parent_token.discriminator.key] = None + else: + class_ = type(initiator) + mapper = class_mapper(class_) + + pk = mapper.identity_key_from_instance(initiator)[1] + + discriminator = six.text_type(class_.__name__) + + for index, id in enumerate(self.parent_token.id): + dict_[id.key] = pk[index] + dict_[self.parent_token.discriminator.key] = discriminator + + +class GenericRelationshipProperty(MapperProperty): + + + +## ... source file continues with no further attributes examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-backref.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-backref.markdown new file mode 100644 index 000000000..976a36212 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-backref.markdown @@ -0,0 +1,103 @@ +title: sqlalchemy.orm backref Example Code +category: page +slug: sqlalchemy-orm-backref-examples +sortorder: 500031063 +toc: False +sidebartitle: sqlalchemy.orm backref +meta: Python example code that shows how to use the backref callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`backref` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from sqlalchemy-datatables +[sqlalchemy-datatables](https://github.com/Pegase745/sqlalchemy-datatables) +([PyPI package information](https://pypi.org/project/sqlalchemy-datatables/)) +is a helper library that makes it easier to use [SQLAlchemy](/sqlalchemy.html) +with the jQuery [JavaScript](/javascript.html) +[DataTables](https://datatables.net/) plugin. This library is designed to +be [web framework](/web-frameworks.html) agnostic and provides code examples +for both [Flask](/flask.html) and [Pyramid](/pyramid.html). + +The project is built and maintained by +[Michel Nemnom (Pegase745)](https://github.com/Pegase745) and is open +sourced under the +[MIT license](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/LICENSE). + +[**sqlalchemy-datatables / tests / models.py**](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/./tests/models.py) + +```python +# models.py +import datetime + +from sqlalchemy import Column, Date, DateTime, ForeignKey, Integer, String, func +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import backref, relationship + +Base = declarative_base() + + +class User(Base): + + __tablename__ = 'users' + + id = Column(Integer, primary_key=True) + name = Column(String, unique=True) + created_at = Column(DateTime, default=datetime.datetime.utcnow) + birthday = Column(Date) +~~ address = relationship('Address', uselist=False, backref=backref('user')) + + def __unicode__(self): + return '%s' % self.name + + def __repr__(self): + return '<%s#%s>' % (self.__class__.__name__, self.id) + + @hybrid_property + def dummy(self): + return self.name[0:3] + + @dummy.expression + def dummy(cls): + return func.substr(cls.name, 0, 3) + + +class Address(Base): + + __tablename__ = 'addresses' + + id = Column(Integer, primary_key=True) + description = Column(String, unique=True) + user_id = Column(Integer, ForeignKey('users.id')) + + + +## ... source file continues with no further backref examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-class-mapper.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-class-mapper.markdown new file mode 100644 index 000000000..052598f8b --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-class-mapper.markdown @@ -0,0 +1,222 @@ +title: sqlalchemy.orm class_mapper Example Code +category: page +slug: sqlalchemy-orm-class-mapper-examples +sortorder: 500031064 +toc: False +sidebartitle: sqlalchemy.orm class_mapper +meta: Python example code that shows how to use the class_mapper callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`class_mapper` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / utils.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./utils.py) + +```python +# utils.py +import re +import warnings + +from sqlalchemy.exc import ArgumentError +~~from sqlalchemy.orm import class_mapper, object_mapper +from sqlalchemy.orm.exc import UnmappedClassError, UnmappedInstanceError + + +def get_session(context): + return context.get("session") + + +def get_query(model, context): + query = getattr(model, "query", None) + if not query: + session = get_session(context) + if not session: + raise Exception( + "A query in the model Base or a session in the schema is required for querying.\n" + "Read more http://docs.graphene-python.org/projects/sqlalchemy/en/latest/tips/#querying" + ) + query = session.query(model) + return query + + +def is_mapped_class(cls): + try: +~~ class_mapper(cls) + except (ArgumentError, UnmappedClassError): + return False + else: + return True + + +def is_mapped_instance(cls): + try: + object_mapper(cls) + except (ArgumentError, UnmappedInstanceError): + return False + else: + return True + + +def to_type_name(name): + return "".join(part[:1].upper() + part[1:] for part in name.split("_")) + + +_re_enum_value_name_1 = re.compile("(.)([A-Z][a-z]+)") +_re_enum_value_name_2 = re.compile("([a-z0-9])([A-Z])") + + +def to_enum_value_name(name): + + +## ... source file continues with no further class_mapper examples... + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / generic.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./generic.py) + +```python +# generic.py +from collections.abc import Iterable + +import six +import sqlalchemy as sa +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import attributes, class_mapper, ColumnProperty +from sqlalchemy.orm.interfaces import MapperProperty, PropComparator +from sqlalchemy.orm.session import _state_session +from sqlalchemy.util import set_creation_order + +from .exceptions import ImproperlyConfigured +from .functions import identity + + +class GenericAttributeImpl(attributes.ScalarAttributeImpl): + def get(self, state, dict_, passive=attributes.PASSIVE_OFF): + if self.key in dict_: + return dict_[self.key] + + session = _state_session(state) + if session is None: + return None + + discriminator = self.get_state_discriminator(state) + target_class = state.class_._decl_class_registry.get(discriminator) + + if target_class is None: + return None + + id = self.get_state_id(state) + + +## ... source file abbreviated to get to class_mapper examples ... + + + return target + + def get_state_discriminator(self, state): + discriminator = self.parent_token.discriminator + if isinstance(discriminator, hybrid_property): + return getattr(state.obj(), discriminator.__name__) + else: + return state.attrs[discriminator.key].value + + def get_state_id(self, state): + return tuple(state.attrs[id.key].value for id in self.parent_token.id) + + def set(self, state, dict_, initiator, + passive=attributes.PASSIVE_OFF, + check_old=None, + pop=False): + + dict_[self.key] = initiator + + if initiator is None: + for id in self.parent_token.id: + dict_[id.key] = None + dict_[self.parent_token.discriminator.key] = None + else: + class_ = type(initiator) +~~ mapper = class_mapper(class_) + + pk = mapper.identity_key_from_instance(initiator)[1] + + discriminator = six.text_type(class_.__name__) + + for index, id in enumerate(self.parent_token.id): + dict_[id.key] = pk[index] + dict_[self.parent_token.discriminator.key] = discriminator + + +class GenericRelationshipProperty(MapperProperty): + + def __init__(self, discriminator, id, doc=None): + super(GenericRelationshipProperty, self).__init__() + self._discriminator_col = discriminator + self._id_cols = id + self._id = None + self._discriminator = None + self.doc = doc + + set_creation_order(self) + + def _column_to_property(self, column): + if isinstance(column, hybrid_property): + + +## ... source file continues with no further class_mapper examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-collections-instrumentedlist.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-collections-instrumentedlist.markdown new file mode 100644 index 000000000..cc3017f82 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-collections-instrumentedlist.markdown @@ -0,0 +1,156 @@ +title: sqlalchemy.orm.collections InstrumentedList Example Code +category: page +slug: sqlalchemy-orm-collections-instrumentedlist-examples +sortorder: 500031079 +toc: False +sidebartitle: sqlalchemy.orm.collections InstrumentedList +meta: Example code for understanding how to use the InstrumentedList class from the sqlalchemy.orm.collections module of the SQLAlchemy project. + + +`InstrumentedList` is a class within the `sqlalchemy.orm.collections` module of the SQLAlchemy project. + + + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / types / __init__.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/types/__init__.py) + +```python +# __init__.py +from functools import wraps + +~~from sqlalchemy.orm.collections import InstrumentedList as _InstrumentedList + +from .arrow import ArrowType # noqa +from .choice import Choice, ChoiceType # noqa +from .color import ColorType # noqa +from .country import CountryType # noqa +from .currency import CurrencyType # noqa +from .email import EmailType # noqa +from .encrypted.encrypted_type import EncryptedType # noqa +from .enriched_datetime.enriched_date_type import EnrichedDateType # noqa +from .ip_address import IPAddressType # noqa +from .json import JSONType # noqa +from .locale import LocaleType # noqa +from .ltree import LtreeType # noqa +from .password import Password, PasswordType # noqa +from .pg_composite import ( # noqa + CompositeArray, + CompositeType, + register_composites, + remove_composite_listeners +) +from .phone_number import ( # noqa + PhoneNumber, + PhoneNumberParseException, + PhoneNumberType +) +from .range import ( # noqa + DateRangeType, + DateTimeRangeType, + Int8RangeType, + IntRangeType, + NumericRangeType +) +from .scalar_list import ScalarListException, ScalarListType # noqa +from .timezone import TimezoneType # noqa +from .ts_vector import TSVectorType # noqa +from .url import URLType # noqa +from .uuid import UUIDType # noqa +from .weekdays import WeekDaysType # noqa + +from .enriched_datetime.enriched_datetime_type import EnrichedDateTimeType # noqa isort:skip + + +~~class InstrumentedList(_InstrumentedList): + + def any(self, attr): + return any(getattr(item, attr) for item in self) + + def all(self, attr): + return all(getattr(item, attr) for item in self) + + +def instrumented_list(f): + @wraps(f) + def wrapper(*args, **kwargs): +~~ return InstrumentedList([item for item in f(*args, **kwargs)]) + return wrapper + + + +## ... source file continues with no further InstrumentedList examples... + +``` + + +## Example 2 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / utilities.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./utilities.py) + +```python +# utilities.py + +import csv +import linecache +import warnings +import yaml +from collections import OrderedDict + +~~from sqlalchemy.orm.collections import InstrumentedList +from sqlalchemy.exc import InvalidRequestError as SA_InvalidRequestError +from sqlalchemy.exc import UnsupportedCompilationError as SA_UnsupportedCompilationError + +from validator_collection import validators, checkers +from validator_collection.errors import NotAnIterableError + +from sqlathanor._compat import json, is_py2, is_py36, is_py35, dict as dict_ +from sqlathanor.errors import InvalidFormatError, UnsupportedSerializationError, \ + UnsupportedDeserializationError, MaximumNestingExceededError, \ + MaximumNestingExceededWarning, DeserializationError, CSVStructureError + +UTILITY_COLUMNS = [ + 'metadata', + 'primary_key_value', + '_decl_class_registry', + '_sa_instance_state', + '_sa_class_manager' +] + +def bool_to_tuple(input): + + if input is True: + input = (True, True) + elif not input: + + +## ... source file continues with no further InstrumentedList examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-column-property.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-column-property.markdown new file mode 100644 index 000000000..c8b6ef253 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-column-property.markdown @@ -0,0 +1,148 @@ +title: sqlalchemy.orm column_property Example Code +category: page +slug: sqlalchemy-orm-column-property-examples +sortorder: 500031065 +toc: False +sidebartitle: sqlalchemy.orm column_property +meta: Python example code that shows how to use the column_property callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`column_property` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / tests / models.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/tests/models.py) + +```python +# models.py +from __future__ import absolute_import + +import enum + +from sqlalchemy import (Column, Date, Enum, ForeignKey, Integer, String, Table, + func, select) +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import column_property, composite, mapper, relationship + +PetKind = Enum("cat", "dog", name="pet_kind") + + +class HairKind(enum.Enum): + LONG = 'long' + SHORT = 'short' + + +Base = declarative_base() + +association_table = Table( + "association", + Base.metadata, + Column("pet_id", Integer, ForeignKey("pets.id")), + Column("reporter_id", Integer, ForeignKey("reporters.id")), +) + + +class Editor(Base): + __tablename__ = "editors" + editor_id = Column(Integer(), primary_key=True) + name = Column(String(100)) + + + +## ... source file abbreviated to get to column_property examples ... + + + self.last_name = last_name + + def __composite_values__(self): + return self.first_name, self.last_name + + def __repr__(self): + return "{} {}".format(self.first_name, self.last_name) + + +class Reporter(Base): + __tablename__ = "reporters" + + id = Column(Integer(), primary_key=True) + first_name = Column(String(30), doc="First name") + last_name = Column(String(30), doc="Last name") + email = Column(String(), doc="Email") + favorite_pet_kind = Column(PetKind) + pets = relationship("Pet", secondary=association_table, backref="reporters", order_by="Pet.id") + articles = relationship("Article", backref="reporter") + favorite_article = relationship("Article", uselist=False) + + @hybrid_property + def hybrid_prop(self): + return self.first_name + +~~ column_prop = column_property( + select([func.cast(func.count(id), Integer)]), doc="Column property" + ) + + composite_prop = composite(CompositeFullName, first_name, last_name, doc="Composite") + + +class Article(Base): + __tablename__ = "articles" + id = Column(Integer(), primary_key=True) + headline = Column(String(100)) + pub_date = Column(Date()) + reporter_id = Column(Integer(), ForeignKey("reporters.id")) + + +class ReflectedEditor(type): + + @classmethod + def __subclasses__(cls): + return [] + + +editor_table = Table("editors", Base.metadata, autoload=True) + +mapper(ReflectedEditor, editor_table) + + +## ... source file continues with no further column_property examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-columnproperty.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-columnproperty.markdown new file mode 100644 index 000000000..b96af0043 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-columnproperty.markdown @@ -0,0 +1,355 @@ +title: sqlalchemy.orm ColumnProperty Example Code +category: page +slug: sqlalchemy-orm-columnproperty-examples +sortorder: 500031054 +toc: False +sidebartitle: sqlalchemy.orm ColumnProperty +meta: Example code for understanding how to use the ColumnProperty class from the sqlalchemy.orm module of the SQLAlchemy project. + + +`ColumnProperty` is a class within the `sqlalchemy.orm` module of the SQLAlchemy project. + +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / enums.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./enums.py) + +```python +# enums.py +import six +~~from sqlalchemy.orm import ColumnProperty +from sqlalchemy.types import Enum as SQLAlchemyEnumType + +from graphene import Argument, Enum, List + +from .utils import EnumValue, to_enum_value_name, to_type_name + + +def _convert_sa_to_graphene_enum(sa_enum, fallback_name=None): + if not isinstance(sa_enum, SQLAlchemyEnumType): + raise TypeError( + "Expected sqlalchemy.types.Enum, but got: {!r}".format(sa_enum) + ) + enum_class = sa_enum.enum_class + if enum_class: + if all(to_enum_value_name(key) == key for key in enum_class.__members__): + return Enum.from_enum(enum_class) + name = enum_class.__name__ + members = [ + (to_enum_value_name(key), value.value) + for key, value in enum_class.__members__.items() + ] + else: + sql_enum_name = sa_enum.name + if sql_enum_name: + + +## ... source file abbreviated to get to ColumnProperty examples ... + + +def enum_for_sa_enum(sa_enum, registry): + if not isinstance(sa_enum, SQLAlchemyEnumType): + raise TypeError( + "Expected sqlalchemy.types.Enum, but got: {!r}".format(sa_enum) + ) + enum = registry.get_graphene_enum_for_sa_enum(sa_enum) + if not enum: + enum = _convert_sa_to_graphene_enum(sa_enum) + registry.register_enum(sa_enum, enum) + return enum + + +def enum_for_field(obj_type, field_name): + from .types import SQLAlchemyObjectType + + if not isinstance(obj_type, type) or not issubclass(obj_type, SQLAlchemyObjectType): + raise TypeError( + "Expected SQLAlchemyObjectType, but got: {!r}".format(obj_type)) + if not field_name or not isinstance(field_name, six.string_types): + raise TypeError( + "Expected a field name, but got: {!r}".format(field_name)) + registry = obj_type._meta.registry + orm_field = registry.get_orm_field_for_graphene_field(obj_type, field_name) + if orm_field is None: + raise TypeError("Cannot get {}.{}".format(obj_type._meta.name, field_name)) +~~ if not isinstance(orm_field, ColumnProperty): + raise TypeError( + "{}.{} does not map to model column".format(obj_type._meta.name, field_name) + ) + column = orm_field.columns[0] + sa_enum = column.type + if not isinstance(sa_enum, SQLAlchemyEnumType): + raise TypeError( + "{}.{} does not map to enum column".format(obj_type._meta.name, field_name) + ) + enum = registry.get_graphene_enum_for_sa_enum(sa_enum) + if not enum: + fallback_name = obj_type._meta.name + to_type_name(field_name) + enum = _convert_sa_to_graphene_enum(sa_enum, fallback_name) + registry.register_enum(sa_enum, enum) + return enum + + +def _default_sort_enum_symbol_name(column_name, sort_asc=True): + return to_enum_value_name(column_name) + ("_ASC" if sort_asc else "_DESC") + + +def sort_enum_for_object_type( + obj_type, name=None, only_fields=None, only_indexed=None, get_symbol_name=None +): + name = name or obj_type._meta.name + "SortEnum" + registry = obj_type._meta.registry + enum = registry.get_sort_enum_for_object_type(obj_type) + custom_options = dict( + only_fields=only_fields, + only_indexed=only_indexed, + get_symbol_name=get_symbol_name, + ) + if enum: + if name != enum.__name__ or custom_options != enum.custom_options: + raise ValueError( + "Sort enum for {} has already been customized".format(obj_type) + ) + else: + members = [] + default = [] + fields = obj_type._meta.fields + get_name = get_symbol_name or _default_sort_enum_symbol_name + for field_name in fields: + if only_fields and field_name not in only_fields: + continue + orm_field = registry.get_orm_field_for_graphene_field(obj_type, field_name) +~~ if not isinstance(orm_field, ColumnProperty): + continue + column = orm_field.columns[0] + if only_indexed and not (column.primary_key or column.index): + continue + asc_name = get_name(column.name, True) + asc_value = EnumValue(asc_name, column.asc()) + desc_name = get_name(column.name, False) + desc_value = EnumValue(desc_name, column.desc()) + if column.primary_key: + default.append(asc_value) + members.extend(((asc_name, asc_value), (desc_name, desc_value))) + enum = Enum(name, members) + enum.default = default # store default as attribute + enum.custom_options = custom_options + registry.register_sort_enum(obj_type, enum) + return enum + + +def sort_argument_for_object_type( + obj_type, + enum_name=None, + only_fields=None, + only_indexed=None, + get_symbol_name=None, + + +## ... source file continues with no further ColumnProperty examples... + +``` + + +## Example 2 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management that is +powered by [SQLAlchemy](/sqlalchemy.html) on the backend. The code +for this project is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / core / marshmallow.py**](https://github.com/indico/indico/blob/master/indico/core/marshmallow.py) + +```python +# marshmallow.py + +from __future__ import absolute_import, unicode_literals + +from inspect import getmro + +from flask_marshmallow import Marshmallow +from flask_marshmallow.sqla import SchemaOpts +from marshmallow import fields, post_dump, post_load, pre_load +from marshmallow_enum import EnumField +from marshmallow_sqlalchemy import ModelConverter +from marshmallow_sqlalchemy import ModelSchema as MSQLAModelSchema +~~from sqlalchemy.orm import ColumnProperty +from sqlalchemy.sql.elements import Label +from webargs.flaskparser import parser as webargs_flask_parser + +from indico.core import signals +from indico.core.db.sqlalchemy import PyIntEnum, UTCDateTime +from indico.web.args import parser as indico_webargs_flask_parser + + +mm = Marshmallow() + + +def _is_column_property(prop): + return hasattr(prop, 'columns') and isinstance(prop.columns[0], Label) + + +class IndicoModelConverter(ModelConverter): + SQLA_TYPE_MAPPING = ModelConverter.SQLA_TYPE_MAPPING.copy() + SQLA_TYPE_MAPPING.update({ + UTCDateTime: fields.DateTime, + PyIntEnum: EnumField + }) + + def _get_field_kwargs_for_property(self, prop): + kwargs = super(IndicoModelConverter, self)._get_field_kwargs_for_property(prop) + + +## ... source file continues with no further ColumnProperty examples... + +``` + + +## Example 3 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / generic.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./generic.py) + +```python +# generic.py +from collections.abc import Iterable + +import six +import sqlalchemy as sa +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import attributes, class_mapper, ColumnProperty +from sqlalchemy.orm.interfaces import MapperProperty, PropComparator +from sqlalchemy.orm.session import _state_session +from sqlalchemy.util import set_creation_order + +from .exceptions import ImproperlyConfigured +from .functions import identity + + +class GenericAttributeImpl(attributes.ScalarAttributeImpl): + def get(self, state, dict_, passive=attributes.PASSIVE_OFF): + if self.key in dict_: + return dict_[self.key] + + session = _state_session(state) + if session is None: + return None + + discriminator = self.get_state_discriminator(state) + target_class = state.class_._decl_class_registry.get(discriminator) + + if target_class is None: + return None + + id = self.get_state_id(state) + + +## ... source file abbreviated to get to ColumnProperty examples ... + + + for index, id in enumerate(self.parent_token.id): + dict_[id.key] = pk[index] + dict_[self.parent_token.discriminator.key] = discriminator + + +class GenericRelationshipProperty(MapperProperty): + + def __init__(self, discriminator, id, doc=None): + super(GenericRelationshipProperty, self).__init__() + self._discriminator_col = discriminator + self._id_cols = id + self._id = None + self._discriminator = None + self.doc = doc + + set_creation_order(self) + + def _column_to_property(self, column): + if isinstance(column, hybrid_property): + attr_key = column.__name__ + for key, attr in self.parent.all_orm_descriptors.items(): + if key == attr_key: + return attr + else: + for key, attr in self.parent.attrs.items(): +~~ if isinstance(attr, ColumnProperty): + if attr.columns[0].name == column.name: + return attr + + def init(self): + def convert_strings(column): + if isinstance(column, six.string_types): + return self.parent.columns[column] + return column + + self._discriminator_col = convert_strings(self._discriminator_col) + self._id_cols = convert_strings(self._id_cols) + + if isinstance(self._id_cols, Iterable): + self._id_cols = list(map(convert_strings, self._id_cols)) + else: + self._id_cols = [self._id_cols] + + self.discriminator = self._column_to_property(self._discriminator_col) + + if self.discriminator is None: + raise ImproperlyConfigured( + 'Could not find discriminator descriptor.' + ) + + + +## ... source file continues with no further ColumnProperty examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-composite.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-composite.markdown new file mode 100644 index 000000000..3848c031f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-composite.markdown @@ -0,0 +1,145 @@ +title: sqlalchemy.orm composite Example Code +category: page +slug: sqlalchemy-orm-composite-examples +sortorder: 500031066 +toc: False +sidebartitle: sqlalchemy.orm composite +meta: Python example code that shows how to use the composite callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`composite` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / tests / models.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/tests/models.py) + +```python +# models.py +from __future__ import absolute_import + +import enum + +from sqlalchemy import (Column, Date, Enum, ForeignKey, Integer, String, Table, + func, select) +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import column_property, composite, mapper, relationship + +PetKind = Enum("cat", "dog", name="pet_kind") + + +class HairKind(enum.Enum): + LONG = 'long' + SHORT = 'short' + + +Base = declarative_base() + +association_table = Table( + "association", + Base.metadata, + Column("pet_id", Integer, ForeignKey("pets.id")), + Column("reporter_id", Integer, ForeignKey("reporters.id")), +) + + +class Editor(Base): + __tablename__ = "editors" + editor_id = Column(Integer(), primary_key=True) + name = Column(String(100)) + + + +## ... source file abbreviated to get to composite examples ... + + + + def __repr__(self): + return "{} {}".format(self.first_name, self.last_name) + + +class Reporter(Base): + __tablename__ = "reporters" + + id = Column(Integer(), primary_key=True) + first_name = Column(String(30), doc="First name") + last_name = Column(String(30), doc="Last name") + email = Column(String(), doc="Email") + favorite_pet_kind = Column(PetKind) + pets = relationship("Pet", secondary=association_table, backref="reporters", order_by="Pet.id") + articles = relationship("Article", backref="reporter") + favorite_article = relationship("Article", uselist=False) + + @hybrid_property + def hybrid_prop(self): + return self.first_name + + column_prop = column_property( + select([func.cast(func.count(id), Integer)]), doc="Column property" + ) + +~~ composite_prop = composite(CompositeFullName, first_name, last_name, doc="Composite") + + +class Article(Base): + __tablename__ = "articles" + id = Column(Integer(), primary_key=True) + headline = Column(String(100)) + pub_date = Column(Date()) + reporter_id = Column(Integer(), ForeignKey("reporters.id")) + + +class ReflectedEditor(type): + + @classmethod + def __subclasses__(cls): + return [] + + +editor_table = Table("editors", Base.metadata, autoload=True) + +mapper(ReflectedEditor, editor_table) + + + +## ... source file continues with no further composite examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-compositeproperty.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-compositeproperty.markdown new file mode 100644 index 000000000..a1843a7bd --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-compositeproperty.markdown @@ -0,0 +1,144 @@ +title: sqlalchemy.orm CompositeProperty Example Code +category: page +slug: sqlalchemy-orm-compositeproperty-examples +sortorder: 500031055 +toc: False +sidebartitle: sqlalchemy.orm CompositeProperty +meta: Example code for understanding how to use the CompositeProperty class from the sqlalchemy.orm module of the SQLAlchemy project. + + +`CompositeProperty` is a class within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / types.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./types.py) + +```python +# types.py +from collections import OrderedDict + +import sqlalchemy +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import (ColumnProperty, CompositeProperty, + RelationshipProperty) +from sqlalchemy.orm.exc import NoResultFound + +from graphene import Field +from graphene.relay import Connection, Node +from graphene.types.objecttype import ObjectType, ObjectTypeOptions +from graphene.types.utils import yank_fields_from_attrs +from graphene.utils.orderedtype import OrderedType + +from .converter import (convert_sqlalchemy_column, + convert_sqlalchemy_composite, + convert_sqlalchemy_hybrid_method, + convert_sqlalchemy_relationship) +from .enums import (enum_for_field, sort_argument_for_object_type, + sort_enum_for_object_type) +from .registry import Registry, get_global_registry +from .resolvers import get_attr_resolver, get_custom_resolver +from .utils import get_query, is_mapped_class, is_mapped_instance + + +class ORMField(OrderedType): + def __init__( + self, + model_attr=None, + + +## ... source file abbreviated to get to CompositeProperty examples ... + + + if attr_name not in all_model_attrs: + raise ValueError(( + "Cannot map ORMField to a model attribute.\n" + "Field: '{}.{}'" + ).format(obj_type.__name__, orm_field_name,)) + orm_field.kwargs['model_attr'] = attr_name + + orm_fields = OrderedDict(custom_orm_fields_items) + for orm_field_name in auto_orm_field_names: + if orm_field_name in orm_fields: + continue + orm_fields[orm_field_name] = ORMField(model_attr=orm_field_name) + + fields = OrderedDict() + for orm_field_name, orm_field in orm_fields.items(): + attr_name = orm_field.kwargs.pop('model_attr') + attr = all_model_attrs[attr_name] + resolver = get_custom_resolver(obj_type, orm_field_name) or get_attr_resolver(obj_type, attr_name) + + if isinstance(attr, ColumnProperty): + field = convert_sqlalchemy_column(attr, registry, resolver, **orm_field.kwargs) + elif isinstance(attr, RelationshipProperty): + batching_ = orm_field.kwargs.pop('batching', batching) + field = convert_sqlalchemy_relationship( + attr, obj_type, connection_field_factory, batching_, orm_field_name, **orm_field.kwargs) +~~ elif isinstance(attr, CompositeProperty): + if attr_name != orm_field_name or orm_field.kwargs: + raise ValueError( + "ORMField kwargs for composite fields must be empty. " + "Field: {}.{}".format(obj_type.__name__, orm_field_name)) + field = convert_sqlalchemy_composite(attr, registry, resolver) + elif isinstance(attr, hybrid_property): + field = convert_sqlalchemy_hybrid_method(attr, resolver, **orm_field.kwargs) + else: + raise Exception('Property type is not supported') # Should never happen + + registry.register_orm_field(obj_type, orm_field_name, attr) + fields[orm_field_name] = field + + return fields + + +class SQLAlchemyObjectTypeOptions(ObjectTypeOptions): + model = None # type: sqlalchemy.Model + registry = None # type: sqlalchemy.Registry + connection = None # type: sqlalchemy.Type[sqlalchemy.Connection] + id = None # type: str + + +class SQLAlchemyObjectType(ObjectType): + + +## ... source file continues with no further CompositeProperty examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-exc-noresultfound.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-exc-noresultfound.markdown new file mode 100644 index 000000000..ecfd4dc6c --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-exc-noresultfound.markdown @@ -0,0 +1,343 @@ +title: sqlalchemy.orm.exc NoResultFound Example Code +category: page +slug: sqlalchemy-orm-exc-noresultfound-examples +sortorder: 500031080 +toc: False +sidebartitle: sqlalchemy.orm.exc NoResultFound +meta: Example code for understanding how to use the NoResultFound class from the sqlalchemy.orm.exc module of the SQLAlchemy project. + + +`NoResultFound` is a class within the `sqlalchemy.orm.exc` module of the SQLAlchemy project. + +UnmappedClassError +and +UnmappedInstanceError +are a couple of other callables within the `sqlalchemy.orm.exc` package that also have code examples. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / types.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./types.py) + +```python +# types.py +from collections import OrderedDict + +import sqlalchemy +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import (ColumnProperty, CompositeProperty, + RelationshipProperty) +~~from sqlalchemy.orm.exc import NoResultFound + +from graphene import Field +from graphene.relay import Connection, Node +from graphene.types.objecttype import ObjectType, ObjectTypeOptions +from graphene.types.utils import yank_fields_from_attrs +from graphene.utils.orderedtype import OrderedType + +from .converter import (convert_sqlalchemy_column, + convert_sqlalchemy_composite, + convert_sqlalchemy_hybrid_method, + convert_sqlalchemy_relationship) +from .enums import (enum_for_field, sort_argument_for_object_type, + sort_enum_for_object_type) +from .registry import Registry, get_global_registry +from .resolvers import get_attr_resolver, get_custom_resolver +from .utils import get_query, is_mapped_class, is_mapped_instance + + +class ORMField(OrderedType): + def __init__( + self, + model_attr=None, + type=None, + required=None, + + +## ... source file abbreviated to get to NoResultFound examples ... + + + + super(SQLAlchemyObjectType, cls).__init_subclass_with_meta__( + _meta=_meta, interfaces=interfaces, **options + ) + + if not skip_registry: + registry.register(cls) + + @classmethod + def is_type_of(cls, root, info): + if isinstance(root, cls): + return True + if not is_mapped_instance(root): + raise Exception(('Received incompatible instance "{}".').format(root)) + return isinstance(root, cls._meta.model) + + @classmethod + def get_query(cls, info): + model = cls._meta.model + return get_query(model, info.context) + + @classmethod + def get_node(cls, info, id): + try: + return cls.get_query(info).get(id) +~~ except NoResultFound: + return None + + def resolve_id(self, info): + keys = self.__mapper__.primary_key_from_instance(self) + return tuple(keys) if len(keys) > 1 else keys[0] + + @classmethod + def enum_for_field(cls, field_name): + return enum_for_field(cls, field_name) + + sort_enum = classmethod(sort_enum_for_object_type) + + sort_argument = classmethod(sort_argument_for_object_type) + + + +## ... source file continues with no further NoResultFound examples... + +``` + + +## Example 2 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management that is +powered by [SQLAlchemy](/sqlalchemy.html) on the backend. The code +for this project is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / web / rh.py**](https://github.com/indico/indico/blob/master/indico/web/rh.py) + +```python +# rh.py + +from __future__ import absolute_import, unicode_literals + +import cProfile +import inspect +import itertools +import os +import time +from functools import partial, wraps + +import jsonschema +from flask import current_app, g, redirect, request, session +from sqlalchemy.exc import DatabaseError +~~from sqlalchemy.orm.exc import NoResultFound +from werkzeug.exceptions import BadRequest, Forbidden, MethodNotAllowed, NotFound +from werkzeug.routing import BuildError +from werkzeug.wrappers import Response + +from indico.core import signals +from indico.core.config import config +from indico.core.db import db +from indico.core.db.sqlalchemy.core import handle_sqlalchemy_database_error +from indico.core.logger import Logger, sentry_set_tags +from indico.core.notifications import flush_email_queue, init_email_queue +from indico.util import fossilize +from indico.util.i18n import _ +from indico.util.locators import get_locator +from indico.util.signals import values_from_signal +from indico.web.flask.util import url_for +from indico.web.util import is_signed_url_valid + + +HTTP_VERBS = {'GET', 'PATCH', 'POST', 'PUT', 'DELETE'} +logger = Logger.get('rh') + + +class RH(object): + CSRF_ENABLED = True # require a csrf_token when accessing the RH with anything but GET + + +## ... source file abbreviated to get to NoResultFound examples ... + + + valid_methods = [m for m in HTTP_VERBS if hasattr(self, '_process_' + m)] + raise MethodNotAllowed(valid_methods) + return method() + + def _check_csrf(self): + token = request.headers.get('X-CSRF-Token') or request.form.get('csrf_token') + if token is None: + token = next((v for k, v in request.form.iteritems() if k.endswith('-csrf_token')), None) + if self.CSRF_ENABLED and request.method != 'GET' and token != session.csrf_token: + msg = _("It looks like there was a problem with your current session. Please use your browser's back " + "button, reload the page and try again.") + raise BadRequest(msg) + + def _check_event_feature(self): + from indico.modules.events.features.util import require_feature + event_id = request.view_args.get('confId') or request.view_args.get('event_id') + if event_id is not None: + require_feature(event_id, self.EVENT_FEATURE) + + def _do_process(self): + try: + args_result = self._process_args() + signals.rh.process_args.send(type(self), rh=self, result=args_result) + if isinstance(args_result, (current_app.response_class, Response)): + return args_result +~~ except NoResultFound: # sqlalchemy .one() not finding anything + raise NotFound(_('The specified item could not be found.')) + + rv = self.normalize_url() + if rv is not None: + return rv + + self._check_access() + signals.rh.check_access.send(type(self), rh=self) + + signal_rv = values_from_signal(signals.rh.before_process.send(type(self), rh=self), + single_value=True, as_list=True) + if signal_rv and len(signal_rv) != 1: + raise Exception('More than one signal handler returned custom RH result') + elif signal_rv: + return signal_rv[0] + + if config.PROFILE: + result = [None] + profile_path = os.path.join(config.TEMP_DIR, '{}-{}.prof'.format(type(self).__name__, time.time())) + cProfile.runctx('result[0] = self._process()', globals(), locals(), profile_path) + rv = result[0] + else: + rv = self._process() + + + +## ... source file continues with no further NoResultFound examples... + +``` + + +## Example 3 from marshmallow-sqlalchemy +[marshmallow-sqlalchemy](https://github.com/marshmallow-code/marshmallow-sqlalchemy) +([project documentation](https://marshmallow-sqlalchemy.readthedocs.io/en/latest/)) +is a code library that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) with the +[Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +data serialization tool. + +The marshmallow-sqlalchemy project is provided as open source under the +[MIT license](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/LICENSE). + +[**marshmallow-sqlalchemy / src/marshmallow_sqlalchemy / fields.py**](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/src/marshmallow_sqlalchemy/./fields.py) + +```python +# fields.py +from marshmallow import fields +from marshmallow.utils import is_iterable_but_not_string + +from sqlalchemy import inspect +~~from sqlalchemy.orm.exc import NoResultFound + + +def get_primary_keys(model): + mapper = model.__mapper__ + return [mapper.get_property_by_column(column) for column in mapper.primary_key] + + +def ensure_list(value): + return value if is_iterable_but_not_string(value) else [value] + + +class RelatedList(fields.List): + def get_value(self, obj, attr, accessor=None): + return super(fields.List, self).get_value(obj, attr, accessor=accessor) + + +class Related(fields.Field): + + default_error_messages = { + "invalid": "Could not deserialize related value {value!r}; " + "expected a dictionary with keys {keys!r}" + } + + def __init__(self, column=None, **kwargs): + + +## ... source file abbreviated to get to NoResultFound examples ... + + + return self.root.session + + @property + def transient(self): + return self.root.transient + + def _serialize(self, value, attr, obj): + ret = {prop.key: getattr(value, prop.key, None) for prop in self.related_keys} + return ret if len(ret) > 1 else list(ret.values())[0] + + def _deserialize(self, value, *args, **kwargs): + if not isinstance(value, dict): + if len(self.related_keys) != 1: + keys = [prop.key for prop in self.related_keys] + if hasattr(self, "make_error"): + raise self.make_error("invalid", value=value, keys=keys) + else: # marshmallow 2 + self.fail("invalid", value=value, keys=keys) + value = {self.related_keys[0].key: value} + if self.transient: + return self.related_model(**value) + try: + result = self._get_existing_instance( + self.session.query(self.related_model), value + ) +~~ except NoResultFound: + return self.related_model(**value) + return result + + def _get_existing_instance(self, query, value): + if self.columns: + result = query.filter_by( + **{prop.key: value.get(prop.key) for prop in self.related_keys} + ).one() + else: + lookup_values = [value.get(prop.key) for prop in self.related_keys] + try: + result = query.get(lookup_values) + except TypeError: + keys = [prop.key for prop in self.related_keys] + if hasattr(self, "make_error"): + raise self.make_error("invalid", value=value, keys=keys) + else: # marshmallow 2 + self.fail("invalid", value=value, keys=keys) + if result is None: +~~ raise NoResultFound + return result + + +class Nested(fields.Nested): + + def _deserialize(self, *args, **kwargs): + if hasattr(self.schema, "session"): + self.schema.session = self.root.session + self.schema.transient = self.root.transient + return super()._deserialize(*args, **kwargs) + + + +## ... source file continues with no further NoResultFound examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-exc-unmappedclasserror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-exc-unmappedclasserror.markdown new file mode 100644 index 000000000..8e565fa42 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-exc-unmappedclasserror.markdown @@ -0,0 +1,219 @@ +title: sqlalchemy.orm.exc UnmappedClassError Example Code +category: page +slug: sqlalchemy-orm-exc-unmappedclasserror-examples +sortorder: 500031081 +toc: False +sidebartitle: sqlalchemy.orm.exc UnmappedClassError +meta: Example code for understanding how to use the UnmappedClassError class from the sqlalchemy.orm.exc module of the SQLAlchemy project. + + +`UnmappedClassError` is a class within the `sqlalchemy.orm.exc` module of the SQLAlchemy project. + +NoResultFound +and +UnmappedInstanceError +are a couple of other callables within the `sqlalchemy.orm.exc` package that also have code examples. + +## Example 1 from flask-sqlalchemy +[flask-sqlalchemy](https://github.com/pallets/flask-sqlalchemy) +([project documentation](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) +and +[PyPI information](https://pypi.org/project/Flask-SQLAlchemy/)) is a +[Flask](/flask.html) extension that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) when building Flask apps. flask-sqlalchemy +provides helper functions that reduce the amount of common boilerplate +code that you have to frequently write yourself if you did not use this +library when combining Flask with SQLAlchemy. + +flask-sqlalchemy is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/pallets/flask-sqlalchemy/blob/master/LICENSE.rst). + +[**flask-sqlalchemy / src/flask_sqlalchemy / __init__.py**](https://github.com/pallets/flask-sqlalchemy/blob/master/src/flask_sqlalchemy/./__init__.py) + +```python +# __init__.py +import functools +import os +import sys +import warnings +from math import ceil +from operator import itemgetter +from threading import Lock +from time import perf_counter + +import sqlalchemy +from flask import _app_ctx_stack +from flask import abort +from flask import current_app +from flask import request +from flask.signals import Namespace +from sqlalchemy import event +from sqlalchemy import inspect +from sqlalchemy import orm +from sqlalchemy.engine.url import make_url +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.declarative import DeclarativeMeta +~~from sqlalchemy.orm.exc import UnmappedClassError +from sqlalchemy.orm.session import Session as SessionBase + +from .model import DefaultMeta +from .model import Model + +__version__ = "3.0.0.dev" + +_signals = Namespace() +models_committed = _signals.signal("models-committed") +before_models_committed = _signals.signal("before-models-committed") + + +def _make_table(db): + def _make_table(*args, **kwargs): + if len(args) > 1 and isinstance(args[1], db.Column): + args = (args[0], db.metadata) + args[1:] + info = kwargs.pop("info", None) or {} + info.setdefault("bind_key", None) + kwargs["info"] = info + return sqlalchemy.Table(*args, **kwargs) + + return _make_table + + + + +## ... source file abbreviated to get to UnmappedClassError examples ... + + + else: + per_page = 20 + + items = self.limit(per_page).offset((page - 1) * per_page).all() + + if not items and page != 1 and error_out: + abort(404) + + if not count: + total = None + else: + total = self.order_by(None).count() + + return Pagination(self, page, per_page, total, items) + + +class _QueryProperty: + def __init__(self, sa): + self.sa = sa + + def __get__(self, obj, type): + try: + mapper = orm.class_mapper(type) + if mapper: + return type.query_class(mapper, session=self.sa.session()) +~~ except UnmappedClassError: + return None + + +def _record_queries(app): + if app.debug: + return True + rq = app.config["SQLALCHEMY_RECORD_QUERIES"] + if rq is not None: + return rq + return bool(app.config.get("TESTING")) + + +class _EngineConnector: + def __init__(self, sa, app, bind=None): + self._sa = sa + self._app = app + self._engine = None + self._connected_for = None + self._bind = bind + self._lock = Lock() + + def get_uri(self): + if self._bind is None: + return self._app.config["SQLALCHEMY_DATABASE_URI"] + + +## ... source file continues with no further UnmappedClassError examples... + +``` + + +## Example 2 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / utils.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./utils.py) + +```python +# utils.py +import re +import warnings + +from sqlalchemy.exc import ArgumentError +from sqlalchemy.orm import class_mapper, object_mapper +~~from sqlalchemy.orm.exc import UnmappedClassError, UnmappedInstanceError + + +def get_session(context): + return context.get("session") + + +def get_query(model, context): + query = getattr(model, "query", None) + if not query: + session = get_session(context) + if not session: + raise Exception( + "A query in the model Base or a session in the schema is required for querying.\n" + "Read more http://docs.graphene-python.org/projects/sqlalchemy/en/latest/tips/#querying" + ) + query = session.query(model) + return query + + +def is_mapped_class(cls): + try: + class_mapper(cls) +~~ except (ArgumentError, UnmappedClassError): + return False + else: + return True + + +def is_mapped_instance(cls): + try: + object_mapper(cls) + except (ArgumentError, UnmappedInstanceError): + return False + else: + return True + + +def to_type_name(name): + return "".join(part[:1].upper() + part[1:] for part in name.split("_")) + + +_re_enum_value_name_1 = re.compile("(.)([A-Z][a-z]+)") +_re_enum_value_name_2 = re.compile("([a-z0-9])([A-Z])") + + +def to_enum_value_name(name): + return _re_enum_value_name_2.sub( + + +## ... source file continues with no further UnmappedClassError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-exc-unmappedinstanceerror.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-exc-unmappedinstanceerror.markdown new file mode 100644 index 000000000..dd9ae4940 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-exc-unmappedinstanceerror.markdown @@ -0,0 +1,218 @@ +title: sqlalchemy.orm.exc UnmappedInstanceError Example Code +category: page +slug: sqlalchemy-orm-exc-unmappedinstanceerror-examples +sortorder: 500031082 +toc: False +sidebartitle: sqlalchemy.orm.exc UnmappedInstanceError +meta: Example code for understanding how to use the UnmappedInstanceError class from the sqlalchemy.orm.exc module of the SQLAlchemy project. + + +`UnmappedInstanceError` is a class within the `sqlalchemy.orm.exc` module of the SQLAlchemy project. + +NoResultFound +and +UnmappedClassError +are a couple of other callables within the `sqlalchemy.orm.exc` package that also have code examples. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / utils.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./utils.py) + +```python +# utils.py +import re +import warnings + +from sqlalchemy.exc import ArgumentError +from sqlalchemy.orm import class_mapper, object_mapper +~~from sqlalchemy.orm.exc import UnmappedClassError, UnmappedInstanceError + + +def get_session(context): + return context.get("session") + + +def get_query(model, context): + query = getattr(model, "query", None) + if not query: + session = get_session(context) + if not session: + raise Exception( + "A query in the model Base or a session in the schema is required for querying.\n" + "Read more http://docs.graphene-python.org/projects/sqlalchemy/en/latest/tips/#querying" + ) + query = session.query(model) + return query + + +def is_mapped_class(cls): + try: + class_mapper(cls) + except (ArgumentError, UnmappedClassError): + return False + else: + return True + + +def is_mapped_instance(cls): + try: + object_mapper(cls) +~~ except (ArgumentError, UnmappedInstanceError): + return False + else: + return True + + +def to_type_name(name): + return "".join(part[:1].upper() + part[1:] for part in name.split("_")) + + +_re_enum_value_name_1 = re.compile("(.)([A-Z][a-z]+)") +_re_enum_value_name_2 = re.compile("([a-z0-9])([A-Z])") + + +def to_enum_value_name(name): + return _re_enum_value_name_2.sub( + r"\1_\2", _re_enum_value_name_1.sub(r"\1_\2", name) + ).upper() + + +class EnumValue(str): + + def __new__(cls, s, value): + return super(EnumValue, cls).__new__(cls, s) + + + +## ... source file continues with no further UnmappedInstanceError examples... + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / orm.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/orm.py) + +```python +# orm.py +from collections import OrderedDict +from functools import partial +from inspect import isclass +from operator import attrgetter + +import six +import sqlalchemy as sa +from sqlalchemy.engine.interfaces import Dialect +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import mapperlib +from sqlalchemy.orm.attributes import InstrumentedAttribute +~~from sqlalchemy.orm.exc import UnmappedInstanceError +from sqlalchemy.orm.properties import ColumnProperty, RelationshipProperty +from sqlalchemy.orm.query import _ColumnEntity +from sqlalchemy.orm.session import object_session +from sqlalchemy.orm.util import AliasedInsp + +from ..utils import is_sequence + + +def get_class_by_table(base, table, data=None): + found_classes = set( + c for c in base._decl_class_registry.values() + if hasattr(c, '__table__') and c.__table__ is table + ) + if len(found_classes) > 1: + if not data: + raise ValueError( + "Multiple declarative classes found for table '{0}'. " + "Please provide data parameter for this function to be able " + "to determine polymorphic scenarios.".format( + table.name + ) + ) + else: + for cls in found_classes: + + +## ... source file abbreviated to get to UnmappedInstanceError examples ... + + + mappers = [ + mapper for mapper in mapperlib._mapper_registry + if mixed in mapper.tables + ] + if len(mappers) > 1: + raise ValueError( + "Multiple mappers found for table '%s'." % mixed.name + ) + elif not mappers: + raise ValueError( + "Could not get mapper for table '%s'." % mixed.name + ) + else: + return mappers[0] + if not isclass(mixed): + mixed = type(mixed) + return sa.inspect(mixed) + + +def get_bind(obj): + if hasattr(obj, 'bind'): + conn = obj.bind + else: + try: + conn = object_session(obj).bind +~~ except UnmappedInstanceError: + conn = obj + + if not hasattr(conn, 'execute'): + raise TypeError( + 'This method accepts only Session, Engine, Connection and ' + 'declarative model objects.' + ) + return conn + + +def get_primary_keys(mixed): + return OrderedDict( + ( + (key, column) for key, column in get_columns(mixed).items() + if column.primary_key + ) + ) + + +def get_tables(mixed): + if isinstance(mixed, sa.Table): + return [mixed] + elif isinstance(mixed, sa.Column): + return [mixed.table] + + +## ... source file continues with no further UnmappedInstanceError examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-interfaces-mapperproperty.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-interfaces-mapperproperty.markdown new file mode 100644 index 000000000..fdae687dd --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-interfaces-mapperproperty.markdown @@ -0,0 +1,124 @@ +title: sqlalchemy.orm.interfaces MapperProperty Example Code +category: page +slug: sqlalchemy-orm-interfaces-mapperproperty-examples +sortorder: 500031083 +toc: False +sidebartitle: sqlalchemy.orm.interfaces MapperProperty +meta: Example code for understanding how to use the MapperProperty class from the sqlalchemy.orm.interfaces module of the SQLAlchemy project. + + +`MapperProperty` is a class within the `sqlalchemy.orm.interfaces` module of the SQLAlchemy project. + +PropComparator +is another callable from the `sqlalchemy.orm.interfaces` package with code examples. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / generic.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./generic.py) + +```python +# generic.py +from collections.abc import Iterable + +import six +import sqlalchemy as sa +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import attributes, class_mapper, ColumnProperty +~~from sqlalchemy.orm.interfaces import MapperProperty, PropComparator +from sqlalchemy.orm.session import _state_session +from sqlalchemy.util import set_creation_order + +from .exceptions import ImproperlyConfigured +from .functions import identity + + +class GenericAttributeImpl(attributes.ScalarAttributeImpl): + def get(self, state, dict_, passive=attributes.PASSIVE_OFF): + if self.key in dict_: + return dict_[self.key] + + session = _state_session(state) + if session is None: + return None + + discriminator = self.get_state_discriminator(state) + target_class = state.class_._decl_class_registry.get(discriminator) + + if target_class is None: + return None + + id = self.get_state_id(state) + + + +## ... source file abbreviated to get to MapperProperty examples ... + + + + def set(self, state, dict_, initiator, + passive=attributes.PASSIVE_OFF, + check_old=None, + pop=False): + + dict_[self.key] = initiator + + if initiator is None: + for id in self.parent_token.id: + dict_[id.key] = None + dict_[self.parent_token.discriminator.key] = None + else: + class_ = type(initiator) + mapper = class_mapper(class_) + + pk = mapper.identity_key_from_instance(initiator)[1] + + discriminator = six.text_type(class_.__name__) + + for index, id in enumerate(self.parent_token.id): + dict_[id.key] = pk[index] + dict_[self.parent_token.discriminator.key] = discriminator + + +~~class GenericRelationshipProperty(MapperProperty): + + def __init__(self, discriminator, id, doc=None): + super(GenericRelationshipProperty, self).__init__() + self._discriminator_col = discriminator + self._id_cols = id + self._id = None + self._discriminator = None + self.doc = doc + + set_creation_order(self) + + def _column_to_property(self, column): + if isinstance(column, hybrid_property): + attr_key = column.__name__ + for key, attr in self.parent.all_orm_descriptors.items(): + if key == attr_key: + return attr + else: + for key, attr in self.parent.attrs.items(): + if isinstance(attr, ColumnProperty): + if attr.columns[0].name == column.name: + return attr + + def init(self): + + +## ... source file continues with no further MapperProperty examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-interfaces-propcomparator.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-interfaces-propcomparator.markdown new file mode 100644 index 000000000..22c3e587f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-interfaces-propcomparator.markdown @@ -0,0 +1,124 @@ +title: sqlalchemy.orm.interfaces PropComparator Example Code +category: page +slug: sqlalchemy-orm-interfaces-propcomparator-examples +sortorder: 500031084 +toc: False +sidebartitle: sqlalchemy.orm.interfaces PropComparator +meta: Example code for understanding how to use the PropComparator class from the sqlalchemy.orm.interfaces module of the SQLAlchemy project. + + +`PropComparator` is a class within the `sqlalchemy.orm.interfaces` module of the SQLAlchemy project. + +MapperProperty +is another callable from the `sqlalchemy.orm.interfaces` package with code examples. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / generic.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./generic.py) + +```python +# generic.py +from collections.abc import Iterable + +import six +import sqlalchemy as sa +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import attributes, class_mapper, ColumnProperty +~~from sqlalchemy.orm.interfaces import MapperProperty, PropComparator +from sqlalchemy.orm.session import _state_session +from sqlalchemy.util import set_creation_order + +from .exceptions import ImproperlyConfigured +from .functions import identity + + +class GenericAttributeImpl(attributes.ScalarAttributeImpl): + def get(self, state, dict_, passive=attributes.PASSIVE_OFF): + if self.key in dict_: + return dict_[self.key] + + session = _state_session(state) + if session is None: + return None + + discriminator = self.get_state_discriminator(state) + target_class = state.class_._decl_class_registry.get(discriminator) + + if target_class is None: + return None + + id = self.get_state_id(state) + + + +## ... source file abbreviated to get to PropComparator examples ... + + + return attr + + def init(self): + def convert_strings(column): + if isinstance(column, six.string_types): + return self.parent.columns[column] + return column + + self._discriminator_col = convert_strings(self._discriminator_col) + self._id_cols = convert_strings(self._id_cols) + + if isinstance(self._id_cols, Iterable): + self._id_cols = list(map(convert_strings, self._id_cols)) + else: + self._id_cols = [self._id_cols] + + self.discriminator = self._column_to_property(self._discriminator_col) + + if self.discriminator is None: + raise ImproperlyConfigured( + 'Could not find discriminator descriptor.' + ) + + self.id = list(map(self._column_to_property, self._id_cols)) + +~~ class Comparator(PropComparator): + def __init__(self, prop, parentmapper): + self.property = prop + self._parententity = parentmapper + + def __eq__(self, other): + discriminator = six.text_type(type(other).__name__) + q = self.property._discriminator_col == discriminator + other_id = identity(other) + for index, id in enumerate(self.property._id_cols): + q &= id == other_id[index] + return q + + def __ne__(self, other): + return -(self == other) + + def is_type(self, other): + mapper = sa.inspect(other) + class_names = [six.text_type(other.__name__)] + class_names.extend([ + six.text_type(submapper.class_.__name__) + for submapper in mapper._inheriting_mappers + ]) + + return self.property._discriminator_col.in_(class_names) + + +## ... source file continues with no further PropComparator examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-interfaces.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-interfaces.markdown new file mode 100644 index 000000000..7d4e310ce --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-interfaces.markdown @@ -0,0 +1,134 @@ +title: sqlalchemy.orm interfaces Example Code +category: page +slug: sqlalchemy-orm-interfaces-examples +sortorder: 500031067 +toc: False +sidebartitle: sqlalchemy.orm interfaces +meta: Python example code that shows how to use the interfaces callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`interfaces` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / converter.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./converter.py) + +```python +# converter.py +from enum import EnumMeta + +from singledispatch import singledispatch +from sqlalchemy import types +from sqlalchemy.dialects import postgresql +~~from sqlalchemy.orm import interfaces, strategies + +from graphene import (ID, Boolean, Dynamic, Enum, Field, Float, Int, List, + String) +from graphene.types.json import JSONString + +from .batching import get_batch_resolver +from .enums import enum_for_sa_enum +from .fields import (BatchSQLAlchemyConnectionField, + default_connection_field_factory) +from .registry import get_global_registry +from .resolvers import get_attr_resolver, get_custom_resolver + +try: + from sqlalchemy_utils import ChoiceType, JSONType, ScalarListType, TSVectorType +except ImportError: + ChoiceType = JSONType = ScalarListType = TSVectorType = object + + +is_selectin_available = getattr(strategies, 'SelectInLoader', None) + + +def get_column_doc(column): + return getattr(column, "doc", None) + + +def is_column_nullable(column): + return bool(getattr(column, "nullable", True)) + + +def convert_sqlalchemy_relationship(relationship_prop, obj_type, connection_field_factory, batching, + orm_field_name, **field_kwargs): + def dynamic_type(): + direction = relationship_prop.direction + child_type = obj_type._meta.registry.get_type_for_model(relationship_prop.mapper.entity) + batching_ = batching if is_selectin_available else False + + if not child_type: + return None + +~~ if direction == interfaces.MANYTOONE or not relationship_prop.uselist: + return _convert_o2o_or_m2o_relationship(relationship_prop, obj_type, batching_, orm_field_name, + **field_kwargs) + +~~ if direction in (interfaces.ONETOMANY, interfaces.MANYTOMANY): + return _convert_o2m_or_m2m_relationship(relationship_prop, obj_type, batching_, + connection_field_factory, **field_kwargs) + + return Dynamic(dynamic_type) + + +def _convert_o2o_or_m2o_relationship(relationship_prop, obj_type, batching, orm_field_name, **field_kwargs): + child_type = obj_type._meta.registry.get_type_for_model(relationship_prop.mapper.entity) + + resolver = get_custom_resolver(obj_type, orm_field_name) + if resolver is None: + resolver = get_batch_resolver(relationship_prop) if batching else \ + get_attr_resolver(obj_type, relationship_prop.key) + + return Field(child_type, resolver=resolver, **field_kwargs) + + +def _convert_o2m_or_m2m_relationship(relationship_prop, obj_type, batching, connection_field_factory, **field_kwargs): + child_type = obj_type._meta.registry.get_type_for_model(relationship_prop.mapper.entity) + + if not child_type._meta.connection: + return Field(List(child_type), **field_kwargs) + + if connection_field_factory is None: + + +## ... source file continues with no further interfaces examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-load.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-load.markdown new file mode 100644 index 000000000..658b1699e --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-load.markdown @@ -0,0 +1,113 @@ +title: sqlalchemy.orm Load Example Code +category: page +slug: sqlalchemy-orm-load-examples +sortorder: 500031056 +toc: False +sidebartitle: sqlalchemy.orm Load +meta: Example code for understanding how to use the Load class from the sqlalchemy.orm module of the SQLAlchemy project. + + +`Load` is a class within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from SQLAlchemy filters +[SQLAlchemy filters](https://github.com/juliotrigo/sqlalchemy-filters) + provides filtering, sorting and pagination for [SQLAlchemy](/sqlalchemy.html) + query objects, which is particularly useful when building + [web APIs](/application-programming-interfaces.html). SQLAlchemy filters + is open sourced under the + [Apache License version 2.0](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/LICENSE). + +[**SQLAlchemy filters / sqlalchemy_filters / loads.py**](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/sqlalchemy_filters/./loads.py) + +```python +# loads.py +~~from sqlalchemy.orm import Load + +from .exceptions import BadLoadFormat +from .models import Field, auto_join, get_model_from_spec, get_default_model + + +class LoadOnly(object): + + def __init__(self, load_spec): + self.load_spec = load_spec + + try: + field_names = load_spec['fields'] + except KeyError: + raise BadLoadFormat('`fields` is a mandatory attribute.') + except TypeError: + raise BadLoadFormat( + 'Load spec `{}` should be a dictionary.'.format(load_spec) + ) + + self.field_names = field_names + + def get_named_models(self): + if "model" in self.load_spec: + return {self.load_spec['model']} + return set() + + def format_for_sqlalchemy(self, query, default_model): + load_spec = self.load_spec + field_names = self.field_names + + model = get_model_from_spec(load_spec, query, default_model) + fields = [Field(model, field_name) for field_name in field_names] + +~~ return Load(model).load_only( + *[field.get_sqlalchemy_field() for field in fields] + ) + + +def get_named_models(loads): + models = set() + for load in loads: + models.update(load.get_named_models()) + return models + + +def apply_loads(query, load_spec): + if ( + isinstance(load_spec, list) and + all(map(lambda item: isinstance(item, str), load_spec)) + ): + load_spec = {'fields': load_spec} + + if isinstance(load_spec, dict): + load_spec = [load_spec] + + loads = [LoadOnly(item) for item in load_spec] + + default_model = get_default_model(query) + + +## ... source file continues with no further Load examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-mapper-mapper.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-mapper-mapper.markdown new file mode 100644 index 000000000..6da851f1f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-mapper-mapper.markdown @@ -0,0 +1,58 @@ +title: sqlalchemy.orm.mapper Mapper Example Code +category: page +slug: sqlalchemy-orm-mapper-mapper-examples +sortorder: 500031085 +toc: False +sidebartitle: sqlalchemy.orm.mapper Mapper +meta: Example code for understanding how to use the Mapper class from the sqlalchemy.orm.mapper module of the SQLAlchemy project. + + +`Mapper` is a class within the `sqlalchemy.orm.mapper` module of the SQLAlchemy project. + + + +## Example 1 from SQLAlchemy filters +[SQLAlchemy filters](https://github.com/juliotrigo/sqlalchemy-filters) + provides filtering, sorting and pagination for [SQLAlchemy](/sqlalchemy.html) + query objects, which is particularly useful when building + [web APIs](/application-programming-interfaces.html). SQLAlchemy filters + is open sourced under the + [Apache License version 2.0](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/LICENSE). + +[**SQLAlchemy filters / sqlalchemy_filters / models.py**](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/sqlalchemy_filters/./models.py) + +```python +# models.py +from sqlalchemy.exc import InvalidRequestError +from sqlalchemy.inspection import inspect +~~from sqlalchemy.orm.mapper import Mapper +from sqlalchemy.util import symbol +import types + +from .exceptions import BadQuery, FieldNotFound, BadSpec + + +class Field(object): + + def __init__(self, model, field_name): + self.model = model + self.field_name = field_name + + def get_sqlalchemy_field(self): + if self.field_name not in self._get_valid_field_names(): + raise FieldNotFound( + 'Model {} has no column `{}`.'.format( + self.model, self.field_name + ) + ) + sqlalchemy_field = getattr(self.model, self.field_name) + + if isinstance(sqlalchemy_field, types.MethodType): + sqlalchemy_field = sqlalchemy_field() + + + +## ... source file continues with no further Mapper examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-mapper.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-mapper.markdown new file mode 100644 index 000000000..6b04b11cd --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-mapper.markdown @@ -0,0 +1,312 @@ +title: sqlalchemy.orm mapper Example Code +category: page +slug: sqlalchemy-orm-mapper-examples +sortorder: 500031068 +toc: False +sidebartitle: sqlalchemy.orm mapper +meta: Python example code that shows how to use the mapper callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`mapper` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / orm.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/orm.py) + +```python +# orm.py +from collections import OrderedDict +from functools import partial +from inspect import isclass +from operator import attrgetter + +import six +import sqlalchemy as sa +from sqlalchemy.engine.interfaces import Dialect +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import mapperlib +from sqlalchemy.orm.attributes import InstrumentedAttribute +from sqlalchemy.orm.exc import UnmappedInstanceError +from sqlalchemy.orm.properties import ColumnProperty, RelationshipProperty +from sqlalchemy.orm.query import _ColumnEntity +from sqlalchemy.orm.session import object_session +from sqlalchemy.orm.util import AliasedInsp + +from ..utils import is_sequence + + +def get_class_by_table(base, table, data=None): + found_classes = set( + c for c in base._decl_class_registry.values() + if hasattr(c, '__table__') and c.__table__ is table + ) + if len(found_classes) > 1: + if not data: + raise ValueError( + "Multiple declarative classes found for table '{0}'. " + "Please provide data parameter for this function to be able " + "to determine polymorphic scenarios.".format( + table.name + ) + ) + else: + for cls in found_classes: + mapper = sa.inspect(cls) +~~ polymorphic_on = mapper.polymorphic_on.name + if polymorphic_on in data: +~~ if data[polymorphic_on] == mapper.polymorphic_identity: + return cls + raise ValueError( + "Multiple declarative classes found for table '{0}'. Given " + "data row does not match any polymorphic identity of the " + "found classes.".format( + table.name + ) + ) + elif found_classes: + return found_classes.pop() + return None + + +def get_type(expr): + if hasattr(expr, 'type'): + return expr.type + elif isinstance(expr, InstrumentedAttribute): + expr = expr.property + + if isinstance(expr, ColumnProperty): + return expr.columns[0].type + elif isinstance(expr, RelationshipProperty): + return expr.mapper.class_ + raise TypeError("Couldn't inspect type.") + + +def cast_if(expression, type_): + try: + expr_type = get_type(expression) + except TypeError: + expr_type = expression + check_type = type_().python_type + else: + check_type = type_ + + return ( + sa.cast(expression, type_) + if not isinstance(expr_type, check_type) + else expression + ) + + +def get_column_key(model, column): + mapper = sa.inspect(model) + try: +~~ return mapper.get_property_by_column(column).key + except sa.orm.exc.UnmappedColumnError: +~~ for key, c in mapper.columns.items(): + if c.name == column.name and c.table is column.table: + return key + raise sa.orm.exc.UnmappedColumnError( + 'No column %s is configured on mapper %s...' % + (column, mapper) + ) + + +def get_mapper(mixed): + if isinstance(mixed, sa.orm.query._MapperEntity): + mixed = mixed.expr + elif isinstance(mixed, sa.Column): + mixed = mixed.table + elif isinstance(mixed, sa.orm.query._ColumnEntity): + mixed = mixed.expr + + if isinstance(mixed, sa.orm.Mapper): + return mixed + if isinstance(mixed, sa.orm.util.AliasedClass): + return sa.inspect(mixed).mapper + if isinstance(mixed, sa.sql.selectable.Alias): + mixed = mixed.element + if isinstance(mixed, AliasedInsp): + return mixed.mapper + if isinstance(mixed, sa.orm.attributes.InstrumentedAttribute): + mixed = mixed.class_ + if isinstance(mixed, sa.Table): + mappers = [ + mapper for mapper in mapperlib._mapper_registry +~~ if mixed in mapper.tables + ] + if len(mappers) > 1: + raise ValueError( + "Multiple mappers found for table '%s'." % mixed.name + ) + elif not mappers: + raise ValueError( + "Could not get mapper for table '%s'." % mixed.name + ) + else: + return mappers[0] + if not isclass(mixed): + mixed = type(mixed) + return sa.inspect(mixed) + + +def get_bind(obj): + if hasattr(obj, 'bind'): + conn = obj.bind + else: + try: + conn = object_session(obj).bind + except UnmappedInstanceError: + conn = obj + + +## ... source file abbreviated to get to mapper examples ... + + +def get_primary_keys(mixed): + return OrderedDict( + ( + (key, column) for key, column in get_columns(mixed).items() + if column.primary_key + ) + ) + + +def get_tables(mixed): + if isinstance(mixed, sa.Table): + return [mixed] + elif isinstance(mixed, sa.Column): + return [mixed.table] + elif isinstance(mixed, sa.orm.attributes.InstrumentedAttribute): + return mixed.parent.tables + elif isinstance(mixed, sa.orm.query._ColumnEntity): + mixed = mixed.expr + + mapper = get_mapper(mixed) + + polymorphic_mappers = get_polymorphic_mappers(mapper) + if polymorphic_mappers: + tables = sum((m.tables for m in polymorphic_mappers), []) + else: +~~ tables = mapper.tables + return tables + + +def get_columns(mixed): + if isinstance(mixed, sa.sql.selectable.Selectable): + return mixed.c + if isinstance(mixed, sa.orm.util.AliasedClass): + return sa.inspect(mixed).mapper.columns + if isinstance(mixed, sa.orm.Mapper): + return mixed.columns + if isinstance(mixed, InstrumentedAttribute): + return mixed.property.columns + if isinstance(mixed, ColumnProperty): + return mixed.columns + if isinstance(mixed, sa.Column): + return [mixed] + if not isclass(mixed): + mixed = mixed.__class__ + return sa.inspect(mixed).columns + + +def table_name(obj): + class_ = getattr(obj, 'class_', obj) + + + +## ... source file abbreviated to get to mapper examples ... + + + return attr + else: + entity = get_query_entity_by_alias(query, entity) + if entity: + descriptor = get_descriptor(entity, attr) + if ( + hasattr(descriptor, 'property') and + isinstance(descriptor.property, sa.orm.RelationshipProperty) + ): + return + return descriptor + + +def get_descriptor(entity, attr): + mapper = sa.inspect(entity) + + for key, descriptor in get_all_descriptors(mapper).items(): + if attr == key: + prop = ( + descriptor.property + if hasattr(descriptor, 'property') + else None + ) + if isinstance(prop, ColumnProperty): + if isinstance(entity, sa.orm.util.AliasedClass): +~~ for c in mapper.selectable.c: + if c.key == attr: + return c + else: + return getattr(prop.parent.class_, attr) + else: + + if isinstance(entity, sa.orm.util.AliasedClass): + return getattr(entity, attr) + try: + return getattr(mapper.class_, attr) + except AttributeError: + pass + + +def get_all_descriptors(expr): + if isinstance(expr, sa.sql.selectable.Selectable): + return expr.c + insp = sa.inspect(expr) + try: + polymorphic_mappers = get_polymorphic_mappers(insp) + except sa.exc.NoInspectionAvailable: + return get_mapper(expr).all_orm_descriptors + else: + attrs = dict(get_mapper(expr).all_orm_descriptors) + + +## ... source file continues with no further mapper examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-mapperlib.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-mapperlib.markdown new file mode 100644 index 000000000..7b567fffa --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-mapperlib.markdown @@ -0,0 +1,149 @@ +title: sqlalchemy.orm mapperlib Example Code +category: page +slug: sqlalchemy-orm-mapperlib-examples +sortorder: 500031069 +toc: False +sidebartitle: sqlalchemy.orm mapperlib +meta: Python example code that shows how to use the mapperlib callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`mapperlib` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / orm.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/orm.py) + +```python +# orm.py +from collections import OrderedDict +from functools import partial +from inspect import isclass +from operator import attrgetter + +import six +import sqlalchemy as sa +from sqlalchemy.engine.interfaces import Dialect +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import mapperlib +from sqlalchemy.orm.attributes import InstrumentedAttribute +from sqlalchemy.orm.exc import UnmappedInstanceError +from sqlalchemy.orm.properties import ColumnProperty, RelationshipProperty +from sqlalchemy.orm.query import _ColumnEntity +from sqlalchemy.orm.session import object_session +from sqlalchemy.orm.util import AliasedInsp + +from ..utils import is_sequence + + +def get_class_by_table(base, table, data=None): + found_classes = set( + c for c in base._decl_class_registry.values() + if hasattr(c, '__table__') and c.__table__ is table + ) + if len(found_classes) > 1: + if not data: + raise ValueError( + "Multiple declarative classes found for table '{0}'. " + "Please provide data parameter for this function to be able " + "to determine polymorphic scenarios.".format( + table.name + ) + ) + + +## ... source file abbreviated to get to mapperlib examples ... + + + 'No column %s is configured on mapper %s...' % + (column, mapper) + ) + + +def get_mapper(mixed): + if isinstance(mixed, sa.orm.query._MapperEntity): + mixed = mixed.expr + elif isinstance(mixed, sa.Column): + mixed = mixed.table + elif isinstance(mixed, sa.orm.query._ColumnEntity): + mixed = mixed.expr + + if isinstance(mixed, sa.orm.Mapper): + return mixed + if isinstance(mixed, sa.orm.util.AliasedClass): + return sa.inspect(mixed).mapper + if isinstance(mixed, sa.sql.selectable.Alias): + mixed = mixed.element + if isinstance(mixed, AliasedInsp): + return mixed.mapper + if isinstance(mixed, sa.orm.attributes.InstrumentedAttribute): + mixed = mixed.class_ + if isinstance(mixed, sa.Table): + mappers = [ +~~ mapper for mapper in mapperlib._mapper_registry + if mixed in mapper.tables + ] + if len(mappers) > 1: + raise ValueError( + "Multiple mappers found for table '%s'." % mixed.name + ) + elif not mappers: + raise ValueError( + "Could not get mapper for table '%s'." % mixed.name + ) + else: + return mappers[0] + if not isclass(mixed): + mixed = type(mixed) + return sa.inspect(mixed) + + +def get_bind(obj): + if hasattr(obj, 'bind'): + conn = obj.bind + else: + try: + conn = object_session(obj).bind + except UnmappedInstanceError: + + +## ... source file continues with no further mapperlib examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-object-mapper.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-object-mapper.markdown new file mode 100644 index 000000000..198598aa2 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-object-mapper.markdown @@ -0,0 +1,121 @@ +title: sqlalchemy.orm object_mapper Example Code +category: page +slug: sqlalchemy-orm-object-mapper-examples +sortorder: 500031070 +toc: False +sidebartitle: sqlalchemy.orm object_mapper +meta: Python example code that shows how to use the object_mapper callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`object_mapper` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / utils.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./utils.py) + +```python +# utils.py +import re +import warnings + +from sqlalchemy.exc import ArgumentError +~~from sqlalchemy.orm import class_mapper, object_mapper +from sqlalchemy.orm.exc import UnmappedClassError, UnmappedInstanceError + + +def get_session(context): + return context.get("session") + + +def get_query(model, context): + query = getattr(model, "query", None) + if not query: + session = get_session(context) + if not session: + raise Exception( + "A query in the model Base or a session in the schema is required for querying.\n" + "Read more http://docs.graphene-python.org/projects/sqlalchemy/en/latest/tips/#querying" + ) + query = session.query(model) + return query + + +def is_mapped_class(cls): + try: + class_mapper(cls) + except (ArgumentError, UnmappedClassError): + return False + else: + return True + + +def is_mapped_instance(cls): + try: +~~ object_mapper(cls) + except (ArgumentError, UnmappedInstanceError): + return False + else: + return True + + +def to_type_name(name): + return "".join(part[:1].upper() + part[1:] for part in name.split("_")) + + +_re_enum_value_name_1 = re.compile("(.)([A-Z][a-z]+)") +_re_enum_value_name_2 = re.compile("([a-z0-9])([A-Z])") + + +def to_enum_value_name(name): + return _re_enum_value_name_2.sub( + r"\1_\2", _re_enum_value_name_1.sub(r"\1_\2", name) + ).upper() + + +class EnumValue(str): + + def __new__(cls, s, value): + return super(EnumValue, cls).__new__(cls, s) + + +## ... source file continues with no further object_mapper examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-object-session.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-object-session.markdown new file mode 100644 index 000000000..39fe0cb34 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-object-session.markdown @@ -0,0 +1,175 @@ +title: sqlalchemy.orm object_session Example Code +category: page +slug: sqlalchemy-orm-object-session-examples +sortorder: 500031071 +toc: False +sidebartitle: sqlalchemy.orm object_session +meta: Python example code that shows how to use the object_session callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`object_session` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / foreign_keys.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/foreign_keys.py) + +```python +# foreign_keys.py +from collections import defaultdict +from itertools import groupby + +import sqlalchemy as sa +from sqlalchemy.exc import NoInspectionAvailable +~~from sqlalchemy.orm import object_session +from sqlalchemy.schema import ForeignKeyConstraint, MetaData, Table + +from ..query_chain import QueryChain +from .database import has_index +from .orm import get_column_key, get_mapper, get_tables + + +def get_foreign_key_values(fk, obj): + return dict( + ( + fk.constraint.columns.values()[index].key, + getattr(obj, element.column.key) + ) + for + index, element + in + enumerate(fk.constraint.elements) + ) + + +def group_foreign_keys(foreign_keys): + foreign_keys = sorted( + foreign_keys, key=lambda key: key.constraint.table.name + ) + return groupby(foreign_keys, lambda key: key.constraint.table) + + +def get_referencing_foreign_keys(mixed): + if isinstance(mixed, sa.Table): + tables = [mixed] + else: + tables = get_tables(mixed) + + referencing_foreign_keys = set() + + for table in mixed.metadata.tables.values(): + if table not in tables: + for constraint in table.constraints: + if isinstance(constraint, sa.sql.schema.ForeignKeyConstraint): + for fk in constraint.elements: + if any(fk.references(t) for t in tables): + referencing_foreign_keys.add(fk) + return referencing_foreign_keys + + +def merge_references(from_, to, foreign_keys=None): + if from_.__tablename__ != to.__tablename__: + raise TypeError('The tables of given arguments do not match.') + +~~ session = object_session(from_) + foreign_keys = get_referencing_foreign_keys(from_) + + for fk in foreign_keys: + old_values = get_foreign_key_values(fk, from_) + new_values = get_foreign_key_values(fk, to) + criteria = ( + getattr(fk.constraint.table.c, key) == value + for key, value in old_values.items() + ) + try: + mapper = get_mapper(fk.constraint.table) + except ValueError: + query = ( + fk.constraint.table + .update() + .where(sa.and_(*criteria)) + .values(new_values) + ) + session.execute(query) + else: + ( + session.query(mapper.class_) + .filter_by(**old_values) + .update( + new_values, + 'evaluate' + ) + ) + + +def dependent_objects(obj, foreign_keys=None): + if foreign_keys is None: + foreign_keys = get_referencing_foreign_keys(obj) + +~~ session = object_session(obj) + + chain = QueryChain([]) + classes = obj.__class__._decl_class_registry + + for table, keys in group_foreign_keys(foreign_keys): + keys = list(keys) + for class_ in classes.values(): + try: + mapper = sa.inspect(class_) + except NoInspectionAvailable: + continue + parent_mapper = mapper.inherits + if ( + table in mapper.tables and + not (parent_mapper and table in parent_mapper.tables) + ): + query = session.query(class_).filter( + sa.or_(*_get_criteria(keys, class_, obj)) + ) + chain.queries.append(query) + return chain + + +def _get_criteria(keys, class_, obj): + + +## ... source file continues with no further object_session examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-properties-columnproperty.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-properties-columnproperty.markdown new file mode 100644 index 000000000..5023c939e --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-properties-columnproperty.markdown @@ -0,0 +1,397 @@ +title: sqlalchemy.orm.properties ColumnProperty Example Code +category: page +slug: sqlalchemy-orm-properties-columnproperty-examples +sortorder: 500031086 +toc: False +sidebartitle: sqlalchemy.orm.properties ColumnProperty +meta: Example code for understanding how to use the ColumnProperty class from the sqlalchemy.orm.properties module of the SQLAlchemy project. + + +`ColumnProperty` is a class within the `sqlalchemy.orm.properties` module of the SQLAlchemy project. + +RelationshipProperty +is another callable from the `sqlalchemy.orm.properties` package with code examples. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / orm.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/orm.py) + +```python +# orm.py +from collections import OrderedDict +from functools import partial +from inspect import isclass +from operator import attrgetter + +import six +import sqlalchemy as sa +from sqlalchemy.engine.interfaces import Dialect +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import mapperlib +from sqlalchemy.orm.attributes import InstrumentedAttribute +from sqlalchemy.orm.exc import UnmappedInstanceError +~~from sqlalchemy.orm.properties import ColumnProperty, RelationshipProperty +from sqlalchemy.orm.query import _ColumnEntity +from sqlalchemy.orm.session import object_session +from sqlalchemy.orm.util import AliasedInsp + +from ..utils import is_sequence + + +def get_class_by_table(base, table, data=None): + found_classes = set( + c for c in base._decl_class_registry.values() + if hasattr(c, '__table__') and c.__table__ is table + ) + if len(found_classes) > 1: + if not data: + raise ValueError( + "Multiple declarative classes found for table '{0}'. " + "Please provide data parameter for this function to be able " + "to determine polymorphic scenarios.".format( + table.name + ) + ) + else: + for cls in found_classes: + mapper = sa.inspect(cls) + polymorphic_on = mapper.polymorphic_on.name + if polymorphic_on in data: + if data[polymorphic_on] == mapper.polymorphic_identity: + return cls + raise ValueError( + "Multiple declarative classes found for table '{0}'. Given " + "data row does not match any polymorphic identity of the " + "found classes.".format( + table.name + ) + ) + elif found_classes: + return found_classes.pop() + return None + + +def get_type(expr): + if hasattr(expr, 'type'): + return expr.type + elif isinstance(expr, InstrumentedAttribute): + expr = expr.property + +~~ if isinstance(expr, ColumnProperty): + return expr.columns[0].type + elif isinstance(expr, RelationshipProperty): + return expr.mapper.class_ + raise TypeError("Couldn't inspect type.") + + +def cast_if(expression, type_): + try: + expr_type = get_type(expression) + except TypeError: + expr_type = expression + check_type = type_().python_type + else: + check_type = type_ + + return ( + sa.cast(expression, type_) + if not isinstance(expr_type, check_type) + else expression + ) + + +def get_column_key(model, column): + mapper = sa.inspect(model) + + +## ... source file abbreviated to get to ColumnProperty examples ... + + + return [mixed.table] + elif isinstance(mixed, sa.orm.attributes.InstrumentedAttribute): + return mixed.parent.tables + elif isinstance(mixed, sa.orm.query._ColumnEntity): + mixed = mixed.expr + + mapper = get_mapper(mixed) + + polymorphic_mappers = get_polymorphic_mappers(mapper) + if polymorphic_mappers: + tables = sum((m.tables for m in polymorphic_mappers), []) + else: + tables = mapper.tables + return tables + + +def get_columns(mixed): + if isinstance(mixed, sa.sql.selectable.Selectable): + return mixed.c + if isinstance(mixed, sa.orm.util.AliasedClass): + return sa.inspect(mixed).mapper.columns + if isinstance(mixed, sa.orm.Mapper): + return mixed.columns + if isinstance(mixed, InstrumentedAttribute): + return mixed.property.columns +~~ if isinstance(mixed, ColumnProperty): + return mixed.columns + if isinstance(mixed, sa.Column): + return [mixed] + if not isclass(mixed): + mixed = mixed.__class__ + return sa.inspect(mixed).columns + + +def table_name(obj): + class_ = getattr(obj, 'class_', obj) + + try: + return class_.__tablename__ + except AttributeError: + pass + + try: + return class_.__table__.name + except AttributeError: + pass + + +def getattrs(obj, attrs): + return map(partial(getattr, obj), attrs) + + +## ... source file abbreviated to get to ColumnProperty examples ... + + +def get_query_descriptor(query, entity, attr): + if attr in query_labels(query): + return attr + else: + entity = get_query_entity_by_alias(query, entity) + if entity: + descriptor = get_descriptor(entity, attr) + if ( + hasattr(descriptor, 'property') and + isinstance(descriptor.property, sa.orm.RelationshipProperty) + ): + return + return descriptor + + +def get_descriptor(entity, attr): + mapper = sa.inspect(entity) + + for key, descriptor in get_all_descriptors(mapper).items(): + if attr == key: + prop = ( + descriptor.property + if hasattr(descriptor, 'property') + else None + ) +~~ if isinstance(prop, ColumnProperty): + if isinstance(entity, sa.orm.util.AliasedClass): + for c in mapper.selectable.c: + if c.key == attr: + return c + else: + return getattr(prop.parent.class_, attr) + else: + + if isinstance(entity, sa.orm.util.AliasedClass): + return getattr(entity, attr) + try: + return getattr(mapper.class_, attr) + except AttributeError: + pass + + +def get_all_descriptors(expr): + if isinstance(expr, sa.sql.selectable.Selectable): + return expr.c + insp = sa.inspect(expr) + try: + polymorphic_mappers = get_polymorphic_mappers(insp) + except sa.exc.NoInspectionAvailable: + return get_mapper(expr).all_orm_descriptors + + +## ... source file continues with no further ColumnProperty examples... + +``` + + +## Example 2 from WTForms-Alchemy +[wtforms-alchemy](git@github.com:kvesteri/wtforms-alchemy.git) +([documentation](https://wtforms-alchemy.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/WTForms-Alchemy/)) +is a [WTForms](https://wtforms.readthedocs.io/en/2.2.1/) extension toolkit +for easier creation of [SQLAlchemy](/sqlalchemy.html) model based forms. +While this project primarily focuses on proper form handling, it also +has many good examples of how to use various parts of SQLAlchemy in +its code base. The project is provided as open source under the +[MIT license](https://github.com/kvesteri/wtforms-alchemy/blob/master/LICENSE). + +[**WTForms-Alchemy / wtforms_alchemy / generator.py**](https://github.com/kvesteri/wtforms-alchemy/blob/master/wtforms_alchemy/./generator.py) + +```python +# generator.py +import inspect +from collections import OrderedDict +from decimal import Decimal +from enum import Enum + +import six +import sqlalchemy as sa +~~from sqlalchemy.orm.properties import ColumnProperty +from sqlalchemy_utils import types +from wtforms import ( + BooleanField, + Field, + FloatField, + PasswordField, + TextAreaField +) +from wtforms.widgets import CheckboxInput, TextArea +from wtforms_components import ( + ColorField, + DateField, + DateIntervalField, + DateTimeField, + DateTimeIntervalField, + DateTimeLocalField, + DecimalField, + DecimalIntervalField, + EmailField, + IntegerField, + IntIntervalField, + SelectField, + StringField, + TimeField + + +## ... source file abbreviated to get to ColumnProperty examples ... + + + + WIDGET_MAP = OrderedDict(( + (BooleanField, CheckboxInput), + (ColorField, ColorInput), + (DateField, DateInput), + (DateTimeField, DateTimeInput), + (DateTimeLocalField, DateTimeLocalInput), + (DecimalField, NumberInput), + (EmailField, EmailInput), + (FloatField, NumberInput), + (IntegerField, NumberInput), + (TextAreaField, TextArea), + (TimeField, TimeInput), + (StringField, TextInput) + )) + + def __init__(self, form_class): + self.form_class = form_class + self.model_class = self.form_class.Meta.model + self.meta = self.form_class.Meta + self.TYPE_MAP.update(self.form_class.Meta.type_map) + + def create_form(self, form): + attrs = OrderedDict() + for key, property_ in sa.inspect(self.model_class).attrs.items(): +~~ if not isinstance(property_, ColumnProperty): + continue + if self.skip_column_property(property_): + continue + attrs[key] = property_ + + for attr in translated_attributes(self.model_class): + attrs[attr.key] = attr.property + + return self.create_fields(form, self.filter_attributes(attrs)) + + def filter_attributes(self, attrs): + if self.meta.only: + attrs = OrderedDict([ + (key, prop) + for key, prop in map(self.validate_attribute, self.meta.only) + if key + ]) + else: + if self.meta.include: + attrs.update([ + (key, prop) + for key, prop + in map(self.validate_attribute, self.meta.include) + if key + + +## ... source file abbreviated to get to ColumnProperty examples ... + + + + if self.meta.exclude: + for key in self.meta.exclude: + try: + del attrs[key] + except KeyError: + if self.meta.attr_errors: + raise InvalidAttributeException(key) + return attrs + + def validate_attribute(self, attr_name): + try: + attr = getattr(self.model_class, attr_name) + except AttributeError: + try: + translation_class = ( + self.model_class.__translatable__['class'] + ) + attr = getattr(translation_class, attr_name) + except AttributeError: + if self.meta.attr_errors: + raise InvalidAttributeException(attr_name) + else: + return None, None + try: +~~ if not isinstance(attr.property, ColumnProperty): + if self.meta.attr_errors: + raise InvalidAttributeException(attr_name) + else: + return None, None + except AttributeError: + raise AttributeTypeException(attr_name) + return attr_name, attr.property + + def create_fields(self, form, properties): + for key, prop in properties.items(): + column = prop.columns[0] + try: + field = self.create_field(prop, column) + except UnknownTypeException: + if not self.meta.skip_unknown_types: + raise + else: + continue + + if not hasattr(form, key): + setattr(form, key, field) + + def skip_column_property(self, column_property): + if column_property._is_polymorphic_discriminator: + + +## ... source file continues with no further ColumnProperty examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-properties-relationshipproperty.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-properties-relationshipproperty.markdown new file mode 100644 index 000000000..a0f42a173 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-properties-relationshipproperty.markdown @@ -0,0 +1,124 @@ +title: sqlalchemy.orm.properties RelationshipProperty Example Code +category: page +slug: sqlalchemy-orm-properties-relationshipproperty-examples +sortorder: 500031087 +toc: False +sidebartitle: sqlalchemy.orm.properties RelationshipProperty +meta: Example code for understanding how to use the RelationshipProperty class from the sqlalchemy.orm.properties module of the SQLAlchemy project. + + +`RelationshipProperty` is a class within the `sqlalchemy.orm.properties` module of the SQLAlchemy project. + +ColumnProperty +is another callable from the `sqlalchemy.orm.properties` package with code examples. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / orm.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/orm.py) + +```python +# orm.py +from collections import OrderedDict +from functools import partial +from inspect import isclass +from operator import attrgetter + +import six +import sqlalchemy as sa +from sqlalchemy.engine.interfaces import Dialect +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import mapperlib +from sqlalchemy.orm.attributes import InstrumentedAttribute +from sqlalchemy.orm.exc import UnmappedInstanceError +~~from sqlalchemy.orm.properties import ColumnProperty, RelationshipProperty +from sqlalchemy.orm.query import _ColumnEntity +from sqlalchemy.orm.session import object_session +from sqlalchemy.orm.util import AliasedInsp + +from ..utils import is_sequence + + +def get_class_by_table(base, table, data=None): + found_classes = set( + c for c in base._decl_class_registry.values() + if hasattr(c, '__table__') and c.__table__ is table + ) + if len(found_classes) > 1: + if not data: + raise ValueError( + "Multiple declarative classes found for table '{0}'. " + "Please provide data parameter for this function to be able " + "to determine polymorphic scenarios.".format( + table.name + ) + ) + else: + for cls in found_classes: + mapper = sa.inspect(cls) + polymorphic_on = mapper.polymorphic_on.name + if polymorphic_on in data: + if data[polymorphic_on] == mapper.polymorphic_identity: + return cls + raise ValueError( + "Multiple declarative classes found for table '{0}'. Given " + "data row does not match any polymorphic identity of the " + "found classes.".format( + table.name + ) + ) + elif found_classes: + return found_classes.pop() + return None + + +def get_type(expr): + if hasattr(expr, 'type'): + return expr.type + elif isinstance(expr, InstrumentedAttribute): + expr = expr.property + + if isinstance(expr, ColumnProperty): + return expr.columns[0].type +~~ elif isinstance(expr, RelationshipProperty): + return expr.mapper.class_ + raise TypeError("Couldn't inspect type.") + + +def cast_if(expression, type_): + try: + expr_type = get_type(expression) + except TypeError: + expr_type = expression + check_type = type_().python_type + else: + check_type = type_ + + return ( + sa.cast(expression, type_) + if not isinstance(expr_type, check_type) + else expression + ) + + +def get_column_key(model, column): + mapper = sa.inspect(model) + try: + return mapper.get_property_by_column(column).key + + +## ... source file continues with no further RelationshipProperty examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-query-query.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-query-query.markdown new file mode 100644 index 000000000..4963c60c4 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-query-query.markdown @@ -0,0 +1,114 @@ +title: sqlalchemy.orm.query Query Example Code +category: page +slug: sqlalchemy-orm-query-query-examples +sortorder: 500031088 +toc: False +sidebartitle: sqlalchemy.orm.query Query +meta: Example code for understanding how to use the Query class from the sqlalchemy.orm.query module of the SQLAlchemy project. + + +`Query` is a class within the `sqlalchemy.orm.query` module of the SQLAlchemy project. + +QueryContext +is another callable from the `sqlalchemy.orm.query` package with code examples. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / fields.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./fields.py) + +```python +# fields.py +import warnings +from functools import partial + +import six +from promise import Promise, is_thenable +~~from sqlalchemy.orm.query import Query + +from graphene import NonNull +from graphene.relay import Connection, ConnectionField +from graphene.relay.connection import PageInfo +from graphql_relay.connection.arrayconnection import connection_from_list_slice + +from .batching import get_batch_resolver +from .utils import get_query + + +class UnsortedSQLAlchemyConnectionField(ConnectionField): + @property + def type(self): + from .types import SQLAlchemyObjectType + + _type = super(ConnectionField, self).type + nullable_type = get_nullable_type(_type) + if issubclass(nullable_type, Connection): + return _type + assert issubclass(nullable_type, SQLAlchemyObjectType), ( + "SQLALchemyConnectionField only accepts SQLAlchemyObjectType types, not {}" + ).format(nullable_type.__name__) + assert ( + nullable_type.connection + ), "The type {} doesn't have a connection".format( + nullable_type.__name__ + ) + assert _type == nullable_type, ( + "Passing a SQLAlchemyObjectType instance is deprecated. " + "Pass the connection type instead accessible via SQLAlchemyObjectType.connection" + ) + return nullable_type.connection + + @property + def model(self): + return get_nullable_type(self.type)._meta.node._meta.model + + @classmethod + def get_query(cls, model, info, **args): + return get_query(model, info.context) + + @classmethod + def resolve_connection(cls, connection_type, model, info, args, resolved): + if resolved is None: + resolved = cls.get_query(model, info, **args) +~~ if isinstance(resolved, Query): + _len = resolved.count() + else: + _len = len(resolved) + connection = connection_from_list_slice( + resolved, + args, + slice_start=0, + list_length=_len, + list_slice_length=_len, + connection_type=connection_type, + pageinfo_type=PageInfo, + edge_type=connection_type.Edge, + ) + connection.iterable = resolved + connection.length = _len + return connection + + @classmethod + def connection_resolver(cls, resolver, connection_type, model, root, info, **args): + resolved = resolver(root, info, **args) + + on_resolve = partial(cls.resolve_connection, connection_type, model, info, args) + if is_thenable(resolved): + return Promise.resolve(resolved).then(on_resolve) + + +## ... source file continues with no further Query examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-query-querycontext.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-query-querycontext.markdown new file mode 100644 index 000000000..3e8a4f02b --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-query-querycontext.markdown @@ -0,0 +1,81 @@ +title: sqlalchemy.orm.query QueryContext Example Code +category: page +slug: sqlalchemy-orm-query-querycontext-examples +sortorder: 500031089 +toc: False +sidebartitle: sqlalchemy.orm.query QueryContext +meta: Example code for understanding how to use the QueryContext class from the sqlalchemy.orm.query module of the SQLAlchemy project. + + +`QueryContext` is a class within the `sqlalchemy.orm.query` module of the SQLAlchemy project. + +Query +is another callable from the `sqlalchemy.orm.query` package with code examples. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / batching.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./batching.py) + +```python +# batching.py +import sqlalchemy +from promise import dataloader, promise +from sqlalchemy.orm import Session, strategies +~~from sqlalchemy.orm.query import QueryContext + + +def get_batch_resolver(relationship_prop): + + selectin_loader = strategies.SelectInLoader(relationship_prop, (('lazy', 'selectin'),)) + + class RelationshipLoader(dataloader.DataLoader): + cache = False + + def batch_load_fn(self, parents): # pylint: disable=method-hidden + child_mapper = relationship_prop.mapper + parent_mapper = relationship_prop.parent + session = Session.object_session(parents[0]) + + for parent in parents: + assert session is Session.object_session(parent) + assert parent not in session.dirty + + states = [(sqlalchemy.inspect(parent), True) for parent in parents] + +~~ query_context = QueryContext(session.query(parent_mapper.entity)) + + selectin_loader._load_for_path( + query_context, + parent_mapper._path_registry, + states, + None, + child_mapper, + ) + + return promise.Promise.resolve([getattr(parent, relationship_prop.key) for parent in parents]) + + loader = RelationshipLoader() + + def resolve(root, info, **args): + return loader.load(root) + + return resolve + + + +## ... source file continues with no further QueryContext examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-query.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-query.markdown new file mode 100644 index 000000000..55773f5e6 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-query.markdown @@ -0,0 +1,81 @@ +title: sqlalchemy.orm Query Example Code +category: page +slug: sqlalchemy-orm-query-examples +sortorder: 500031057 +toc: False +sidebartitle: sqlalchemy.orm Query +meta: Example code for understanding how to use the Query class from the sqlalchemy.orm module of the SQLAlchemy project. + + +`Query` is a class within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from SQLAlchemy Mixins +[SQLAlchemy Mixins](https://github.com/absent1706/sqlalchemy-mixins) +([PyPI package information](https://pypi.org/project/sqlalchemy-mixins/)) +is a collection of +[mixins](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful) +useful for extending [SQLAlchemy](/sqlalchemy.html) and simplifying +your [database](/databases.html)-interacting code for some common +use cases. SQLAlchemy Mixins is open sourced under the +[MIT license](https://github.com/absent1706/sqlalchemy-mixins/blob/master/LICENSE.txt). + +[**SQLAlchemy Mixins / sqlalchemy_mixins / session.py**](https://github.com/absent1706/sqlalchemy-mixins/blob/master/sqlalchemy_mixins/./session.py) + +```python +# session.py +~~from sqlalchemy.orm import Session, scoped_session, Query +from .utils import classproperty + + +class NoSessionError(RuntimeError): + pass + + +class SessionMixin: + _session = None + + @classmethod + def set_session(cls, session): + cls._session = session + + @classproperty + def session(cls): + if cls._session is not None: + return cls._session + else: + raise NoSessionError('Cant get session.' + 'Please, call SaActiveRecord.set_session()') + + @classproperty + def query(cls): + + +## ... source file continues with no further Query examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-relationship.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-relationship.markdown new file mode 100644 index 000000000..046e5cc97 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-relationship.markdown @@ -0,0 +1,218 @@ +title: sqlalchemy.orm relationship Example Code +category: page +slug: sqlalchemy-orm-relationship-examples +sortorder: 500031072 +toc: False +sidebartitle: sqlalchemy.orm relationship +meta: Python example code that shows how to use the relationship callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`relationship` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / tests / models.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/tests/models.py) + +```python +# models.py +from __future__ import absolute_import + +import enum + +from sqlalchemy import (Column, Date, Enum, ForeignKey, Integer, String, Table, + func, select) +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import column_property, composite, mapper, relationship + +PetKind = Enum("cat", "dog", name="pet_kind") + + +class HairKind(enum.Enum): + LONG = 'long' + SHORT = 'short' + + +Base = declarative_base() + +association_table = Table( + "association", + Base.metadata, + Column("pet_id", Integer, ForeignKey("pets.id")), + Column("reporter_id", Integer, ForeignKey("reporters.id")), +) + + +class Editor(Base): + __tablename__ = "editors" + editor_id = Column(Integer(), primary_key=True) + name = Column(String(100)) + + + +## ... source file abbreviated to get to relationship examples ... + + + pet_kind = Column(PetKind, nullable=False) + hair_kind = Column(Enum(HairKind, name="hair_kind"), nullable=False) + reporter_id = Column(Integer(), ForeignKey("reporters.id")) + + +class CompositeFullName(object): + def __init__(self, first_name, last_name): + self.first_name = first_name + self.last_name = last_name + + def __composite_values__(self): + return self.first_name, self.last_name + + def __repr__(self): + return "{} {}".format(self.first_name, self.last_name) + + +class Reporter(Base): + __tablename__ = "reporters" + + id = Column(Integer(), primary_key=True) + first_name = Column(String(30), doc="First name") + last_name = Column(String(30), doc="Last name") + email = Column(String(), doc="Email") + favorite_pet_kind = Column(PetKind) +~~ pets = relationship("Pet", secondary=association_table, backref="reporters", order_by="Pet.id") +~~ articles = relationship("Article", backref="reporter") +~~ favorite_article = relationship("Article", uselist=False) + + @hybrid_property + def hybrid_prop(self): + return self.first_name + + column_prop = column_property( + select([func.cast(func.count(id), Integer)]), doc="Column property" + ) + + composite_prop = composite(CompositeFullName, first_name, last_name, doc="Composite") + + +class Article(Base): + __tablename__ = "articles" + id = Column(Integer(), primary_key=True) + headline = Column(String(100)) + pub_date = Column(Date()) + reporter_id = Column(Integer(), ForeignKey("reporters.id")) + + +class ReflectedEditor(type): + + @classmethod + def __subclasses__(cls): + + +## ... source file continues with no further relationship examples... + +``` + + +## Example 2 from sqlalchemy-datatables +[sqlalchemy-datatables](https://github.com/Pegase745/sqlalchemy-datatables) +([PyPI package information](https://pypi.org/project/sqlalchemy-datatables/)) +is a helper library that makes it easier to use [SQLAlchemy](/sqlalchemy.html) +with the jQuery [JavaScript](/javascript.html) +[DataTables](https://datatables.net/) plugin. This library is designed to +be [web framework](/web-frameworks.html) agnostic and provides code examples +for both [Flask](/flask.html) and [Pyramid](/pyramid.html). + +The project is built and maintained by +[Michel Nemnom (Pegase745)](https://github.com/Pegase745) and is open +sourced under the +[MIT license](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/LICENSE). + +[**sqlalchemy-datatables / tests / models.py**](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/./tests/models.py) + +```python +# models.py +import datetime + +from sqlalchemy import Column, Date, DateTime, ForeignKey, Integer, String, func +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.hybrid import hybrid_property +~~from sqlalchemy.orm import backref, relationship + +Base = declarative_base() + + +class User(Base): + + __tablename__ = 'users' + + id = Column(Integer, primary_key=True) + name = Column(String, unique=True) + created_at = Column(DateTime, default=datetime.datetime.utcnow) + birthday = Column(Date) +~~ address = relationship('Address', uselist=False, backref=backref('user')) + + def __unicode__(self): + return '%s' % self.name + + def __repr__(self): + return '<%s#%s>' % (self.__class__.__name__, self.id) + + @hybrid_property + def dummy(self): + return self.name[0:3] + + @dummy.expression + def dummy(cls): + return func.substr(cls.name, 0, 3) + + +class Address(Base): + + __tablename__ = 'addresses' + + id = Column(Integer, primary_key=True) + description = Column(String, unique=True) + user_id = Column(Integer, ForeignKey('users.id')) + + + +## ... source file continues with no further relationship examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-relationshipproperty.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-relationshipproperty.markdown new file mode 100644 index 000000000..5466fa762 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-relationshipproperty.markdown @@ -0,0 +1,84 @@ +title: sqlalchemy.orm RelationshipProperty Example Code +category: page +slug: sqlalchemy-orm-relationshipproperty-examples +sortorder: 500031058 +toc: False +sidebartitle: sqlalchemy.orm RelationshipProperty +meta: Example code for understanding how to use the RelationshipProperty class from the sqlalchemy.orm module of the SQLAlchemy project. + + +`RelationshipProperty` is a class within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from SQLAlchemy Mixins +[SQLAlchemy Mixins](https://github.com/absent1706/sqlalchemy-mixins) +([PyPI package information](https://pypi.org/project/sqlalchemy-mixins/)) +is a collection of +[mixins](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful) +useful for extending [SQLAlchemy](/sqlalchemy.html) and simplifying +your [database](/databases.html)-interacting code for some common +use cases. SQLAlchemy Mixins is open sourced under the +[MIT license](https://github.com/absent1706/sqlalchemy-mixins/blob/master/LICENSE.txt). + +[**SQLAlchemy Mixins / sqlalchemy_mixins / inspection.py**](https://github.com/absent1706/sqlalchemy-mixins/blob/master/sqlalchemy_mixins/./inspection.py) + +```python +# inspection.py +from sqlalchemy import inspect +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method +~~from sqlalchemy.orm import RelationshipProperty + +from .utils import classproperty + + +Base = declarative_base() + + +class InspectionMixin(Base): + __abstract__ = True + + @classproperty + def columns(cls): + return inspect(cls).columns.keys() + + @classproperty + def primary_keys_full(cls): + mapper = cls.__mapper__ + return [ + mapper.get_property_by_column(column) + for column in mapper.primary_key + ] + + @classproperty + def primary_keys(cls): + + +## ... source file continues with no further RelationshipProperty examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-relationships-relationshipproperty.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-relationships-relationshipproperty.markdown new file mode 100644 index 000000000..8812fdf8f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-relationships-relationshipproperty.markdown @@ -0,0 +1,186 @@ +title: sqlalchemy.orm.relationships RelationshipProperty Example Code +category: page +slug: sqlalchemy-orm-relationships-relationshipproperty-examples +sortorder: 500031090 +toc: False +sidebartitle: sqlalchemy.orm.relationships RelationshipProperty +meta: Example code for understanding how to use the RelationshipProperty class from the sqlalchemy.orm.relationships module of the SQLAlchemy project. + + +`RelationshipProperty` is a class within the `sqlalchemy.orm.relationships` module of the SQLAlchemy project. + + + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / schema.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./schema.py) + +```python +# schema.py + + +import functools +import operator + +from sqlalchemy import Column as SA_Column +from sqlalchemy import Table as SA_Table +from sqlalchemy.orm import class_mapper +~~from sqlalchemy.orm.relationships import RelationshipProperty as SA_RelationshipProperty +from sqlalchemy.util.langhelpers import public_factory +from sqlalchemy.ext.hybrid import hybrid_property as SA_hybrid_property + +from sqlalchemy import exc, orm, util, inspect + + +from validator_collection import checkers, validators + +from sqlathanor import attributes +from sqlathanor._serialization_support import SerializationMixin +from sqlathanor.default_deserializers import get_type_mapping +from sqlathanor.utilities import parse_json, parse_yaml, parse_csv, read_csv_data +from sqlathanor.errors import SQLAthanorError + + +class Column(SerializationMixin, SA_Column): + + + def __init__(self, *args, **kwargs): + super(Column, self).__init__(*args, **kwargs) + + +~~class RelationshipProperty(SA_RelationshipProperty): + + def __init__(self, + argument, + supports_json = False, + supports_yaml = False, + supports_dict = False, + on_serialize = None, + on_deserialize = None, + **kwargs): + if on_serialize is not None and not isinstance(on_serialize, dict): + on_serialize = { + 'csv': on_serialize, + 'json': on_serialize, + 'yaml': on_serialize, + 'dict': on_serialize + } + elif on_serialize is not None: + if 'csv' not in on_serialize: + on_serialize['csv'] = None + if 'json' not in on_serialize: + on_serialize['json'] = None + if 'yaml' not in on_serialize: + on_serialize['yaml'] = None + if 'dict' not in on_serialize: + + +## ... source file abbreviated to get to RelationshipProperty examples ... + + + raise SQLAthanorError('on_deserialize for %s must be callable' % key) + + if supports_json is True: + supports_json = (True, True) + elif not supports_json: + supports_json = (False, False) + + if supports_yaml is True: + supports_yaml = (True, True) + elif not supports_yaml: + supports_yaml = (False, False) + + if supports_dict is True: + supports_dict = (True, True) + elif not supports_dict: + supports_dict = (False, False) + + self.supports_csv = (False, False) + self.csv_sequence = None + self.supports_json = supports_json + self.supports_yaml = supports_yaml + self.supports_dict = supports_dict + self.on_serialize = on_serialize + self.on_deserialize = on_deserialize + +~~ comparator_factory = kwargs.pop('comparator_factory', RelationshipProperty.Comparator) + +~~ super(RelationshipProperty, self).__init__(argument, + comparator_factory = comparator_factory, + **kwargs) + + class Comparator(SA_RelationshipProperty.Comparator): + @property + def supports_csv(self): + return self.prop.supports_csv + + @property + def csv_sequence(self): + return self.prop.csv_sequence + + @property + def supports_json(self): + return self.prop.supports_json + + @property + def supports_yaml(self): + return self.prop.supports_yaml + + @property + def supports_dict(self): + return self.prop.supports_dict + + @property + def on_serialize(self): + return self.prop.on_serialize + + @property + def on_deserialize(self): + return self.prop.on_deserialize + + +~~relationship = public_factory(RelationshipProperty, ".orm.relationship") + + +class Table(SA_Table): + + + def __init__(self, *args, **kwargs): + super(Table, self).__init__(*args, **kwargs) + + @classmethod + def from_dict(cls, + serialized, + tablename, + metadata, + primary_key, + column_kwargs = None, + skip_nested = True, + default_to_str = False, + type_mapping = None, + **kwargs): + if not isinstance(serialized, dict): + raise ValueError('serialized must be a dict') + + if not serialized: + raise ValueError('serialized cannot be empty') + + +## ... source file continues with no further RelationshipProperty examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-session-object-session.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-session-object-session.markdown new file mode 100644 index 000000000..719d25f15 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-session-object-session.markdown @@ -0,0 +1,132 @@ +title: sqlalchemy.orm.session object_session Example Code +category: page +slug: sqlalchemy-orm-session-object-session-examples +sortorder: 500031092 +toc: False +sidebartitle: sqlalchemy.orm.session object_session +meta: Python example code that shows how to use the object_session callable from the sqlalchemy.orm.session module of the SQLAlchemy project. + + +`object_session` is a callable within the `sqlalchemy.orm.session` module of the SQLAlchemy project. + +Session +is another callable from the `sqlalchemy.orm.session` package with code examples. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / orm.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/orm.py) + +```python +# orm.py +from collections import OrderedDict +from functools import partial +from inspect import isclass +from operator import attrgetter + +import six +import sqlalchemy as sa +from sqlalchemy.engine.interfaces import Dialect +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import mapperlib +from sqlalchemy.orm.attributes import InstrumentedAttribute +from sqlalchemy.orm.exc import UnmappedInstanceError +from sqlalchemy.orm.properties import ColumnProperty, RelationshipProperty +from sqlalchemy.orm.query import _ColumnEntity +~~from sqlalchemy.orm.session import object_session +from sqlalchemy.orm.util import AliasedInsp + +from ..utils import is_sequence + + +def get_class_by_table(base, table, data=None): + found_classes = set( + c for c in base._decl_class_registry.values() + if hasattr(c, '__table__') and c.__table__ is table + ) + if len(found_classes) > 1: + if not data: + raise ValueError( + "Multiple declarative classes found for table '{0}'. " + "Please provide data parameter for this function to be able " + "to determine polymorphic scenarios.".format( + table.name + ) + ) + else: + for cls in found_classes: + mapper = sa.inspect(cls) + polymorphic_on = mapper.polymorphic_on.name + if polymorphic_on in data: + + +## ... source file abbreviated to get to object_session examples ... + + + if isinstance(mixed, sa.Table): + mappers = [ + mapper for mapper in mapperlib._mapper_registry + if mixed in mapper.tables + ] + if len(mappers) > 1: + raise ValueError( + "Multiple mappers found for table '%s'." % mixed.name + ) + elif not mappers: + raise ValueError( + "Could not get mapper for table '%s'." % mixed.name + ) + else: + return mappers[0] + if not isclass(mixed): + mixed = type(mixed) + return sa.inspect(mixed) + + +def get_bind(obj): + if hasattr(obj, 'bind'): + conn = obj.bind + else: + try: +~~ conn = object_session(obj).bind + except UnmappedInstanceError: + conn = obj + + if not hasattr(conn, 'execute'): + raise TypeError( + 'This method accepts only Session, Engine, Connection and ' + 'declarative model objects.' + ) + return conn + + +def get_primary_keys(mixed): + return OrderedDict( + ( + (key, column) for key, column in get_columns(mixed).items() + if column.primary_key + ) + ) + + +def get_tables(mixed): + if isinstance(mixed, sa.Table): + return [mixed] + elif isinstance(mixed, sa.Column): + + +## ... source file continues with no further object_session examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-session-session.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-session-session.markdown new file mode 100644 index 000000000..d2c37bda9 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-session-session.markdown @@ -0,0 +1,85 @@ +title: sqlalchemy.orm.session Session Example Code +category: page +slug: sqlalchemy-orm-session-session-examples +sortorder: 500031091 +toc: False +sidebartitle: sqlalchemy.orm.session Session +meta: Example code for understanding how to use the Session class from the sqlalchemy.orm.session module of the SQLAlchemy project. + + +`Session` is a class within the `sqlalchemy.orm.session` module of the SQLAlchemy project. + +object_session +is another callable from the `sqlalchemy.orm.session` package with code examples. + +## Example 1 from flask-sqlalchemy +[flask-sqlalchemy](https://github.com/pallets/flask-sqlalchemy) +([project documentation](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) +and +[PyPI information](https://pypi.org/project/Flask-SQLAlchemy/)) is a +[Flask](/flask.html) extension that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) when building Flask apps. flask-sqlalchemy +provides helper functions that reduce the amount of common boilerplate +code that you have to frequently write yourself if you did not use this +library when combining Flask with SQLAlchemy. + +flask-sqlalchemy is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/pallets/flask-sqlalchemy/blob/master/LICENSE.rst). + +[**flask-sqlalchemy / src/flask_sqlalchemy / __init__.py**](https://github.com/pallets/flask-sqlalchemy/blob/master/src/flask_sqlalchemy/./__init__.py) + +```python +# __init__.py +import functools +import os +import sys +import warnings +from math import ceil +from operator import itemgetter +from threading import Lock +from time import perf_counter + +import sqlalchemy +from flask import _app_ctx_stack +from flask import abort +from flask import current_app +from flask import request +from flask.signals import Namespace +from sqlalchemy import event +from sqlalchemy import inspect +from sqlalchemy import orm +from sqlalchemy.engine.url import make_url +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.declarative import DeclarativeMeta +from sqlalchemy.orm.exc import UnmappedClassError +~~from sqlalchemy.orm.session import Session as SessionBase + +from .model import DefaultMeta +from .model import Model + +__version__ = "3.0.0.dev" + +_signals = Namespace() +models_committed = _signals.signal("models-committed") +before_models_committed = _signals.signal("before-models-committed") + + +def _make_table(db): + def _make_table(*args, **kwargs): + if len(args) > 1 and isinstance(args[1], db.Column): + args = (args[0], db.metadata) + args[1:] + info = kwargs.pop("info", None) or {} + info.setdefault("bind_key", None) + kwargs["info"] = info + return sqlalchemy.Table(*args, **kwargs) + + return _make_table + + +def _set_default_query_class(d, cls): + + +## ... source file continues with no further Session examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-session.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-session.markdown new file mode 100644 index 000000000..6145c36ab --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-session.markdown @@ -0,0 +1,168 @@ +title: sqlalchemy.orm session Example Code +category: page +slug: sqlalchemy-orm-session-examples +sortorder: 500031073 +toc: False +sidebartitle: sqlalchemy.orm session +meta: Python example code that shows how to use the session callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`session` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / tests / conftest.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/tests/conftest.py) + +```python +# conftest.py +import pytest +from sqlalchemy import create_engine +~~from sqlalchemy.orm import sessionmaker + +import graphene + +from ..converter import convert_sqlalchemy_composite +from ..registry import reset_global_registry +from .models import Base, CompositeFullName + +test_db_url = 'sqlite://' # use in-memory database for tests + + +@pytest.fixture(autouse=True) +def reset_registry(): + reset_global_registry() + + @convert_sqlalchemy_composite.register(CompositeFullName) + def convert_composite_class(composite, registry): + return graphene.Field(graphene.Int) + + +@pytest.yield_fixture(scope="function") +def session_factory(): + engine = create_engine(test_db_url) + Base.metadata.create_all(engine) + + yield sessionmaker(bind=engine) + + engine.dispose() + + +@pytest.fixture(scope="function") +~~def session(session_factory): + return session_factory() + + + +## ... source file continues with no further session examples... + +``` + + +## Example 2 from sqlalchemy-datatables +[sqlalchemy-datatables](https://github.com/Pegase745/sqlalchemy-datatables) +([PyPI package information](https://pypi.org/project/sqlalchemy-datatables/)) +is a helper library that makes it easier to use [SQLAlchemy](/sqlalchemy.html) +with the jQuery [JavaScript](/javascript.html) +[DataTables](https://datatables.net/) plugin. This library is designed to +be [web framework](/web-frameworks.html) agnostic and provides code examples +for both [Flask](/flask.html) and [Pyramid](/pyramid.html). + +The project is built and maintained by +[Michel Nemnom (Pegase745)](https://github.com/Pegase745) and is open +sourced under the +[MIT license](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/LICENSE). + +[**sqlalchemy-datatables / tests / conftest.py**](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/./tests/conftest.py) + +```python +# conftest.py +from __future__ import print_function + +import itertools +from datetime import datetime, timedelta + +import faker +import pytest +from sqlalchemy import create_engine +~~from sqlalchemy.orm import sessionmaker + +from .models import Address, Base, User + + +def populate(session): + users = [] + f = faker.Faker(seed=1) + addresses = [Address(description=d) for d in ['Street', 'Avenue', 'Road']] +~~ session.add_all(addresses) + + for i, addr in zip(range(0, 50), itertools.cycle(addresses)): + user = User( + name=f.name(), + address=addr, + birthday=datetime(1970, 1, 2) + timedelta(days=10 * i)) + users.append(user) + +~~ session.add_all(users) +~~ session.commit() + + +@pytest.fixture(scope="session") +def engine(): + print("TestCase: Using sqlite database") + return create_engine('sqlite:///', echo=False) + + +@pytest.fixture(scope="session") +~~def session(engine): + sessionmaker_ = sessionmaker(bind=engine) + session = sessionmaker_() + Base.metadata.create_all(engine) + populate(session) + + yield session + +~~ session.close() + + + +## ... source file continues with no further session examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-sessionmaker.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-sessionmaker.markdown new file mode 100644 index 000000000..b0c85e19f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-sessionmaker.markdown @@ -0,0 +1,168 @@ +title: sqlalchemy.orm sessionmaker Example Code +category: page +slug: sqlalchemy-orm-sessionmaker-examples +sortorder: 500031074 +toc: False +sidebartitle: sqlalchemy.orm sessionmaker +meta: Python example code that shows how to use the sessionmaker callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`sessionmaker` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / tests / conftest.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/tests/conftest.py) + +```python +# conftest.py +import pytest +from sqlalchemy import create_engine +~~from sqlalchemy.orm import sessionmaker + +import graphene + +from ..converter import convert_sqlalchemy_composite +from ..registry import reset_global_registry +from .models import Base, CompositeFullName + +test_db_url = 'sqlite://' # use in-memory database for tests + + +@pytest.fixture(autouse=True) +def reset_registry(): + reset_global_registry() + + @convert_sqlalchemy_composite.register(CompositeFullName) + def convert_composite_class(composite, registry): + return graphene.Field(graphene.Int) + + +@pytest.yield_fixture(scope="function") +def session_factory(): + engine = create_engine(test_db_url) + Base.metadata.create_all(engine) + +~~ yield sessionmaker(bind=engine) + + engine.dispose() + + +@pytest.fixture(scope="function") +def session(session_factory): + return session_factory() + + + +## ... source file continues with no further sessionmaker examples... + +``` + + +## Example 2 from sqlalchemy-datatables +[sqlalchemy-datatables](https://github.com/Pegase745/sqlalchemy-datatables) +([PyPI package information](https://pypi.org/project/sqlalchemy-datatables/)) +is a helper library that makes it easier to use [SQLAlchemy](/sqlalchemy.html) +with the jQuery [JavaScript](/javascript.html) +[DataTables](https://datatables.net/) plugin. This library is designed to +be [web framework](/web-frameworks.html) agnostic and provides code examples +for both [Flask](/flask.html) and [Pyramid](/pyramid.html). + +The project is built and maintained by +[Michel Nemnom (Pegase745)](https://github.com/Pegase745) and is open +sourced under the +[MIT license](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/LICENSE). + +[**sqlalchemy-datatables / tests / conftest.py**](https://github.com/Pegase745/sqlalchemy-datatables/blob/master/./tests/conftest.py) + +```python +# conftest.py +from __future__ import print_function + +import itertools +from datetime import datetime, timedelta + +import faker +import pytest +from sqlalchemy import create_engine +~~from sqlalchemy.orm import sessionmaker + +from .models import Address, Base, User + + +def populate(session): + users = [] + f = faker.Faker(seed=1) + addresses = [Address(description=d) for d in ['Street', 'Avenue', 'Road']] + session.add_all(addresses) + + for i, addr in zip(range(0, 50), itertools.cycle(addresses)): + user = User( + name=f.name(), + address=addr, + birthday=datetime(1970, 1, 2) + timedelta(days=10 * i)) + users.append(user) + + session.add_all(users) + session.commit() + + +@pytest.fixture(scope="session") +def engine(): + print("TestCase: Using sqlite database") + return create_engine('sqlite:///', echo=False) + + +@pytest.fixture(scope="session") +def session(engine): +~~ sessionmaker_ = sessionmaker(bind=engine) + session = sessionmaker_() + Base.metadata.create_all(engine) + populate(session) + + yield session + + session.close() + + + +## ... source file continues with no further sessionmaker examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-strategies.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-strategies.markdown new file mode 100644 index 000000000..6d6bf87e3 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-strategies.markdown @@ -0,0 +1,93 @@ +title: sqlalchemy.orm strategies Example Code +category: page +slug: sqlalchemy-orm-strategies-examples +sortorder: 500031075 +toc: False +sidebartitle: sqlalchemy.orm strategies +meta: Python example code that shows how to use the strategies callable from the sqlalchemy.orm module of the SQLAlchemy project. + + +`strategies` is a callable within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +SynonymProperty, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +and sessionmaker +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / batching.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./batching.py) + +```python +# batching.py +import sqlalchemy +from promise import dataloader, promise +~~from sqlalchemy.orm import Session, strategies +from sqlalchemy.orm.query import QueryContext + + +def get_batch_resolver(relationship_prop): + +~~ selectin_loader = strategies.SelectInLoader(relationship_prop, (('lazy', 'selectin'),)) + + class RelationshipLoader(dataloader.DataLoader): + cache = False + + def batch_load_fn(self, parents): # pylint: disable=method-hidden + child_mapper = relationship_prop.mapper + parent_mapper = relationship_prop.parent + session = Session.object_session(parents[0]) + + for parent in parents: + assert session is Session.object_session(parent) + assert parent not in session.dirty + + states = [(sqlalchemy.inspect(parent), True) for parent in parents] + + query_context = QueryContext(session.query(parent_mapper.entity)) + + selectin_loader._load_for_path( + query_context, + parent_mapper._path_registry, + states, + None, + child_mapper, + ) + + +## ... source file continues with no further strategies examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-synonymproperty.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-synonymproperty.markdown new file mode 100644 index 000000000..2fa640302 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-synonymproperty.markdown @@ -0,0 +1,145 @@ +title: sqlalchemy.orm SynonymProperty Example Code +category: page +slug: sqlalchemy-orm-synonymproperty-examples +sortorder: 500031060 +toc: False +sidebartitle: sqlalchemy.orm SynonymProperty +meta: Example code for understanding how to use the SynonymProperty class from the sqlalchemy.orm module of the SQLAlchemy project. + + +`SynonymProperty` is a class within the `sqlalchemy.orm` module of the SQLAlchemy project. + +ColumnProperty, +CompositeProperty, +Load, +Mapper, +Query, +RelationshipProperty, +Session, +aliased, +attributes, +backref, +class_mapper, +column_property, +composite, +interfaces, +mapper, +mapperlib, +object_mapper, +object_session, +query, +relationship, +session, +sessionmaker, +and strategies +are several other callables with code examples from the same `sqlalchemy.orm` package. + +## Example 1 from marshmallow-sqlalchemy +[marshmallow-sqlalchemy](https://github.com/marshmallow-code/marshmallow-sqlalchemy) +([project documentation](https://marshmallow-sqlalchemy.readthedocs.io/en/latest/)) +is a code library that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) with the +[Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +data serialization tool. + +The marshmallow-sqlalchemy project is provided as open source under the +[MIT license](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/LICENSE). + +[**marshmallow-sqlalchemy / src/marshmallow_sqlalchemy / convert.py**](https://github.com/marshmallow-code/marshmallow-sqlalchemy/blob/dev/src/marshmallow_sqlalchemy/./convert.py) + +```python +# convert.py +import inspect +import functools +import warnings + +import uuid +import marshmallow as ma +from marshmallow import validate, fields +from sqlalchemy.dialects import postgresql, mysql, mssql +~~from sqlalchemy.orm import SynonymProperty +import sqlalchemy as sa + +from .exceptions import ModelConversionError +from .fields import Related, RelatedList + + +def _is_field(value): + return isinstance(value, type) and issubclass(value, fields.Field) + + +def _has_default(column): + return ( + column.default is not None + or column.server_default is not None + or _is_auto_increment(column) + ) + + +def _is_auto_increment(column): + return column.table is not None and column is column.table._autoincrement_column + + +def _postgres_array_factory(converter, data_type): + return functools.partial( + + +## ... source file abbreviated to get to SynonymProperty examples ... + + + @property + def type_mapping(self): + if self.schema_cls: + return self.schema_cls.TYPE_MAPPING + else: + return ma.Schema.TYPE_MAPPING + + def fields_for_model( + self, + model, + *, + include_fk=False, + include_relationships=False, + fields=None, + exclude=None, + base_fields=None, + dict_cls=dict, + ): + result = dict_cls() + base_fields = base_fields or {} + for prop in model.__mapper__.iterate_properties: + key = self._get_field_name(prop) + if self._should_exclude_field(prop, fields=fields, exclude=exclude): + result[key] = None + continue +~~ if isinstance(prop, SynonymProperty): + continue + if hasattr(prop, "columns"): + if not include_fk: + for column in prop.columns: + if not column.foreign_keys: + break + else: + continue + if not include_relationships and hasattr(prop, "direction"): + continue + field = base_fields.get(key) or self.property2field(prop) + if field: + result[key] = field + return result + + def fields_for_table( + self, + table, + *, + include_fk=False, + fields=None, + exclude=None, + base_fields=None, + dict_cls=dict, + + +## ... source file continues with no further SynonymProperty examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-util-aliasedclass.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-util-aliasedclass.markdown new file mode 100644 index 000000000..d971263db --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-util-aliasedclass.markdown @@ -0,0 +1,159 @@ +title: sqlalchemy.orm.util AliasedClass Example Code +category: page +slug: sqlalchemy-orm-util-aliasedclass-examples +sortorder: 500031093 +toc: False +sidebartitle: sqlalchemy.orm.util AliasedClass +meta: Example code for understanding how to use the AliasedClass class from the sqlalchemy.orm.util module of the SQLAlchemy project. + + +`AliasedClass` is a class within the `sqlalchemy.orm.util` module of the SQLAlchemy project. + +AliasedInsp +and +identity_key +are a couple of other callables within the `sqlalchemy.orm.util` package that also have code examples. + +## Example 1 from SQLAlchemy Mixins +[SQLAlchemy Mixins](https://github.com/absent1706/sqlalchemy-mixins) +([PyPI package information](https://pypi.org/project/sqlalchemy-mixins/)) +is a collection of +[mixins](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful) +useful for extending [SQLAlchemy](/sqlalchemy.html) and simplifying +your [database](/databases.html)-interacting code for some common +use cases. SQLAlchemy Mixins is open sourced under the +[MIT license](https://github.com/absent1706/sqlalchemy-mixins/blob/master/LICENSE.txt). + +[**SQLAlchemy Mixins / sqlalchemy_mixins / smartquery.py**](https://github.com/absent1706/sqlalchemy-mixins/blob/master/sqlalchemy_mixins/./smartquery.py) + +```python +# smartquery.py +try: + from typing import List +except ImportError: # pragma: no cover + pass + +from collections import OrderedDict + +import sqlalchemy +from sqlalchemy import asc, desc, inspect +from sqlalchemy.orm import aliased, contains_eager +~~from sqlalchemy.orm.util import AliasedClass +from sqlalchemy.sql import operators, extract + +from .eagerload import _flatten_schema, _eager_expr_from_flat_schema, \ + EagerLoadMixin +from .inspection import InspectionMixin +from .utils import classproperty + +RELATION_SPLITTER = '___' +OPERATOR_SPLITTER = '__' + +DESC_PREFIX = '-' + + +def _parse_path_and_make_aliases(entity, entity_path, attrs, aliases): + relations = {} + for attr in attrs: + if RELATION_SPLITTER in attr: + relation_name, nested_attr = attr.split(RELATION_SPLITTER, 1) + if relation_name in relations: + relations[relation_name].append(nested_attr) + else: + relations[relation_name] = [nested_attr] + + for relation_name, nested_attrs in relations.items(): + + +## ... source file abbreviated to get to AliasedClass examples ... + + + 'month_ne': lambda c, v: extract('month', c) != v, + 'month_gt': lambda c, v: extract('month', c) > v, + 'month_ge': lambda c, v: extract('month', c) >= v, + 'month_lt': lambda c, v: extract('month', c) < v, + 'month_le': lambda c, v: extract('month', c) <= v, + + 'day': lambda c, v: extract('day', c) == v, + 'day_ne': lambda c, v: extract('day', c) != v, + 'day_gt': lambda c, v: extract('day', c) > v, + 'day_ge': lambda c, v: extract('day', c) >= v, + 'day_lt': lambda c, v: extract('day', c) < v, + 'day_le': lambda c, v: extract('day', c) <= v, + } + + @classproperty + def filterable_attributes(cls): + return cls.relations + cls.columns + \ + cls.hybrid_properties + cls.hybrid_methods + + @classproperty + def sortable_attributes(cls): + return cls.columns + cls.hybrid_properties + + @classmethod + def filter_expr(cls_or_alias, **filters): +~~ if isinstance(cls_or_alias, AliasedClass): + mapper, cls = cls_or_alias, inspect(cls_or_alias).mapper.class_ + else: + mapper = cls = cls_or_alias + + expressions = [] + valid_attributes = cls.filterable_attributes + for attr, value in filters.items(): + if attr in cls.hybrid_methods: + method = getattr(cls, attr) + expressions.append(method(value, mapper=mapper)) + else: + if OPERATOR_SPLITTER in attr: + attr_name, op_name = attr.rsplit(OPERATOR_SPLITTER, 1) + if op_name not in cls._operators: + raise KeyError('Expression `{}` has incorrect ' + 'operator `{}`'.format(attr, op_name)) + op = cls._operators[op_name] + else: + attr_name, op = attr, operators.eq + + if attr_name not in valid_attributes: + raise KeyError('Expression `{}` ' + 'has incorrect attribute `{}`' + .format(attr, attr_name)) + + column = getattr(mapper, attr_name) + expressions.append(op(column, value)) + + return expressions + + @classmethod + def order_expr(cls_or_alias, *columns): +~~ if isinstance(cls_or_alias, AliasedClass): + mapper, cls = cls_or_alias, inspect(cls_or_alias).mapper.class_ + else: + mapper = cls = cls_or_alias + + expressions = [] + for attr in columns: + fn, attr = (desc, attr[1:]) if attr.startswith(DESC_PREFIX) \ + else (asc, attr) + if attr not in cls.sortable_attributes: + raise KeyError('Cant order {} by {}'.format(cls, attr)) + + expr = fn(getattr(mapper, attr)) + expressions.append(expr) + return expressions + + @classmethod + def smart_query(cls, filters=None, sort_attrs=None, schema=None): + return smart_query(cls.query, filters, sort_attrs, schema) + + @classmethod + def where(cls, **filters): + return cls.smart_query(filters) + + @classmethod + + +## ... source file continues with no further AliasedClass examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-util-aliasedinsp.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-util-aliasedinsp.markdown new file mode 100644 index 000000000..041837312 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-util-aliasedinsp.markdown @@ -0,0 +1,212 @@ +title: sqlalchemy.orm.util AliasedInsp Example Code +category: page +slug: sqlalchemy-orm-util-aliasedinsp-examples +sortorder: 500031094 +toc: False +sidebartitle: sqlalchemy.orm.util AliasedInsp +meta: Example code for understanding how to use the AliasedInsp class from the sqlalchemy.orm.util module of the SQLAlchemy project. + + +`AliasedInsp` is a class within the `sqlalchemy.orm.util` module of the SQLAlchemy project. + +AliasedClass +and +identity_key +are a couple of other callables within the `sqlalchemy.orm.util` package that also have code examples. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / orm.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/orm.py) + +```python +# orm.py +from collections import OrderedDict +from functools import partial +from inspect import isclass +from operator import attrgetter + +import six +import sqlalchemy as sa +from sqlalchemy.engine.interfaces import Dialect +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import mapperlib +from sqlalchemy.orm.attributes import InstrumentedAttribute +from sqlalchemy.orm.exc import UnmappedInstanceError +from sqlalchemy.orm.properties import ColumnProperty, RelationshipProperty +from sqlalchemy.orm.query import _ColumnEntity +from sqlalchemy.orm.session import object_session +~~from sqlalchemy.orm.util import AliasedInsp + +from ..utils import is_sequence + + +def get_class_by_table(base, table, data=None): + found_classes = set( + c for c in base._decl_class_registry.values() + if hasattr(c, '__table__') and c.__table__ is table + ) + if len(found_classes) > 1: + if not data: + raise ValueError( + "Multiple declarative classes found for table '{0}'. " + "Please provide data parameter for this function to be able " + "to determine polymorphic scenarios.".format( + table.name + ) + ) + else: + for cls in found_classes: + mapper = sa.inspect(cls) + polymorphic_on = mapper.polymorphic_on.name + if polymorphic_on in data: + if data[polymorphic_on] == mapper.polymorphic_identity: + + +## ... source file abbreviated to get to AliasedInsp examples ... + + + return mapper.get_property_by_column(column).key + except sa.orm.exc.UnmappedColumnError: + for key, c in mapper.columns.items(): + if c.name == column.name and c.table is column.table: + return key + raise sa.orm.exc.UnmappedColumnError( + 'No column %s is configured on mapper %s...' % + (column, mapper) + ) + + +def get_mapper(mixed): + if isinstance(mixed, sa.orm.query._MapperEntity): + mixed = mixed.expr + elif isinstance(mixed, sa.Column): + mixed = mixed.table + elif isinstance(mixed, sa.orm.query._ColumnEntity): + mixed = mixed.expr + + if isinstance(mixed, sa.orm.Mapper): + return mixed + if isinstance(mixed, sa.orm.util.AliasedClass): + return sa.inspect(mixed).mapper + if isinstance(mixed, sa.sql.selectable.Alias): + mixed = mixed.element +~~ if isinstance(mixed, AliasedInsp): + return mixed.mapper + if isinstance(mixed, sa.orm.attributes.InstrumentedAttribute): + mixed = mixed.class_ + if isinstance(mixed, sa.Table): + mappers = [ + mapper for mapper in mapperlib._mapper_registry + if mixed in mapper.tables + ] + if len(mappers) > 1: + raise ValueError( + "Multiple mappers found for table '%s'." % mixed.name + ) + elif not mappers: + raise ValueError( + "Could not get mapper for table '%s'." % mixed.name + ) + else: + return mappers[0] + if not isclass(mixed): + mixed = type(mixed) + return sa.inspect(mixed) + + +def get_bind(obj): + + +## ... source file abbreviated to get to AliasedInsp examples ... + + + else d['entity'] + for d in query.column_descriptions + ] + return [ + get_query_entity(expr) for expr in exprs + ] + [ + get_query_entity(entity) for entity in query._join_entities + ] + + +def is_labeled_query(expr): + return ( + isinstance(expr, sa.sql.elements.Label) and + isinstance( + list(expr.base_columns)[0], + (sa.sql.selectable.Select, sa.sql.selectable.ScalarSelect) + ) + ) + + +def get_query_entity(expr): + if isinstance(expr, sa.orm.attributes.InstrumentedAttribute): + return expr.parent.class_ + elif isinstance(expr, sa.Column): + return expr.table +~~ elif isinstance(expr, AliasedInsp): + return expr.entity + return expr + + +def get_query_entity_by_alias(query, alias): + entities = get_query_entities(query) + + if not alias: + return entities[0] + + for entity in entities: + if isinstance(entity, sa.orm.util.AliasedClass): + name = sa.inspect(entity).name + else: + name = get_mapper(entity).tables[0].name + + if name == alias: + return entity + + +def get_polymorphic_mappers(mixed): +~~ if isinstance(mixed, AliasedInsp): + return mixed.with_polymorphic_mappers + else: + return mixed.polymorphic_map.values() + + +def get_query_descriptor(query, entity, attr): + if attr in query_labels(query): + return attr + else: + entity = get_query_entity_by_alias(query, entity) + if entity: + descriptor = get_descriptor(entity, attr) + if ( + hasattr(descriptor, 'property') and + isinstance(descriptor.property, sa.orm.RelationshipProperty) + ): + return + return descriptor + + +def get_descriptor(entity, attr): + mapper = sa.inspect(entity) + + for key, descriptor in get_all_descriptors(mapper).items(): + + +## ... source file continues with no further AliasedInsp examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-orm-util-identity-key.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-orm-util-identity-key.markdown new file mode 100644 index 000000000..abd9ec301 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-orm-util-identity-key.markdown @@ -0,0 +1,124 @@ +title: sqlalchemy.orm.util identity_key Example Code +category: page +slug: sqlalchemy-orm-util-identity-key-examples +sortorder: 500031095 +toc: False +sidebartitle: sqlalchemy.orm.util identity_key +meta: Python example code that shows how to use the identity_key callable from the sqlalchemy.orm.util module of the SQLAlchemy project. + + +`identity_key` is a callable within the `sqlalchemy.orm.util` module of the SQLAlchemy project. + +AliasedClass +and +AliasedInsp +are a couple of other callables within the `sqlalchemy.orm.util` package that also have code examples. + +## Example 1 from WTForms-Alchemy +[wtforms-alchemy](git@github.com:kvesteri/wtforms-alchemy.git) +([documentation](https://wtforms-alchemy.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/WTForms-Alchemy/)) +is a [WTForms](https://wtforms.readthedocs.io/en/2.2.1/) extension toolkit +for easier creation of [SQLAlchemy](/sqlalchemy.html) model based forms. +While this project primarily focuses on proper form handling, it also +has many good examples of how to use various parts of SQLAlchemy in +its code base. The project is provided as open source under the +[MIT license](https://github.com/kvesteri/wtforms-alchemy/blob/master/LICENSE). + +[**WTForms-Alchemy / wtforms_alchemy / fields.py**](https://github.com/kvesteri/wtforms-alchemy/blob/master/wtforms_alchemy/./fields.py) + +```python +# fields.py +from __future__ import unicode_literals + +import operator +from itertools import groupby + +import six +~~from sqlalchemy.orm.util import identity_key +from sqlalchemy_utils import Country, i18n, PhoneNumber +from sqlalchemy_utils.primitives import WeekDay, WeekDays +from wtforms import widgets +from wtforms.compat import string_types, text_type +from wtforms.fields import FieldList, FormField, SelectFieldBase +from wtforms.validators import ValidationError +from wtforms.widgets import CheckboxInput, ListWidget +from wtforms_components import SelectField, SelectMultipleField +from wtforms_components.fields.html5 import StringField +from wtforms_components.widgets import SelectWidget, TelInput + +from .utils import find_entity + +try: + from wtforms.utils import unset_value as _unset_value +except ImportError: + from wtforms.fields import _unset_value + + +class SkipOperation(Exception): + pass + + +class ModelFormField(FormField): + + +## ... source file abbreviated to get to identity_key examples ... + + + + def _set_data(self, data): + self._data = data + self._formdata = None + + data = property(_get_data, _set_data) + + def iter_choices(self): + for pk, obj in self._get_object_list(): + yield (pk, self.get_label(obj), obj in self.data) + + def process_formdata(self, valuelist): + self._formdata = set(valuelist) + + def pre_validate(self, form): + if self._invalid_formdata: + raise ValidationError(self.gettext('Not a valid choice')) + elif self.data: + obj_list = list(x[1] for x in self._get_object_list()) + for v in self.data: + if v not in obj_list: + raise ValidationError(self.gettext('Not a valid choice')) + + +def get_pk_from_identity(obj): +~~ cls, key = identity_key(instance=obj)[0:2] + return ':'.join(text_type(x) for x in key) + + +class GroupedQuerySelectField(SelectField): + widget = SelectWidget() + + def __init__( + self, + label=None, + validators=None, + query_factory=None, + get_pk=None, + get_label=None, + get_group=None, + allow_blank=False, + blank_text='', + blank_value='__None', + **kwargs + ): + super(GroupedQuerySelectField, self).__init__( + label, + validators, + coerce=lambda x: x, + **kwargs + + +## ... source file continues with no further identity_key examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-pool-nullpool.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-pool-nullpool.markdown new file mode 100644 index 000000000..be8bb61d5 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-pool-nullpool.markdown @@ -0,0 +1,198 @@ +title: sqlalchemy.pool NullPool Example Code +category: page +slug: sqlalchemy-pool-nullpool-examples +sortorder: 500031096 +toc: False +sidebartitle: sqlalchemy.pool NullPool +meta: Example code for understanding how to use the NullPool class from the sqlalchemy.pool module of the SQLAlchemy project. + + +`NullPool` is a class within the `sqlalchemy.pool` module of the SQLAlchemy project. + +StaticPool +is another callable from the `sqlalchemy.pool` package with code examples. + +## Example 1 from flask-sqlalchemy +[flask-sqlalchemy](https://github.com/pallets/flask-sqlalchemy) +([project documentation](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) +and +[PyPI information](https://pypi.org/project/Flask-SQLAlchemy/)) is a +[Flask](/flask.html) extension that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) when building Flask apps. flask-sqlalchemy +provides helper functions that reduce the amount of common boilerplate +code that you have to frequently write yourself if you did not use this +library when combining Flask with SQLAlchemy. + +flask-sqlalchemy is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/pallets/flask-sqlalchemy/blob/master/LICENSE.rst). + +[**flask-sqlalchemy / src/flask_sqlalchemy / __init__.py**](https://github.com/pallets/flask-sqlalchemy/blob/master/src/flask_sqlalchemy/./__init__.py) + +```python +# __init__.py +import functools +import os +import sys +import warnings +from math import ceil +from operator import itemgetter +from threading import Lock +from time import perf_counter + +import sqlalchemy +from flask import _app_ctx_stack +from flask import abort +from flask import current_app +from flask import request +from flask.signals import Namespace +from sqlalchemy import event +from sqlalchemy import inspect +from sqlalchemy import orm +from sqlalchemy.engine.url import make_url +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.declarative import DeclarativeMeta +from sqlalchemy.orm.exc import UnmappedClassError +from sqlalchemy.orm.session import Session as SessionBase + +from .model import DefaultMeta +from .model import Model + +__version__ = "3.0.0.dev" + +_signals = Namespace() +models_committed = _signals.signal("models-committed") +before_models_committed = _signals.signal("before-models-committed") + + +def _make_table(db): + + +## ... source file abbreviated to get to NullPool examples ... + + + def apply_driver_hacks(self, app, sa_url, options): + if sa_url.drivername.startswith("mysql"): + sa_url.query.setdefault("charset", "utf8") + if sa_url.drivername != "mysql+gaerdbms": + options.setdefault("pool_size", 10) + options.setdefault("pool_recycle", 7200) + elif sa_url.drivername == "sqlite": + pool_size = options.get("pool_size") + detected_in_memory = False + if sa_url.database in (None, "", ":memory:"): + detected_in_memory = True + from sqlalchemy.pool import StaticPool + + options["poolclass"] = StaticPool + if "connect_args" not in options: + options["connect_args"] = {} + options["connect_args"]["check_same_thread"] = False + + if pool_size == 0: + raise RuntimeError( + "SQLite in memory database with an " + "empty queue not possible due to data " + "loss." + ) + elif not pool_size: +~~ from sqlalchemy.pool import NullPool + + options["poolclass"] = NullPool + + if not detected_in_memory and not os.path.isabs(sa_url.database): + os.makedirs(app.instance_path, exist_ok=True) + sa_url.database = os.path.join(app.instance_path, sa_url.database) + + @property + def engine(self): + return self.get_engine() + + def make_connector(self, app=None, bind=None): + return _EngineConnector(self, self.get_app(app), bind) + + def get_engine(self, app=None, bind=None): + + app = self.get_app(app) + state = get_state(app) + + with self._engine_lock: + connector = state.connectors.get(bind) + + if connector is None: + connector = self.make_connector(app, bind) + + +## ... source file continues with no further NullPool examples... + +``` + + +## Example 2 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management that is +powered by [SQLAlchemy](/sqlalchemy.html) on the backend. The code +for this project is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / cli / setup.py**](https://github.com/indico/indico/blob/master/indico/cli/setup.py) + +```python +# setup.py + +from __future__ import unicode_literals + +import os +import re +import shutil +import socket +import sys +from operator import attrgetter +from smtplib import SMTP + +import click +from click import wrap_text +from flask.helpers import get_root_path +from pkg_resources import iter_entry_points +from prompt_toolkit import prompt +from prompt_toolkit.contrib.completers import PathCompleter, WordCompleter +from prompt_toolkit.layout.lexers import SimpleLexer +from prompt_toolkit.styles import style_from_dict +from prompt_toolkit.token import Token +from pytz import all_timezones, common_timezones +from redis import RedisError, StrictRedis +from sqlalchemy import create_engine +from sqlalchemy.exc import OperationalError +~~from sqlalchemy.pool import NullPool +from terminaltables import AsciiTable +from werkzeug.urls import url_parse + +from indico.core.db.sqlalchemy.util.models import import_all_models +from indico.util.console import cformat +from indico.util.string import validate_email + + +click.disable_unicode_literals_warning = True + + +def _echo(msg=''): + click.echo(msg, err=True) + + +def _warn(msg): + msg = wrap_text(msg) + click.echo(click.style(msg, fg='yellow'), err=True) + + +def _error(msg): + msg = wrap_text(msg) + click.echo(click.style(msg, fg='red', bold=True), err=True) + + + +## ... source file continues with no further NullPool examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-pool-staticpool.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-pool-staticpool.markdown new file mode 100644 index 000000000..89e7bcaf5 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-pool-staticpool.markdown @@ -0,0 +1,128 @@ +title: sqlalchemy.pool StaticPool Example Code +category: page +slug: sqlalchemy-pool-staticpool-examples +sortorder: 500031097 +toc: False +sidebartitle: sqlalchemy.pool StaticPool +meta: Example code for understanding how to use the StaticPool class from the sqlalchemy.pool module of the SQLAlchemy project. + + +`StaticPool` is a class within the `sqlalchemy.pool` module of the SQLAlchemy project. + +NullPool +is another callable from the `sqlalchemy.pool` package with code examples. + +## Example 1 from flask-sqlalchemy +[flask-sqlalchemy](https://github.com/pallets/flask-sqlalchemy) +([project documentation](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) +and +[PyPI information](https://pypi.org/project/Flask-SQLAlchemy/)) is a +[Flask](/flask.html) extension that makes it easier to use +[SQLAlchemy](/sqlalchemy.html) when building Flask apps. flask-sqlalchemy +provides helper functions that reduce the amount of common boilerplate +code that you have to frequently write yourself if you did not use this +library when combining Flask with SQLAlchemy. + +flask-sqlalchemy is provided as open source under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/pallets/flask-sqlalchemy/blob/master/LICENSE.rst). + +[**flask-sqlalchemy / src/flask_sqlalchemy / __init__.py**](https://github.com/pallets/flask-sqlalchemy/blob/master/src/flask_sqlalchemy/./__init__.py) + +```python +# __init__.py +import functools +import os +import sys +import warnings +from math import ceil +from operator import itemgetter +from threading import Lock +from time import perf_counter + +import sqlalchemy +from flask import _app_ctx_stack +from flask import abort +from flask import current_app +from flask import request +from flask.signals import Namespace +from sqlalchemy import event +from sqlalchemy import inspect +from sqlalchemy import orm +from sqlalchemy.engine.url import make_url +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.declarative import DeclarativeMeta +from sqlalchemy.orm.exc import UnmappedClassError +from sqlalchemy.orm.session import Session as SessionBase + +from .model import DefaultMeta +from .model import Model + +__version__ = "3.0.0.dev" + +_signals = Namespace() +models_committed = _signals.signal("models-committed") +before_models_committed = _signals.signal("before-models-committed") + + +def _make_table(db): + + +## ... source file abbreviated to get to StaticPool examples ... + + + if app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"]: + warnings.warn( + "'COMMIT_ON_TEARDOWN' is deprecated and will be" + " removed in version 3.1. Call" + " 'db.session.commit()'` directly instead.", + DeprecationWarning, + ) + + if response_or_exc is None: + self.session.commit() + + self.session.remove() + return response_or_exc + + def apply_driver_hacks(self, app, sa_url, options): + if sa_url.drivername.startswith("mysql"): + sa_url.query.setdefault("charset", "utf8") + if sa_url.drivername != "mysql+gaerdbms": + options.setdefault("pool_size", 10) + options.setdefault("pool_recycle", 7200) + elif sa_url.drivername == "sqlite": + pool_size = options.get("pool_size") + detected_in_memory = False + if sa_url.database in (None, "", ":memory:"): + detected_in_memory = True +~~ from sqlalchemy.pool import StaticPool + + options["poolclass"] = StaticPool + if "connect_args" not in options: + options["connect_args"] = {} + options["connect_args"]["check_same_thread"] = False + + if pool_size == 0: + raise RuntimeError( + "SQLite in memory database with an " + "empty queue not possible due to data " + "loss." + ) + elif not pool_size: + from sqlalchemy.pool import NullPool + + options["poolclass"] = NullPool + + if not detected_in_memory and not os.path.isabs(sa_url.database): + os.makedirs(app.instance_path, exist_ok=True) + sa_url.database = os.path.join(app.instance_path, sa_url.database) + + @property + def engine(self): + return self.get_engine() + + +## ... source file continues with no further StaticPool examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-schema-checkconstraint.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-schema-checkconstraint.markdown new file mode 100644 index 000000000..7f6cf9824 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-schema-checkconstraint.markdown @@ -0,0 +1,128 @@ +title: sqlalchemy.schema CheckConstraint Example Code +category: page +slug: sqlalchemy-schema-checkconstraint-examples +sortorder: 500031098 +toc: False +sidebartitle: sqlalchemy.schema CheckConstraint +meta: Example code for understanding how to use the CheckConstraint class from the sqlalchemy.schema module of the SQLAlchemy project. + + +`CheckConstraint` is a class within the `sqlalchemy.schema` module of the SQLAlchemy project. + +Column, +CreateIndex, +CreateTable, +DDLElement, +ForeignKey, +ForeignKeyConstraint, +Index, +PrimaryKeyConstraint, +and Table +are several other callables with code examples from the same `sqlalchemy.schema` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / util / sqla_compat.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/util/sqla_compat.py) + +```python +# sqla_compat.py +import re + +from sqlalchemy import __version__ +from sqlalchemy import inspect +from sqlalchemy import schema +from sqlalchemy import sql +from sqlalchemy import types as sqltypes +from sqlalchemy.ext.compiler import compiles +~~from sqlalchemy.schema import CheckConstraint +from sqlalchemy.schema import Column +from sqlalchemy.schema import ForeignKeyConstraint +from sqlalchemy.sql.elements import quoted_name +from sqlalchemy.sql.expression import _BindParamClause +from sqlalchemy.sql.expression import _TextClause as TextClause +from sqlalchemy.sql.visitors import traverse + +from . import compat + + +def _safe_int(value): + try: + return int(value) + except: + return value + + +_vers = tuple( + [_safe_int(x) for x in re.findall(r"(\d+|[abc]\d)", __version__)] +) +sqla_110 = _vers >= (1, 1, 0) +sqla_1115 = _vers >= (1, 1, 15) +sqla_120 = _vers >= (1, 2, 0) +sqla_1216 = _vers >= (1, 2, 16) + + +## ... source file abbreviated to get to CheckConstraint examples ... + + +def _exec_on_inspector(inspector, statement, **params): + if sqla_14: + with inspector._operation_context() as conn: + return conn.execute(statement, params) + else: + return inspector.bind.execute(statement, params) + + +def _server_default_is_computed(column): + if not has_computed: + return False + else: + return isinstance(column.computed, Computed) + + +def _table_for_constraint(constraint): + if isinstance(constraint, ForeignKeyConstraint): + return constraint.parent + else: + return constraint.table + + +def _columns_for_constraint(constraint): + if isinstance(constraint, ForeignKeyConstraint): + return [fk.parent for fk in constraint.elements] +~~ elif isinstance(constraint, CheckConstraint): + return _find_columns(constraint.sqltext) + else: + return list(constraint.columns) + + +def _fk_spec(constraint): + source_columns = [ + constraint.columns[key].name for key in constraint.column_keys + ] + + source_table = constraint.parent.name + source_schema = constraint.parent.schema + target_schema = constraint.elements[0].column.table.schema + target_table = constraint.elements[0].column.table.name + target_columns = [element.column.name for element in constraint.elements] + ondelete = constraint.ondelete + onupdate = constraint.onupdate + deferrable = constraint.deferrable + initially = constraint.initially + return ( + source_schema, + source_table, + source_columns, + target_schema, + + +## ... source file continues with no further CheckConstraint examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-schema-column.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-schema-column.markdown new file mode 100644 index 000000000..3a2d9d096 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-schema-column.markdown @@ -0,0 +1,352 @@ +title: sqlalchemy.schema Column Example Code +category: page +slug: sqlalchemy-schema-column-examples +sortorder: 500031099 +toc: False +sidebartitle: sqlalchemy.schema Column +meta: Example code for understanding how to use the Column class from the sqlalchemy.schema module of the SQLAlchemy project. + + +`Column` is a class within the `sqlalchemy.schema` module of the SQLAlchemy project. + +CheckConstraint, +CreateIndex, +CreateTable, +DDLElement, +ForeignKey, +ForeignKeyConstraint, +Index, +PrimaryKeyConstraint, +and Table +are several other callables with code examples from the same `sqlalchemy.schema` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / util / sqla_compat.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/util/sqla_compat.py) + +```python +# sqla_compat.py +import re + +from sqlalchemy import __version__ +from sqlalchemy import inspect +from sqlalchemy import schema +from sqlalchemy import sql +from sqlalchemy import types as sqltypes +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.schema import CheckConstraint +~~from sqlalchemy.schema import Column +from sqlalchemy.schema import ForeignKeyConstraint +from sqlalchemy.sql.elements import quoted_name +from sqlalchemy.sql.expression import _BindParamClause +from sqlalchemy.sql.expression import _TextClause as TextClause +from sqlalchemy.sql.visitors import traverse + +from . import compat + + +def _safe_int(value): + try: + return int(value) + except: + return value + + +_vers = tuple( + [_safe_int(x) for x in re.findall(r"(\d+|[abc]\d)", __version__)] +) +sqla_110 = _vers >= (1, 1, 0) +sqla_1115 = _vers >= (1, 1, 15) +sqla_120 = _vers >= (1, 2, 0) +sqla_1216 = _vers >= (1, 2, 16) +sqla_13 = _vers >= (1, 3) + + +## ... source file abbreviated to get to Column examples ... + + + tokens = spec.split(".") + tokens.pop(-1) # colname + tablekey = ".".join(tokens) + return tablekey == constraint.parent.key + + +def _is_type_bound(constraint): + return constraint._type_bound + + +def _find_columns(clause): + + cols = set() + traverse(clause, {}, {"column": cols.add}) + return cols + + +def _remove_column_from_collection(collection, column): + + to_remove = collection[column.key] + collection.remove(to_remove) + + +def _textual_index_column(table, text_): + if isinstance(text_, compat.string_types): +~~ c = Column(text_, sqltypes.NULLTYPE) + table.append_column(c) + return c + elif isinstance(text_, TextClause): + return _textual_index_element(table, text_) + else: + raise ValueError("String or text() construct expected") + + +class _textual_index_element(sql.ColumnElement): + + __visit_name__ = "_textual_idx_element" + + def __init__(self, table, text): + self.table = table + self.text = text + self.key = text.text + self.fake_column = schema.Column(self.text.text, sqltypes.NULLTYPE) + table.append_column(self.fake_column) + + def get_children(self): + return [self.fake_column] + + +@compiles(_textual_index_element) + + +## ... source file continues with no further Column examples... + +``` + + +## Example 2 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / loader.py**](https://github.com/python-gino/gino/blob/master/src/gino/./loader.py) + +```python +# loader.py +import types +import warnings + +from sqlalchemy import select +~~from sqlalchemy.schema import Column +from sqlalchemy.sql.elements import Label + +from .declarative import Model + + +class Loader: + + @classmethod + def get(cls, value): + from .crud import Alias + + if isinstance(value, Loader): + rv = value + elif isinstance(value, type) and issubclass(value, Model): + rv = ModelLoader(value) + elif isinstance(value, Alias): + rv = AliasLoader(value) +~~ elif isinstance(value, Column): + rv = ColumnLoader(value) + elif isinstance(value, Label): + rv = ColumnLoader(value.name) + elif isinstance(value, tuple): + rv = TupleLoader(value) + elif callable(value): + rv = CallableLoader(value) + else: + rv = ValueLoader(value) + return rv + + @property + def query(self): + rv = select(self.get_columns()) + from_clause = self.get_from() + if from_clause is not None: + rv = rv.select_from(from_clause) + return rv.execution_options(loader=self) + + def do_load(self, row, context): + raise NotImplementedError + + def get_columns(self): + return [] + + def get_from(self): + return None + + def __getattr__(self, item): + return getattr(self.query, item) + + +_none = object() + + +def _get_column(model, column_or_name) -> Column: + if isinstance(column_or_name, str): + return getattr(model, column_or_name) + +~~ if isinstance(column_or_name, Column): + if column_or_name in model: + return column_or_name + raise AttributeError( + "Column {} does not belong to model {}".format(column_or_name, model) + ) + + raise TypeError( + "Unknown column {} with type {}".format(column_or_name, type(column_or_name)) + ) + + +class ModelLoader(Loader): + + def __init__(self, model, *columns, **extras): + self.model = model + self._distinct = None + if columns: + self.columns = [_get_column(model, name) for name in columns] + else: + self.columns = model + self.extras = dict((key, self.get(value)) for key, value in extras.items()) + self.on_clause = None + + def _do_load(self, row): + + +## ... source file continues with no further Column examples... + +``` + + +## Example 3 from PyHive +[PyHive](https://github.com/dropbox/PyHive) +([PyPI package information](https://pypi.org/project/PyHive/)) +is a set of [DB-API](https://www.python.org/dev/peps/pep-0249/) +and +[SQLAlchemy](/sqlalchemy.html) +interfaces that make it easier to use [Presto](https://prestodb.io/) +and [Apache Hive](http://hive.apache.org/) with Python. +[Dropbox's engineering team](https://www.dropbox.com/jobs/teams/engineering) +created this code library, open sourced it and put it out under +the [Apache 2.0 license](https://github.com/dropbox/PyHive/blob/master/LICENSE). + +[**PyHive / pyhive / tests / test_sqlalchemy_hive.py**](https://github.com/dropbox/PyHive/blob/master/pyhive/tests/test_sqlalchemy_hive.py) + +```python +# test_sqlalchemy_hive.py +from __future__ import absolute_import +from __future__ import unicode_literals +from builtins import str +from pyhive.sqlalchemy_hive import HiveDate +from pyhive.sqlalchemy_hive import HiveDecimal +from pyhive.sqlalchemy_hive import HiveTimestamp +from pyhive.tests.sqlalchemy_test_case import SqlAlchemyTestCase +from pyhive.tests.sqlalchemy_test_case import with_engine_connection +from sqlalchemy import types +from sqlalchemy.engine import create_engine +~~from sqlalchemy.schema import Column +from sqlalchemy.schema import MetaData +from sqlalchemy.schema import Table +import contextlib +import datetime +import decimal +import sqlalchemy.types +import unittest + +_ONE_ROW_COMPLEX_CONTENTS = [ + True, + 127, + 32767, + 2147483647, + 9223372036854775807, + 0.5, + 0.25, + 'a string', + datetime.datetime(1970, 1, 1), + b'123', + '[1,2]', + '{1:2,3:4}', + '{"a":1,"b":2}', + '{0:1}', + decimal.Decimal('0.1'), + + +## ... source file abbreviated to get to Column examples ... + + + self.assertEqual(list(row), _ONE_ROW_COMPLEX_CONTENTS) + + self.assertIsInstance(one_row_complex.c.boolean.type, types.Boolean) + self.assertIsInstance(one_row_complex.c.tinyint.type, types.Integer) + self.assertIsInstance(one_row_complex.c.smallint.type, types.Integer) + self.assertIsInstance(one_row_complex.c.int.type, types.Integer) + self.assertIsInstance(one_row_complex.c.bigint.type, types.BigInteger) + self.assertIsInstance(one_row_complex.c.float.type, types.Float) + self.assertIsInstance(one_row_complex.c.double.type, types.Float) + self.assertIsInstance(one_row_complex.c.string.type, types.String) + self.assertIsInstance(one_row_complex.c.timestamp.type, HiveTimestamp) + self.assertIsInstance(one_row_complex.c.binary.type, types.String) + self.assertIsInstance(one_row_complex.c.array.type, types.String) + self.assertIsInstance(one_row_complex.c.map.type, types.String) + self.assertIsInstance(one_row_complex.c.struct.type, types.String) + self.assertIsInstance(one_row_complex.c.union.type, types.String) + self.assertIsInstance(one_row_complex.c.decimal.type, HiveDecimal) + + @with_engine_connection + def test_type_map(self, engine, connection): + row = connection.execute('SELECT * FROM one_row_complex').fetchone() + self.assertListEqual(list(row), _ONE_ROW_COMPLEX_CONTENTS) + + @with_engine_connection + def test_reserved_words(self, engine, connection): +~~ fake_table = Table('select', MetaData(bind=engine), Column('map', sqlalchemy.types.String)) + query = str(fake_table.select(fake_table.c.map == 'a')) + self.assertIn('`select`', query) + self.assertIn('`map`', query) + self.assertNotIn('"select"', query) + self.assertNotIn('"map"', query) + + def test_switch_database(self): + engine = create_engine('hive://localhost:10000/pyhive_test_database') + try: + with contextlib.closing(engine.connect()) as connection: + self.assertIn( + ('dummy_table',), + connection.execute('SHOW TABLES').fetchall() + ) + connection.execute('USE default') + self.assertIn( + ('one_row',), + connection.execute('SHOW TABLES').fetchall() + ) + finally: + engine.dispose() + + @with_engine_connection + def test_lots_of_types(self, engine, connection): + + +## ... source file continues with no further Column examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-schema-createindex.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-schema-createindex.markdown new file mode 100644 index 000000000..9da2134c0 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-schema-createindex.markdown @@ -0,0 +1,68 @@ +title: sqlalchemy.schema CreateIndex Example Code +category: page +slug: sqlalchemy-schema-createindex-examples +sortorder: 500031100 +toc: False +sidebartitle: sqlalchemy.schema CreateIndex +meta: Example code for understanding how to use the CreateIndex class from the sqlalchemy.schema module of the SQLAlchemy project. + + +`CreateIndex` is a class within the `sqlalchemy.schema` module of the SQLAlchemy project. + +CheckConstraint, +Column, +CreateTable, +DDLElement, +ForeignKey, +ForeignKeyConstraint, +Index, +PrimaryKeyConstraint, +and Table +are several other callables with code examples from the same `sqlalchemy.schema` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / mssql.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/mssql.py) + +```python +# mssql.py +from sqlalchemy import types as sqltypes +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.schema import Column +~~from sqlalchemy.schema import CreateIndex +from sqlalchemy.sql.expression import ClauseElement +from sqlalchemy.sql.expression import Executable + +from .base import AddColumn +from .base import alter_column +from .base import alter_table +from .base import ColumnDefault +from .base import ColumnName +from .base import ColumnNullable +from .base import ColumnType +from .base import format_column_name +from .base import format_server_default +from .base import format_table_name +from .base import format_type +from .base import RenameTable +from .impl import DefaultImpl +from .. import util + + +class MSSQLImpl(DefaultImpl): + __dialect__ = "mssql" + transactional_ddl = True + batch_separator = "GO" + + + +## ... source file continues with no further CreateIndex examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-schema-createtable.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-schema-createtable.markdown new file mode 100644 index 000000000..9b7c802d7 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-schema-createtable.markdown @@ -0,0 +1,131 @@ +title: sqlalchemy.schema CreateTable Example Code +category: page +slug: sqlalchemy-schema-createtable-examples +sortorder: 500031101 +toc: False +sidebartitle: sqlalchemy.schema CreateTable +meta: Example code for understanding how to use the CreateTable class from the sqlalchemy.schema module of the SQLAlchemy project. + + +`CreateTable` is a class within the `sqlalchemy.schema` module of the SQLAlchemy project. + +CheckConstraint, +Column, +CreateIndex, +DDLElement, +ForeignKey, +ForeignKeyConstraint, +Index, +PrimaryKeyConstraint, +and Table +are several other callables with code examples from the same `sqlalchemy.schema` package. + +## Example 1 from Amazon Redshift SQLAlchemy Dialect +[Amazon Redshift SQLAlchemy Dialect](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +that can communicate with the [AWS Redshift](https://aws.amazon.com/redshift/) +data store. The SQL is essentially [PostgreSQL](/postgresql.html) +and requires [psycopg2](https://www.psycopg.org/) to properly +operate. This project and its code are open sourced under the +[MIT license](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/LICENSE). + +[**Amazon Redshift SQLAlchemy Dialect / sqlalchemy_redshift / dialect.py**](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/sqlalchemy_redshift/./dialect.py) + +```python +# dialect.py +import re +from collections import defaultdict, namedtuple + +from packaging.version import Version +import pkg_resources +import sqlalchemy as sa +from sqlalchemy import inspect +from sqlalchemy.dialects.postgresql.base import ( + PGCompiler, PGDDLCompiler, PGIdentifierPreparer, PGTypeCompiler +) +from sqlalchemy.dialects.postgresql.psycopg2 import PGDialect_psycopg2 +from sqlalchemy.engine import reflection +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.sql.expression import ( + BinaryExpression, BooleanClauseList, Delete +) +from sqlalchemy.types import ( + VARCHAR, NullType, SMALLINT, INTEGER, BIGINT, + DECIMAL, REAL, BOOLEAN, CHAR, DATE, TIMESTAMP) +from sqlalchemy.dialects.postgresql import DOUBLE_PRECISION + +from .commands import ( + CopyCommand, UnloadFromSelect, Format, Compression, Encoding, + CreateLibraryCommand, AlterTableAppendCommand, RefreshMaterializedView +) +from .ddl import ( + CreateMaterializedView, DropMaterializedView, get_table_attributes +) + +sa_version = Version(sa.__version__) + +try: + import alembic +except ImportError: + pass + + +## ... source file abbreviated to get to CreateTable examples ... + + + \s* \) \s* # Arbitrary whitespace and literal ')' + Redshift defines a TIMTESTAMPTZ column type as an alias + of TIMESTAMP WITH TIME ZONE. + https://docs.aws.amazon.com/redshift/latest/dg/c_Supported_data_types.html + + Adding an explicit type to the RedshiftDialect allows us follow the + SqlAlchemy conventions for "vendor-specific types." + + https://docs.sqlalchemy.org/en/13/core/type_basics.html#vendor-specific-types + Structured tuple of table/view name and schema name. + Construct a new RelationKey with an explicit schema name. + Return *key* with one level of double quotes removed. + + Redshift stores some identifiers without quotes in internal tables, + even though the name must be quoted elsewhere. + In particular, this happens for tables named as a keyword. + Handles Redshift-specific ``CREATE TABLE`` syntax. + + Users can specify the `diststyle`, `distkey`, `sortkey` and `encode` + properties per table and per column. + + Table level properties can be set using the dialect specific syntax. For + example, to specify a distribution key and style you apply the following: + + >>> import sqlalchemy as sa +~~ >>> from sqlalchemy.schema import CreateTable + >>> engine = sa.create_engine('redshift+psycopg2://example') + >>> metadata = sa.MetaData() + >>> user = sa.Table( + ... 'user', + ... metadata, + ... sa.Column('id', sa.Integer, primary_key=True), + ... sa.Column('name', sa.String), + ... redshift_diststyle='KEY', + ... redshift_distkey='id', + ... redshift_interleaved_sortkey=['id', 'name'], + ... ) + >>> print(CreateTable(user).compile(engine)) + + CREATE TABLE "user" ( + id INTEGER NOT NULL, + name VARCHAR, + PRIMARY KEY (id) + ) DISTSTYLE KEY DISTKEY (id) INTERLEAVED SORTKEY (id, name) + + + + A single sort key can be applied without a wrapping list: + + >>> customer = sa.Table( + + +## ... source file continues with no further CreateTable examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-schema-ddl.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-schema-ddl.markdown new file mode 100644 index 000000000..7a5174d40 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-schema-ddl.markdown @@ -0,0 +1,146 @@ +title: sqlalchemy.schema DDL code examples +category: page +slug: sqlalchemy-schema-ddl-examples +sortorder: 500031003 +toc: False +sidebartitle: sqlalchemy.schema DDL +meta: Python example code for the DDL class from the sqlalchemy.schema module of the SQLAlchemy project. + + +DDL is a class within the sqlalchemy.schema module of the SQLAlchemy project. + + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / base.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/base.py) + +```python +# base.py +import functools + +from sqlalchemy import exc +from sqlalchemy import Integer +from sqlalchemy import types as sqltypes +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.schema import Column +~~from sqlalchemy.schema import DDLElement +from sqlalchemy.sql.elements import quoted_name + +from ..util import sqla_compat +from ..util.sqla_compat import _columns_for_constraint # noqa +from ..util.sqla_compat import _find_columns # noqa +from ..util.sqla_compat import _fk_spec # noqa +from ..util.sqla_compat import _is_type_bound # noqa +from ..util.sqla_compat import _table_for_constraint # noqa + + +~~class AlterTable(DDLElement): + + """Represent an ALTER TABLE statement. + + Only the string name and optional schema name of the table + is required, not a full Table object. + + """ + + def __init__(self, table_name, schema=None): + self.table_name = table_name + self.schema = schema + + +class RenameTable(AlterTable): + def __init__(self, old_table_name, new_table_name, schema=None): + super(RenameTable, self).__init__(old_table_name, schema=schema) + self.new_table_name = new_table_name + + +class AlterColumn(AlterTable): + def __init__( + self, + name, + column_name, + + +## ... source file continues with no further DDL examples... + + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlachemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / view.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./view.py) + +```python +# view.py +import sqlalchemy as sa +from sqlalchemy.ext import compiler +~~from sqlalchemy.schema import DDLElement, PrimaryKeyConstraint + + +~~class CreateView(DDLElement): + def __init__(self, name, selectable, materialized=False): + self.name = name + self.selectable = selectable + self.materialized = materialized + + +@compiler.compiles(CreateView) +def compile_create_materialized_view(element, compiler, **kw): + return 'CREATE {}VIEW {} AS {}'.format( + 'MATERIALIZED ' if element.materialized else '', + element.name, + compiler.sql_compiler.process(element.selectable, literal_binds=True), + ) + + +~~class DropView(DDLElement): + def __init__(self, name, materialized=False, cascade=True): + self.name = name + self.materialized = materialized + self.cascade = cascade + + +@compiler.compiles(DropView) +def compile_drop_materialized_view(element, compiler, **kw): + return 'DROP {}VIEW IF EXISTS {} {}'.format( + 'MATERIALIZED ' if element.materialized else '', + element.name, + 'CASCADE' if element.cascade else '' + ) + + +def create_table_from_selectable( + name, + selectable, + indexes=None, + metadata=None, + aliases=None +): + if indexes is None: + indexes = [] + + +## ... source file continues with no further DDL examples... + + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-schema-ddlelement.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-schema-ddlelement.markdown new file mode 100644 index 000000000..b848e2e8b --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-schema-ddlelement.markdown @@ -0,0 +1,287 @@ +title: sqlalchemy.schema DDLElement Example Code +category: page +slug: sqlalchemy-schema-ddlelement-examples +sortorder: 500031102 +toc: False +sidebartitle: sqlalchemy.schema DDLElement +meta: Example code for understanding how to use the DDLElement class from the sqlalchemy.schema module of the SQLAlchemy project. + + +`DDLElement` is a class within the `sqlalchemy.schema` module of the SQLAlchemy project. + +CheckConstraint, +Column, +CreateIndex, +CreateTable, +ForeignKey, +ForeignKeyConstraint, +Index, +PrimaryKeyConstraint, +and Table +are several other callables with code examples from the same `sqlalchemy.schema` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / base.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/base.py) + +```python +# base.py +import functools + +from sqlalchemy import exc +from sqlalchemy import Integer +from sqlalchemy import types as sqltypes +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.schema import Column +~~from sqlalchemy.schema import DDLElement +from sqlalchemy.sql.elements import quoted_name + +from ..util import sqla_compat +from ..util.sqla_compat import _columns_for_constraint # noqa +from ..util.sqla_compat import _find_columns # noqa +from ..util.sqla_compat import _fk_spec # noqa +from ..util.sqla_compat import _is_type_bound # noqa +from ..util.sqla_compat import _table_for_constraint # noqa + + +~~class AlterTable(DDLElement): + + + def __init__(self, table_name, schema=None): + self.table_name = table_name + self.schema = schema + + +class RenameTable(AlterTable): + def __init__(self, old_table_name, new_table_name, schema=None): + super(RenameTable, self).__init__(old_table_name, schema=schema) + self.new_table_name = new_table_name + + +class AlterColumn(AlterTable): + def __init__( + self, + name, + column_name, + schema=None, + existing_type=None, + existing_nullable=None, + existing_server_default=None, + existing_comment=None, + ): + + +## ... source file continues with no further DDLElement examples... + +``` + + +## Example 2 from Amazon Redshift SQLAlchemy Dialect +[Amazon Redshift SQLAlchemy Dialect](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift) +is a [SQLAlchemy Dialect](https://docs.sqlalchemy.org/en/13/dialects/) +that can communicate with the [AWS Redshift](https://aws.amazon.com/redshift/) +data store. The SQL is essentially [PostgreSQL](/postgresql.html) +and requires [psycopg2](https://www.psycopg.org/) to properly +operate. This project and its code are open sourced under the +[MIT license](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/LICENSE). + +[**Amazon Redshift SQLAlchemy Dialect / sqlalchemy_redshift / ddl.py**](https://github.com/sqlalchemy-redshift/sqlalchemy-redshift/blob/master/sqlalchemy_redshift/./ddl.py) + +```python +# ddl.py +import sqlalchemy as sa +from sqlalchemy.ext import compiler as sa_compiler +~~from sqlalchemy.schema import DDLElement + +from .compat import string_types + + +def _check_if_key_exists(key): + return isinstance(key, sa.Column) or key + + +def get_table_attributes(preparer, + diststyle=None, + distkey=None, + sortkey=None, + interleaved_sortkey=None): + text = "" + + has_distkey = _check_if_key_exists(distkey) + if diststyle: + diststyle = diststyle.upper() + if diststyle not in ('EVEN', 'KEY', 'ALL'): + raise sa.exc.ArgumentError( + u"diststyle {0} is invalid".format(diststyle) + ) + if diststyle != 'KEY' and has_distkey: + raise sa.exc.ArgumentError( + + +## ... source file abbreviated to get to DDLElement examples ... + + + text = """\ + CREATE MATERIALIZED VIEW {name} + {backup} + {table_attributes} + AS {selectable}\ + Drop the materialized view from the database. + SEE: + docs.aws.amazon.com/redshift/latest/dg/materialized-view-drop-sql-command + + This undoes the create command, as expected: + + >>> import sqlalchemy as sa + >>> from sqlalchemy_redshift.dialect import DropMaterializedView + >>> engine = sa.create_engine('redshift+psycopg2://example') + >>> drop = DropMaterializedView( + ... 'materialized_view_of_users', + ... if_exists=True + ... ) + >>> print(drop.compile(engine)) + + DROP MATERIALIZED VIEW IF EXISTS materialized_view_of_users + + + + This can be included in any execute() statement. +~~ Build the DropMaterializedView DDLElement. + + Parameters + ---------- + name: str + name of the materialized view to drop + if_exists: bool, optional + if True, the IF EXISTS clause is added. This will make the query + successful even if the view does not exist, i.e. it lets you drop + a non-existant view. Defaults to False. + cascade: bool, optional + if True, the CASCADE clause is added. This will drop all + views/objects in the DB that depend on this materialized view. + Defaults to False. + Formats and returns the drop statement for materialized views. + + distkey = distkey.name + text += " DISTKEY ({0})".format(preparer.quote(distkey)) + + has_sortkey = _check_if_key_exists(sortkey) + has_interleaved = _check_if_key_exists(interleaved_sortkey) + if has_sortkey and has_interleaved: + raise sa.exc.ArgumentError( + "Parameters sortkey and interleaved_sortkey are " + "mutually exclusive; you may not specify both." + ) + + if has_sortkey or has_interleaved: + keys = sortkey if has_sortkey else interleaved_sortkey + if isinstance(keys, (string_types, sa.Column)): + keys = [keys] + keys = [key.name if isinstance(key, sa.Column) else key + for key in keys] + if has_interleaved: + text += " INTERLEAVED" + sortkey_string = ", ".join(preparer.quote(key) + for key in keys) + text += " SORTKEY ({0})".format(sortkey_string) + return text + + +~~class CreateMaterializedView(DDLElement): + def __init__(self, name, selectable, backup=True, diststyle=None, + distkey=None, sortkey=None, interleaved_sortkey=None): + self.name = name + self.selectable = selectable + self.backup = backup + self.diststyle = diststyle + self.distkey = distkey + self.sortkey = sortkey + self.interleaved_sortkey = interleaved_sortkey + + +@sa_compiler.compiles(CreateMaterializedView) +def compile_create_materialized_view(element, compiler, **kw): + + + +## ... source file continues with no further DDLElement examples... + +``` + + +## Example 3 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / view.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./view.py) + +```python +# view.py +import sqlalchemy as sa +from sqlalchemy.ext import compiler +~~from sqlalchemy.schema import DDLElement, PrimaryKeyConstraint + + +~~class CreateView(DDLElement): + def __init__(self, name, selectable, materialized=False): + self.name = name + self.selectable = selectable + self.materialized = materialized + + +@compiler.compiles(CreateView) +def compile_create_materialized_view(element, compiler, **kw): + return 'CREATE {}VIEW {} AS {}'.format( + 'MATERIALIZED ' if element.materialized else '', + element.name, + compiler.sql_compiler.process(element.selectable, literal_binds=True), + ) + + +~~class DropView(DDLElement): + def __init__(self, name, materialized=False, cascade=True): + self.name = name + self.materialized = materialized + self.cascade = cascade + + +@compiler.compiles(DropView) +def compile_drop_materialized_view(element, compiler, **kw): + return 'DROP {}VIEW IF EXISTS {} {}'.format( + 'MATERIALIZED ' if element.materialized else '', + element.name, + 'CASCADE' if element.cascade else '' + ) + + +def create_table_from_selectable( + name, + selectable, + indexes=None, + metadata=None, + aliases=None +): + if indexes is None: + indexes = [] + + +## ... source file continues with no further DDLElement examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-schema-foreignkey.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-schema-foreignkey.markdown new file mode 100644 index 000000000..da732a5cc --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-schema-foreignkey.markdown @@ -0,0 +1,138 @@ +title: sqlalchemy.schema ForeignKey Example Code +category: page +slug: sqlalchemy-schema-foreignkey-examples +sortorder: 500031103 +toc: False +sidebartitle: sqlalchemy.schema ForeignKey +meta: Example code for understanding how to use the ForeignKey class from the sqlalchemy.schema module of the SQLAlchemy project. + + +`ForeignKey` is a class within the `sqlalchemy.schema` module of the SQLAlchemy project. + +CheckConstraint, +Column, +CreateIndex, +CreateTable, +DDLElement, +ForeignKeyConstraint, +Index, +PrimaryKeyConstraint, +and Table +are several other callables with code examples from the same `sqlalchemy.schema` package. + +## Example 1 from sqlacodegen +[sqlacodegen](https://github.com/agronholm/sqlacodegen) +([PyPI package information](https://pypi.org/project/sqlacodegen/)) +is a tool for +reading from an existing [relational database](/databases.html) to +generate code to create [SQLAlchemy](/sqlalchemy.html) models based +on that database. The project is primarily written and maintained +by [Alex Grönholm (agronholm)](https://github.com/agronholm) and it +is open sourced under the +[MIT license](https://github.com/agronholm/sqlacodegen/blob/master/LICENSE). + +[**sqlacodegen / sqlacodegen / codegen.py**](https://github.com/agronholm/sqlacodegen/blob/master/sqlacodegen/./codegen.py) + +```python +# codegen.py +from __future__ import unicode_literals, division, print_function, absolute_import + +import inspect +import re +import sys +from collections import defaultdict +from importlib import import_module +from inspect import ArgSpec +from keyword import iskeyword + +import sqlalchemy +import sqlalchemy.exc +from sqlalchemy import ( + Enum, ForeignKeyConstraint, PrimaryKeyConstraint, CheckConstraint, UniqueConstraint, Table, + Column, Float) +~~from sqlalchemy.schema import ForeignKey +from sqlalchemy.sql.sqltypes import NullType +from sqlalchemy.types import Boolean, String +from sqlalchemy.util import OrderedDict + +try: + from sqlalchemy import ARRAY +except ImportError: + from sqlalchemy.dialects.postgresql import ARRAY + +try: + from sqlalchemy import Computed +except ImportError: + Computed = None + +try: + import geoalchemy2 # noqa: F401 +except ImportError: + pass + +_re_boolean_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \(0, 1\)") +_re_column_name = re.compile(r'(?:(["`]?)(?:.*)\1\.)?(["`]?)(.*)\2') +_re_enum_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \((.+)\)") +_re_enum_item = re.compile(r"'(.*?)(?CheckConstraint, +Column, +CreateIndex, +CreateTable, +DDLElement, +ForeignKey, +Index, +PrimaryKeyConstraint, +and Table +are several other callables with code examples from the same `sqlalchemy.schema` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / util / sqla_compat.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/util/sqla_compat.py) + +```python +# sqla_compat.py +import re + +from sqlalchemy import __version__ +from sqlalchemy import inspect +from sqlalchemy import schema +from sqlalchemy import sql +from sqlalchemy import types as sqltypes +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.schema import CheckConstraint +from sqlalchemy.schema import Column +~~from sqlalchemy.schema import ForeignKeyConstraint +from sqlalchemy.sql.elements import quoted_name +from sqlalchemy.sql.expression import _BindParamClause +from sqlalchemy.sql.expression import _TextClause as TextClause +from sqlalchemy.sql.visitors import traverse + +from . import compat + + +def _safe_int(value): + try: + return int(value) + except: + return value + + +_vers = tuple( + [_safe_int(x) for x in re.findall(r"(\d+|[abc]\d)", __version__)] +) +sqla_110 = _vers >= (1, 1, 0) +sqla_1115 = _vers >= (1, 1, 15) +sqla_120 = _vers >= (1, 2, 0) +sqla_1216 = _vers >= (1, 2, 16) +sqla_13 = _vers >= (1, 3) +sqla_14 = _vers >= (1, 4) + + +## ... source file abbreviated to get to ForeignKeyConstraint examples ... + + +def _connectable_has_table(connectable, tablename, schemaname): + if sqla_14: + return inspect(connectable).has_table(tablename, schemaname) + else: + return connectable.dialect.has_table( + connectable, tablename, schemaname + ) + + +def _exec_on_inspector(inspector, statement, **params): + if sqla_14: + with inspector._operation_context() as conn: + return conn.execute(statement, params) + else: + return inspector.bind.execute(statement, params) + + +def _server_default_is_computed(column): + if not has_computed: + return False + else: + return isinstance(column.computed, Computed) + + +def _table_for_constraint(constraint): +~~ if isinstance(constraint, ForeignKeyConstraint): + return constraint.parent + else: + return constraint.table + + +def _columns_for_constraint(constraint): +~~ if isinstance(constraint, ForeignKeyConstraint): + return [fk.parent for fk in constraint.elements] + elif isinstance(constraint, CheckConstraint): + return _find_columns(constraint.sqltext) + else: + return list(constraint.columns) + + +def _fk_spec(constraint): + source_columns = [ + constraint.columns[key].name for key in constraint.column_keys + ] + + source_table = constraint.parent.name + source_schema = constraint.parent.schema + target_schema = constraint.elements[0].column.table.schema + target_table = constraint.elements[0].column.table.name + target_columns = [element.column.name for element in constraint.elements] + ondelete = constraint.ondelete + onupdate = constraint.onupdate + deferrable = constraint.deferrable + initially = constraint.initially + return ( + source_schema, + source_table, + + +## ... source file continues with no further ForeignKeyConstraint examples... + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / foreign_keys.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/foreign_keys.py) + +```python +# foreign_keys.py +from collections import defaultdict +from itertools import groupby + +import sqlalchemy as sa +from sqlalchemy.exc import NoInspectionAvailable +from sqlalchemy.orm import object_session +~~from sqlalchemy.schema import ForeignKeyConstraint, MetaData, Table + +from ..query_chain import QueryChain +from .database import has_index +from .orm import get_column_key, get_mapper, get_tables + + +def get_foreign_key_values(fk, obj): + return dict( + ( + fk.constraint.columns.values()[index].key, + getattr(obj, element.column.key) + ) + for + index, element + in + enumerate(fk.constraint.elements) + ) + + +def group_foreign_keys(foreign_keys): + foreign_keys = sorted( + foreign_keys, key=lambda key: key.constraint.table.name + ) + return groupby(foreign_keys, lambda key: key.constraint.table) + + +## ... source file abbreviated to get to ForeignKeyConstraint examples ... + + + ) + criteria.append(sa.and_(*subcriteria)) + return criteria + + +def non_indexed_foreign_keys(metadata, engine=None): + reflected_metadata = MetaData() + + if metadata.bind is None and engine is None: + raise Exception( + 'Either pass a metadata object with bind or ' + 'pass engine as a second parameter' + ) + + constraints = defaultdict(list) + + for table_name in metadata.tables.keys(): + table = Table( + table_name, + reflected_metadata, + autoload=True, + autoload_with=metadata.bind or engine + ) + + for constraint in table.constraints: +~~ if not isinstance(constraint, ForeignKeyConstraint): + continue + + if not has_index(constraint): + constraints[table.name].append(constraint) + + return dict(constraints) + + +def get_fk_constraint_for_columns(table, *columns): + for constraint in table.constraints: + if list(constraint.columns.values()) == list(columns): + return constraint + + + +## ... source file continues with no further ForeignKeyConstraint examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-schema-index.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-schema-index.markdown new file mode 100644 index 000000000..b7807b814 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-schema-index.markdown @@ -0,0 +1,81 @@ +title: sqlalchemy.schema Index Example Code +category: page +slug: sqlalchemy-schema-index-examples +sortorder: 500031105 +toc: False +sidebartitle: sqlalchemy.schema Index +meta: Example code for understanding how to use the Index class from the sqlalchemy.schema module of the SQLAlchemy project. + + +`Index` is a class within the `sqlalchemy.schema` module of the SQLAlchemy project. + +CheckConstraint, +Column, +CreateIndex, +CreateTable, +DDLElement, +ForeignKey, +ForeignKeyConstraint, +PrimaryKeyConstraint, +and Table +are several other callables with code examples from the same `sqlalchemy.schema` package. + +## Example 1 from PyHive +[PyHive](https://github.com/dropbox/PyHive) +([PyPI package information](https://pypi.org/project/PyHive/)) +is a set of [DB-API](https://www.python.org/dev/peps/pep-0249/) +and +[SQLAlchemy](/sqlalchemy.html) +interfaces that make it easier to use [Presto](https://prestodb.io/) +and [Apache Hive](http://hive.apache.org/) with Python. +[Dropbox's engineering team](https://www.dropbox.com/jobs/teams/engineering) +created this code library, open sourced it and put it out under +the [Apache 2.0 license](https://github.com/dropbox/PyHive/blob/master/LICENSE). + +[**PyHive / pyhive / tests / sqlalchemy_test_case.py**](https://github.com/dropbox/PyHive/blob/master/pyhive/tests/sqlalchemy_test_case.py) + +```python +# sqlalchemy_test_case.py +from __future__ import absolute_import +from __future__ import unicode_literals + +import abc +import contextlib +import functools + +import pytest +import sqlalchemy +from builtins import object +from future.utils import with_metaclass +from sqlalchemy.exc import NoSuchTableError +~~from sqlalchemy.schema import Index +from sqlalchemy.schema import MetaData +from sqlalchemy.schema import Table +from sqlalchemy.sql import expression + + +def with_engine_connection(fn): + @functools.wraps(fn) + def wrapped_fn(self, *args, **kwargs): + engine = self.create_engine() + try: + with contextlib.closing(engine.connect()) as connection: + fn(self, engine, connection, *args, **kwargs) + finally: + engine.dispose() + return wrapped_fn + + +class SqlAlchemyTestCase(with_metaclass(abc.ABCMeta, object)): + @with_engine_connection + def test_basic_query(self, engine, connection): + rows = connection.execute('SELECT * FROM one_row').fetchall() + self.assertEqual(len(rows), 1) + self.assertEqual(rows[0].number_of_rows, 1) # number_of_rows is the column name + self.assertEqual(len(rows[0]), 1) + + +## ... source file continues with no further Index examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-schema-primarykeyconstraint.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-schema-primarykeyconstraint.markdown new file mode 100644 index 000000000..99ddc1e37 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-schema-primarykeyconstraint.markdown @@ -0,0 +1,128 @@ +title: sqlalchemy.schema PrimaryKeyConstraint Example Code +category: page +slug: sqlalchemy-schema-primarykeyconstraint-examples +sortorder: 500031106 +toc: False +sidebartitle: sqlalchemy.schema PrimaryKeyConstraint +meta: Example code for understanding how to use the PrimaryKeyConstraint class from the sqlalchemy.schema module of the SQLAlchemy project. + + +`PrimaryKeyConstraint` is a class within the `sqlalchemy.schema` module of the SQLAlchemy project. + +CheckConstraint, +Column, +CreateIndex, +CreateTable, +DDLElement, +ForeignKey, +ForeignKeyConstraint, +Index, +and Table +are several other callables with code examples from the same `sqlalchemy.schema` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / view.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./view.py) + +```python +# view.py +import sqlalchemy as sa +from sqlalchemy.ext import compiler +~~from sqlalchemy.schema import DDLElement, PrimaryKeyConstraint + + +class CreateView(DDLElement): + def __init__(self, name, selectable, materialized=False): + self.name = name + self.selectable = selectable + self.materialized = materialized + + +@compiler.compiles(CreateView) +def compile_create_materialized_view(element, compiler, **kw): + return 'CREATE {}VIEW {} AS {}'.format( + 'MATERIALIZED ' if element.materialized else '', + element.name, + compiler.sql_compiler.process(element.selectable, literal_binds=True), + ) + + +class DropView(DDLElement): + def __init__(self, name, materialized=False, cascade=True): + self.name = name + self.materialized = materialized + self.cascade = cascade + + + +## ... source file abbreviated to get to PrimaryKeyConstraint examples ... + + + name, + selectable, + indexes=None, + metadata=None, + aliases=None +): + if indexes is None: + indexes = [] + if metadata is None: + metadata = sa.MetaData() + if aliases is None: + aliases = {} + args = [ + sa.Column( + c.name, + c.type, + key=aliases.get(c.name, c.name), + primary_key=c.primary_key + ) + for c in selectable.c + ] + indexes + table = sa.Table(name, metadata, *args) + + if not any([c.primary_key for c in selectable.c]): + table.append_constraint( +~~ PrimaryKeyConstraint(*[c.name for c in selectable.c]) + ) + return table + + +def create_materialized_view( + name, + selectable, + metadata, + indexes=None, + aliases=None +): + table = create_table_from_selectable( + name=name, + selectable=selectable, + indexes=indexes, + metadata=None, + aliases=aliases + ) + + sa.event.listen( + metadata, + 'after_create', + CreateView(name, selectable, materialized=True) + ) + + +## ... source file continues with no further PrimaryKeyConstraint examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-schema-table.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-schema-table.markdown new file mode 100644 index 000000000..8640cb326 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-schema-table.markdown @@ -0,0 +1,305 @@ +title: sqlalchemy.schema Table Example Code +category: page +slug: sqlalchemy-schema-table-examples +sortorder: 500031107 +toc: False +sidebartitle: sqlalchemy.schema Table +meta: Example code for understanding how to use the Table class from the sqlalchemy.schema module of the SQLAlchemy project. + + +Table is a class within the sqlalchemy.schema module of the SQLAlchemy project. + +CheckConstraint, +Column, +CreateIndex, +CreateTable, +DDLElement, +ForeignKey, +ForeignKeyConstraint, +Index, +and PrimaryKeyConstraint +are several other callables with code examples from the same `sqlalchemy.schema` package. + +## Example 1 from PyHive +[PyHive](https://github.com/dropbox/PyHive) +([PyPI package information](https://pypi.org/project/PyHive/)) +is a set of [DB-API](https://www.python.org/dev/peps/pep-0249/) +and +[SQLAlchemy](/sqlalchemy.html) +interfaces that make it easier to use [Presto](https://prestodb.io/) +and [Apache Hive](http://hive.apache.org/) with Python. +[Dropbox's engineering team](https://www.dropbox.com/jobs/teams/engineering) +created this code library, open sourced it and put it out under +the [Apache 2.0 license](https://github.com/dropbox/PyHive/blob/master/LICENSE). + +[**PyHive / pyhive / tests / test_sqlalchemy_hive.py**](https://github.com/dropbox/PyHive/blob/master/pyhive/tests/test_sqlalchemy_hive.py) + +```python +# test_sqlalchemy_hive.py +from __future__ import absolute_import +from __future__ import unicode_literals +from builtins import str +from pyhive.sqlalchemy_hive import HiveDate +from pyhive.sqlalchemy_hive import HiveDecimal +from pyhive.sqlalchemy_hive import HiveTimestamp +from pyhive.tests.sqlalchemy_test_case import SqlAlchemyTestCase +from pyhive.tests.sqlalchemy_test_case import with_engine_connection +from sqlalchemy import types +from sqlalchemy.engine import create_engine +from sqlalchemy.schema import Column +from sqlalchemy.schema import MetaData +~~from sqlalchemy.schema import Table +import contextlib +import datetime +import decimal +import sqlalchemy.types +import unittest + +_ONE_ROW_COMPLEX_CONTENTS = [ + True, + 127, + 32767, + 2147483647, + 9223372036854775807, + 0.5, + 0.25, + 'a string', + datetime.datetime(1970, 1, 1), + b'123', + '[1,2]', + '{1:2,3:4}', + '{"a":1,"b":2}', + '{0:1}', + decimal.Decimal('0.1'), +] + + + +## ... source file abbreviated to get to Table examples ... + + +class TestSqlAlchemyHive(unittest.TestCase, SqlAlchemyTestCase): + def create_engine(self): + return create_engine('hive://localhost:10000/default') + + @with_engine_connection + def test_dotted_column_names(self, engine, connection): + row = connection.execute('SELECT * FROM one_row').fetchone() + assert row.keys() == ['number_of_rows'] + assert 'number_of_rows' in row + assert row.number_of_rows == 1 + assert row['number_of_rows'] == 1 + assert getattr(row, 'one_row.number_of_rows') == 1 + assert row['one_row.number_of_rows'] == 1 + + @with_engine_connection + def test_dotted_column_names_raw(self, engine, connection): + row = connection.execution_options(hive_raw_colnames=True) \ + .execute('SELECT * FROM one_row').fetchone() + assert row.keys() == ['one_row.number_of_rows'] + assert 'number_of_rows' not in row + assert getattr(row, 'one_row.number_of_rows') == 1 + assert row['one_row.number_of_rows'] == 1 + + @with_engine_connection + def test_reflect_select(self, engine, connection): +~~ one_row_complex = Table('one_row_complex', MetaData(bind=engine), autoload=True) + self.assertEqual(len(one_row_complex.c), 15) + self.assertIsInstance(one_row_complex.c.string, Column) + row = one_row_complex.select().execute().fetchone() + self.assertEqual(list(row), _ONE_ROW_COMPLEX_CONTENTS) + + self.assertIsInstance(one_row_complex.c.boolean.type, types.Boolean) + self.assertIsInstance(one_row_complex.c.tinyint.type, types.Integer) + self.assertIsInstance(one_row_complex.c.smallint.type, types.Integer) + self.assertIsInstance(one_row_complex.c.int.type, types.Integer) + self.assertIsInstance(one_row_complex.c.bigint.type, types.BigInteger) + self.assertIsInstance(one_row_complex.c.float.type, types.Float) + self.assertIsInstance(one_row_complex.c.double.type, types.Float) + self.assertIsInstance(one_row_complex.c.string.type, types.String) + self.assertIsInstance(one_row_complex.c.timestamp.type, HiveTimestamp) + self.assertIsInstance(one_row_complex.c.binary.type, types.String) + self.assertIsInstance(one_row_complex.c.array.type, types.String) + self.assertIsInstance(one_row_complex.c.map.type, types.String) + self.assertIsInstance(one_row_complex.c.struct.type, types.String) + self.assertIsInstance(one_row_complex.c.union.type, types.String) + self.assertIsInstance(one_row_complex.c.decimal.type, HiveDecimal) + + @with_engine_connection + def test_type_map(self, engine, connection): + row = connection.execute('SELECT * FROM one_row_complex').fetchone() + self.assertListEqual(list(row), _ONE_ROW_COMPLEX_CONTENTS) + + @with_engine_connection + def test_reserved_words(self, engine, connection): +~~ fake_table = Table('select', MetaData(bind=engine), Column('map', sqlalchemy.types.String)) + query = str(fake_table.select(fake_table.c.map == 'a')) + self.assertIn('`select`', query) + self.assertIn('`map`', query) + self.assertNotIn('"select"', query) + self.assertNotIn('"map"', query) + + def test_switch_database(self): + engine = create_engine('hive://localhost:10000/pyhive_test_database') + try: + with contextlib.closing(engine.connect()) as connection: + self.assertIn( + ('dummy_table',), + connection.execute('SHOW TABLES').fetchall() + ) + connection.execute('USE default') + self.assertIn( + ('one_row',), + connection.execute('SHOW TABLES').fetchall() + ) + finally: + engine.dispose() + + @with_engine_connection + def test_lots_of_types(self, engine, connection): + types = [ + 'INT', 'CHAR', 'VARCHAR', 'NCHAR', 'TEXT', 'Text', 'FLOAT', + 'NUMERIC', 'DECIMAL', 'TIMESTAMP', 'DATETIME', 'CLOB', 'BLOB', + 'BOOLEAN', 'SMALLINT', 'DATE', 'TIME', + 'String', 'Integer', 'SmallInteger', + 'Numeric', 'Float', 'DateTime', 'Date', 'Time', 'LargeBinary', + 'Boolean', 'Unicode', 'UnicodeText', + ] + cols = [] + for i, t in enumerate(types): + cols.append(Column(str(i), getattr(sqlalchemy.types, t))) + cols.append(Column('hive_date', HiveDate)) + cols.append(Column('hive_decimal', HiveDecimal)) + cols.append(Column('hive_timestamp', HiveTimestamp)) +~~ table = Table('test_table', MetaData(bind=engine), *cols, schema='pyhive_test_database') + table.drop(checkfirst=True) + table.create() + connection.execute('SET mapred.job.tracker=local') + connection.execute('USE pyhive_test_database') + big_number = 10 ** 10 - 1 + connection.execute(""" + INSERT OVERWRITE TABLE test_table + SELECT + 1, "a", "a", "a", "a", "a", 0.1, + 0.1, 0.1, 0, 0, "a", "a", + false, 1, 0, 0, + "a", 1, 1, + 0.1, 0.1, 0, 0, 0, "a", + false, "a", "a", + 0, %d, 123 + 2000 + FROM default.one_row + + + +## ... source file continues with no further Table examples... + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / functions / foreign_keys.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/foreign_keys.py) + +```python +# foreign_keys.py +from collections import defaultdict +from itertools import groupby + +import sqlalchemy as sa +from sqlalchemy.exc import NoInspectionAvailable +from sqlalchemy.orm import object_session +~~from sqlalchemy.schema import ForeignKeyConstraint, MetaData, Table + +from ..query_chain import QueryChain +from .database import has_index +from .orm import get_column_key, get_mapper, get_tables + + +def get_foreign_key_values(fk, obj): + return dict( + ( + fk.constraint.columns.values()[index].key, + getattr(obj, element.column.key) + ) + for + index, element + in + enumerate(fk.constraint.elements) + ) + + +def group_foreign_keys(foreign_keys): + foreign_keys = sorted( + foreign_keys, key=lambda key: key.constraint.table.name + ) + return groupby(foreign_keys, lambda key: key.constraint.table) + + +## ... source file abbreviated to get to Table examples ... + + + getattr(class_, get_column_key(class_, column)) == + getattr( + obj, + sa.inspect(type(obj)) + .get_property_by_column( + foreign_column + ).key + ) + ) + criteria.append(sa.and_(*subcriteria)) + return criteria + + +def non_indexed_foreign_keys(metadata, engine=None): + reflected_metadata = MetaData() + + if metadata.bind is None and engine is None: + raise Exception( + 'Either pass a metadata object with bind or ' + 'pass engine as a second parameter' + ) + + constraints = defaultdict(list) + + for table_name in metadata.tables.keys(): +~~ table = Table( + table_name, + reflected_metadata, + autoload=True, + autoload_with=metadata.bind or engine + ) + + for constraint in table.constraints: + if not isinstance(constraint, ForeignKeyConstraint): + continue + + if not has_index(constraint): + constraints[table.name].append(constraint) + + return dict(constraints) + + +def get_fk_constraint_for_columns(table, *columns): + for constraint in table.constraints: + if list(constraint.columns.values()) == list(columns): + return constraint + + + +## ... source file continues with no further Table examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-clauseelement.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-clauseelement.markdown new file mode 100644 index 000000000..cfcb294f2 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-clauseelement.markdown @@ -0,0 +1,260 @@ +title: sqlalchemy.sql ClauseElement Example Code +category: page +slug: sqlalchemy-sql-clauseelement-examples +sortorder: 500031108 +toc: False +sidebartitle: sqlalchemy.sql ClauseElement +meta: Example code for understanding how to use the ClauseElement class from the sqlalchemy.sql module of the SQLAlchemy project. + + +`ClauseElement` is a class within the `sqlalchemy.sql` module of the SQLAlchemy project. + +Select, +column, +expression, +extract, +functions, +operators, +schema, +select, +sqltypes, +and table +are several other callables with code examples from the same `sqlalchemy.sql` package. + +## Example 1 from databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + +[**databases / databases / interfaces.py**](https://github.com/encode/databases/blob/master/databases/./interfaces.py) + +```python +# interfaces.py +import typing + +~~from sqlalchemy.sql import ClauseElement + + +class DatabaseBackend: + async def connect(self) -> None: + raise NotImplementedError() # pragma: no cover + + async def disconnect(self) -> None: + raise NotImplementedError() # pragma: no cover + + def connection(self) -> "ConnectionBackend": + raise NotImplementedError() # pragma: no cover + + +class ConnectionBackend: + async def acquire(self) -> None: + raise NotImplementedError() # pragma: no cover + + async def release(self) -> None: + raise NotImplementedError() # pragma: no cover + + async def fetch_all(self, query: ClauseElement) -> typing.List[typing.Mapping]: + raise NotImplementedError() # pragma: no cover + + async def fetch_one(self, query: ClauseElement) -> typing.Optional[typing.Mapping]: + + +## ... source file continues with no further ClauseElement examples... + +``` + + +## Example 2 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / crud.py**](https://github.com/python-gino/gino/blob/master/src/gino/./crud.py) + +```python +# crud.py +import inspect +import itertools +import weakref + +import sqlalchemy as sa +~~from sqlalchemy.sql import ClauseElement + +from . import json_support +from .declarative import Model, InvertDict +from .exceptions import NoSuchRowError +from .loader import AliasLoader, ModelLoader + +DEFAULT = object() + + +class _Create: + def __get__(self, instance, owner): + if instance is None: + return owner._create_without_instance + else: + return instance._create + + +class _Query: + def __get__(self, instance, owner): + owner._check_abstract() + q = sa.select([owner.__table__]) + if instance is not None: + q = q.where(instance.lookup()) + return q.execution_options(model=weakref.ref(owner)) + + +## ... source file abbreviated to get to ClauseElement examples ... + + + owner._check_abstract() + q = owner.__table__.delete() + return q.execution_options(model=weakref.ref(owner)) + else: + return instance._delete + + +class UpdateRequest: + + def __init__(self, instance: "CRUDModel"): + self._instance = instance + self._values = {} + self._props = {} + self._literal = True + self._locator = None + if instance.__table__ is not None: + try: + self._locator = instance.lookup() + except LookupError: + pass + + def _set(self, key, value): + self._values[key] = value + + def _set_prop(self, prop, value): +~~ if isinstance(value, ClauseElement): + self._literal = False + self._props[prop] = value + + async def apply(self, bind=None, timeout=DEFAULT): + if self._locator is None: + raise TypeError( + "Model {} has no table, primary key or custom lookup()".format( + self._instance.__class__.__name__ + ) + ) + cls = type(self._instance) + values = self._values.copy() + + json_updates = {} + for prop, value in self._props.items(): + value = prop.save(self._instance, value) + updates = json_updates.setdefault(prop.prop_name, {}) + if self._literal: + updates[prop.name] = value + else: + if isinstance(value, int): + value = sa.cast(value, sa.BigInteger) +~~ elif not isinstance(value, ClauseElement): + value = sa.cast(value, sa.Unicode) + updates[sa.cast(prop.name, sa.Unicode)] = value + for prop_name, updates in json_updates.items(): + prop = getattr(cls, prop_name) + from .dialects.asyncpg import JSONB + + if isinstance(prop.type, JSONB): + if self._literal: + values[prop_name] = prop.concat(updates) + else: + values[prop_name] = prop.concat( + sa.func.jsonb_build_object(*itertools.chain(*updates.items())) + ) + else: + raise TypeError( + "{} is not supported to update json " + "properties in Gino. Please consider using " + "JSONB.".format(prop.type) + ) + + opts = dict(return_model=False) + if timeout is not DEFAULT: + opts["timeout"] = timeout + clause = ( + + +## ... source file abbreviated to get to ClauseElement examples ... + + + ) + if bind is None: + bind = cls.__metadata__.bind + row = await bind.first(clause) + if not row: + raise NoSuchRowError() + for k, v in row.items(): + self._instance.__values__[self._instance._column_name_map.invert_get(k)] = v + for prop in self._props: + prop.reload(self._instance) + return self + + def update(self, **values): + + cls = type(self._instance) + for key, value in values.items(): + prop = cls.__dict__.get(key) + if isinstance(prop, json_support.JSONProperty): + value_from = "__profile__" + method = self._set_prop + k = prop + else: + value_from = "__values__" + method = self._set + k = key +~~ if not isinstance(value, ClauseElement): + setattr(self._instance, key, value) + value = getattr(self._instance, value_from)[key] + method(k, value) + return self + + +class Alias: + + def __init__(self, model, *args, **kwargs): + model._check_abstract() + self.model = model + self.alias = model.__table__.alias(*args, **kwargs) + + def __getattr__(self, item): + rv = getattr( + self.alias.columns, + item, + getattr(self.alias, item, getattr(self.model, item, DEFAULT)), + ) + if rv is DEFAULT: + raise AttributeError + return rv + + def __iter__(self): + + +## ... source file continues with no further ClauseElement examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-column.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-column.markdown new file mode 100644 index 000000000..4f9f90aff --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-column.markdown @@ -0,0 +1,218 @@ +title: sqlalchemy.sql column Example Code +category: page +slug: sqlalchemy-sql-column-examples +sortorder: 500031109 +toc: False +sidebartitle: sqlalchemy.sql column +meta: Python example code that shows how to use the column callable from the sqlalchemy.sql module of the SQLAlchemy project. + + +`column` is a callable within the `sqlalchemy.sql` module of the SQLAlchemy project. + +ClauseElement, +Select, +expression, +extract, +functions, +operators, +schema, +select, +sqltypes, +and table +are several other callables with code examples from the same `sqlalchemy.sql` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / operations / ops.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/operations/ops.py) + +```python +# ops.py +import re + +from sqlalchemy.types import NULLTYPE + +from . import schemaobj +from .base import BatchOperations +from .base import Operations +from .. import util +from ..util import sqla_compat + + +class MigrateOperation(object): + + @util.memoized_property + def info(self): + return {} + + _mutations = frozenset() + + +class AddConstraintOp(MigrateOperation): + + add_constraint_ops = util.Dispatcher() + + @property + def constraint_type(self): + raise NotImplementedError() + + @classmethod + def register_add_constraint(cls, type_): + def go(klass): + cls.add_constraint_ops.dispatch_for(type_)(klass.from_constraint) + return klass + + return go + + +## ... source file abbreviated to get to column examples ... + + + @classmethod + def bulk_insert(cls, operations, table, rows, multiinsert=True): + + op = cls(table, rows, multiinsert=multiinsert) + operations.invoke(op) + + +@Operations.register_operation("execute") +class ExecuteSQLOp(MigrateOperation): + + def __init__(self, sqltext, execution_options=None): + self.sqltext = sqltext + self.execution_options = execution_options + + @classmethod + def execute(cls, operations, sqltext, execution_options=None): + r"""Execute the given SQL using the current migration context. + + The given SQL can be a plain string, e.g.:: + + op.execute("INSERT INTO table (foo) VALUES ('some value')") + + Or it can be any kind of Core SQL Expression construct, such as + below where we use an update construct:: + +~~ from sqlalchemy.sql import table, column + from sqlalchemy import String + from alembic import op + + account = table('account', +~~ column('name', String) + ) + op.execute( + account.update().\\ + where(account.c.name==op.inline_literal('account 1')).\\ + values({'name':op.inline_literal('account 2')}) + ) + + Above, we made use of the SQLAlchemy + :func:`sqlalchemy.sql.expression.table` and + :func:`sqlalchemy.sql.expression.column` constructs to make a brief, + ad-hoc table construct just for our UPDATE statement. A full + :class:`-sqlalchemy.schema.Table` construct of course works perfectly + fine as well, though note it's a recommended practice to at least + ensure the definition of a table is self-contained within the migration + script, rather than imported from a module that may break compatibility + with older migrations. + + In a SQL script context, the statement is emitted directly to the + output stream. There is *no* return result, however, as this + function is oriented towards generating a change script + that can run in "offline" mode. Additionally, parameterized + statements are discouraged here, as they *will not work* in offline + mode. Above, we use :meth:`.inline_literal` where parameters are + to be used. + When producing MySQL-compatible migration files, + it is recommended that the ``existing_type``, + ``existing_server_default``, and ``existing_nullable`` + parameters be present, if not being altered. + + Type changes which are against the SQLAlchemy + "schema" types :class:`-sqlalchemy.types.Boolean` + and :class:`-sqlalchemy.types.Enum` may also + add or drop constraints which accompany those + types on backends that don't support them natively. + The ``existing_type`` argument is + used in this case to identify and remove a previous + constraint that was bound to the type object. + + :param table_name: string name of the target table. + :param column_name: string name of the target column, + as it exists before the operation begins. + :param nullable: Optional; specify ``True`` or ``False`` + to alter the column's nullability. + :param server_default: Optional; specify a string + SQL expression, :func:`-sqlalchemy.sql.expression.text`, + or :class:`-sqlalchemy.schema.DefaultClause` to indicate + an alteration to the column's default value. + Set to ``None`` to have the default removed. + :param comment: optional string text of a new comment to add to the +~~ column. + + .. versionadded:: 1.0.6 + + :param new_column_name: Optional; specify a string name here to + indicate the new name within a column rename operation. + :param type\_: Optional; a :class:`-sqlalchemy.types.TypeEngine` + type object to specify a change to the column's type. + For SQLAlchemy types that also indicate a constraint (i.e. + :class:`-sqlalchemy.types.Boolean`, :class:`-sqlalchemy.types.Enum`), + the constraint is also generated. + :param autoincrement: set the ``AUTO_INCREMENT`` flag of the column; + currently understood by the MySQL dialect. + :param existing_type: Optional; a + :class:`-sqlalchemy.types.TypeEngine` + type object to specify the previous type. This + is required for all MySQL column alter operations that + don't otherwise specify a new type, as well as for + when nullability is being changed on a SQL Server +~~ column. It is also used if the type is a so-called + SQLlchemy "schema" type which may define a constraint (i.e. + :class:`-sqlalchemy.types.Boolean`, + :class:`-sqlalchemy.types.Enum`), + so that the constraint can be dropped. + :param existing_server_default: Optional; The existing +~~ default value of the column. Required on MySQL if + an existing default is not being changed; else MySQL + removes the default. + :param existing_nullable: Optional; the existing nullability +~~ of the column. Required on MySQL if the existing nullability + is not being changed; else MySQL sets this to NULL. + :param existing_autoincrement: Optional; the existing autoincrement +~~ of the column. Used for MySQL's system of altering a column + that specifies ``AUTO_INCREMENT``. + :param existing_comment: string text of the existing comment on the + column to be maintained. Required on MySQL if the existing comment + on the column is not being changed. + + .. versionadded:: 1.0.6 + + :param schema: Optional schema name to operate within. To control + quoting of the schema outside of the default behavior, use + the SQLAlchemy construct + :class:`-sqlalchemy.sql.elements.quoted_name`. + + .. versionadded:: 0.7.0 'schema' can now accept a + :class:`-sqlalchemy.sql.elements.quoted_name` construct. + + :param postgresql_using: String argument which will indicate a + SQL expression to render within the Postgresql-specific USING clause + within ALTER COLUMN. This string is taken directly as raw SQL which + must explicitly include any necessary quoting or escaping of tokens + within the expression. + + .. versionadded:: 0.8.8 + + batch migration context. + + +## ... source file continues with no further column examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-compiler-sqlcompiler.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-compiler-sqlcompiler.markdown new file mode 100644 index 000000000..24aa0e08d --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-compiler-sqlcompiler.markdown @@ -0,0 +1,96 @@ +title: sqlalchemy.sql.compiler SQLCompiler Example Code +category: page +slug: sqlalchemy-sql-compiler-sqlcompiler-examples +sortorder: 500031118 +toc: False +sidebartitle: sqlalchemy.sql.compiler SQLCompiler +meta: Example code for understanding how to use the SQLCompiler class from the sqlalchemy.sql.compiler module of the SQLAlchemy project. + + +`SQLCompiler` is a class within the `sqlalchemy.sql.compiler` module of the SQLAlchemy project. + + + +## Example 1 from PyHive +[PyHive](https://github.com/dropbox/PyHive) +([PyPI package information](https://pypi.org/project/PyHive/)) +is a set of [DB-API](https://www.python.org/dev/peps/pep-0249/) +and +[SQLAlchemy](/sqlalchemy.html) +interfaces that make it easier to use [Presto](https://prestodb.io/) +and [Apache Hive](http://hive.apache.org/) with Python. +[Dropbox's engineering team](https://www.dropbox.com/jobs/teams/engineering) +created this code library, open sourced it and put it out under +the [Apache 2.0 license](https://github.com/dropbox/PyHive/blob/master/LICENSE). + +[**PyHive / pyhive / sqlalchemy_presto.py**](https://github.com/dropbox/PyHive/blob/master/pyhive/./sqlalchemy_presto.py) + +```python +# sqlalchemy_presto.py + +from __future__ import absolute_import +from __future__ import unicode_literals + +import re +from sqlalchemy import exc +from sqlalchemy import types +from sqlalchemy import util +from sqlalchemy.databases import mysql +from sqlalchemy.engine import default +from sqlalchemy.sql import compiler +~~from sqlalchemy.sql.compiler import SQLCompiler + +from pyhive import presto +from pyhive.common import UniversalSet + + +class PrestoIdentifierPreparer(compiler.IdentifierPreparer): + reserved_words = UniversalSet() + + +_type_map = { + 'boolean': types.Boolean, + 'tinyint': mysql.MSTinyInteger, + 'smallint': types.SmallInteger, + 'integer': types.Integer, + 'bigint': types.BigInteger, + 'real': types.Float, + 'double': types.Float, + 'varchar': types.String, + 'timestamp': types.TIMESTAMP, + 'date': types.DATE, + 'varbinary': types.VARBINARY, +} + + +~~class PrestoCompiler(SQLCompiler): + def visit_char_length_func(self, fn, **kw): + return 'length{}'.format(self.function_argspec(fn, **kw)) + + +class PrestoTypeCompiler(compiler.GenericTypeCompiler): + def visit_CLOB(self, type_, **kw): + raise ValueError("Presto does not support the CLOB column type.") + + def visit_NCLOB(self, type_, **kw): + raise ValueError("Presto does not support the NCLOB column type.") + + def visit_DATETIME(self, type_, **kw): + raise ValueError("Presto does not support the DATETIME column type.") + + def visit_FLOAT(self, type_, **kw): + return 'DOUBLE' + + def visit_TEXT(self, type_, **kw): + if type_.length: + return 'VARCHAR({:d})'.format(type_.length) + else: + return 'VARCHAR' + + + + +## ... source file continues with no further SQLCompiler examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-elements-columnelement.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-elements-columnelement.markdown new file mode 100644 index 000000000..a65b10493 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-elements-columnelement.markdown @@ -0,0 +1,71 @@ +title: sqlalchemy.sql.elements ColumnElement Example Code +category: page +slug: sqlalchemy-sql-elements-columnelement-examples +sortorder: 500031119 +toc: False +sidebartitle: sqlalchemy.sql.elements ColumnElement +meta: Example code for understanding how to use the ColumnElement class from the sqlalchemy.sql.elements module of the SQLAlchemy project. + + +`ColumnElement` is a class within the `sqlalchemy.sql.elements` module of the SQLAlchemy project. + +Label +is another callable from the `sqlalchemy.sql.elements` package with code examples. + +## Example 1 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / functions.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./functions.py) + +```python +# functions.py +import re + +from sqlalchemy import inspect +from sqlalchemy.sql import functions +~~from sqlalchemy.sql.elements import ColumnElement +from sqlalchemy.ext.compiler import compiles + +from . import types +from . import elements + + +~~class TableRowElement(ColumnElement): + def __init__(self, selectable): + self.selectable = selectable + + @property + def _from_objects(self): + return [self.selectable] + + +class ST_AsGeoJSON(functions.GenericFunction): + + name = "ST_AsGeoJSON" + + def __init__(self, *args, **kwargs): + expr = kwargs.pop('expr', None) + args = list(args) + if expr is not None: + args = [expr] + args + for idx, element in enumerate(args): + if isinstance(element, functions.Function): + continue + elif isinstance(element, elements.HasFunction): + if element.extended: + func_name = element.geom_from_extended_version + func_args = [element.data] + + +## ... source file continues with no further ColumnElement examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-elements-label.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-elements-label.markdown new file mode 100644 index 000000000..fe52fa492 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-elements-label.markdown @@ -0,0 +1,143 @@ +title: sqlalchemy.sql.elements Label Example Code +category: page +slug: sqlalchemy-sql-elements-label-examples +sortorder: 500031120 +toc: False +sidebartitle: sqlalchemy.sql.elements Label +meta: Example code for understanding how to use the Label class from the sqlalchemy.sql.elements module of the SQLAlchemy project. + + +`Label` is a class within the `sqlalchemy.sql.elements` module of the SQLAlchemy project. + +ColumnElement +is another callable from the `sqlalchemy.sql.elements` package with code examples. + +## Example 1 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / loader.py**](https://github.com/python-gino/gino/blob/master/src/gino/./loader.py) + +```python +# loader.py +import types +import warnings + +from sqlalchemy import select +from sqlalchemy.schema import Column +~~from sqlalchemy.sql.elements import Label + +from .declarative import Model + + +class Loader: + + @classmethod + def get(cls, value): + from .crud import Alias + + if isinstance(value, Loader): + rv = value + elif isinstance(value, type) and issubclass(value, Model): + rv = ModelLoader(value) + elif isinstance(value, Alias): + rv = AliasLoader(value) + elif isinstance(value, Column): + rv = ColumnLoader(value) +~~ elif isinstance(value, Label): + rv = ColumnLoader(value.name) + elif isinstance(value, tuple): + rv = TupleLoader(value) + elif callable(value): + rv = CallableLoader(value) + else: + rv = ValueLoader(value) + return rv + + @property + def query(self): + rv = select(self.get_columns()) + from_clause = self.get_from() + if from_clause is not None: + rv = rv.select_from(from_clause) + return rv.execution_options(loader=self) + + def do_load(self, row, context): + raise NotImplementedError + + def get_columns(self): + return [] + + def get_from(self): + + +## ... source file continues with no further Label examples... + +``` + + +## Example 2 from indico +[indico](https://github.com/indico/indico) +([project website](https://getindico.io/), +[documentation](https://docs.getindico.io/en/stable/installation/) +and [sandbox demo](https://sandbox.getindico.io/)) +is a [Flask](/flask.html)-based web app for event management that is +powered by [SQLAlchemy](/sqlalchemy.html) on the backend. The code +for this project is open sourced under the +[MIT license](https://github.com/indico/indico/blob/master/LICENSE). + +[**indico / indico / core / marshmallow.py**](https://github.com/indico/indico/blob/master/indico/core/marshmallow.py) + +```python +# marshmallow.py + +from __future__ import absolute_import, unicode_literals + +from inspect import getmro + +from flask_marshmallow import Marshmallow +from flask_marshmallow.sqla import SchemaOpts +from marshmallow import fields, post_dump, post_load, pre_load +from marshmallow_enum import EnumField +from marshmallow_sqlalchemy import ModelConverter +from marshmallow_sqlalchemy import ModelSchema as MSQLAModelSchema +from sqlalchemy.orm import ColumnProperty +~~from sqlalchemy.sql.elements import Label +from webargs.flaskparser import parser as webargs_flask_parser + +from indico.core import signals +from indico.core.db.sqlalchemy import PyIntEnum, UTCDateTime +from indico.web.args import parser as indico_webargs_flask_parser + + +mm = Marshmallow() + + +def _is_column_property(prop): + return hasattr(prop, 'columns') and isinstance(prop.columns[0], Label) + + +class IndicoModelConverter(ModelConverter): + SQLA_TYPE_MAPPING = ModelConverter.SQLA_TYPE_MAPPING.copy() + SQLA_TYPE_MAPPING.update({ + UTCDateTime: fields.DateTime, + PyIntEnum: EnumField + }) + + def _get_field_kwargs_for_property(self, prop): + kwargs = super(IndicoModelConverter, self)._get_field_kwargs_for_property(prop) + if isinstance(prop, ColumnProperty) and hasattr(prop.columns[0].type, 'marshmallow_get_field_kwargs'): + + +## ... source file continues with no further Label examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-clauseelement.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-clauseelement.markdown new file mode 100644 index 000000000..0c2a31279 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-clauseelement.markdown @@ -0,0 +1,128 @@ +title: sqlalchemy.sql.expression ClauseElement Example Code +category: page +slug: sqlalchemy-sql-expression-clauseelement-examples +sortorder: 500031121 +toc: False +sidebartitle: sqlalchemy.sql.expression ClauseElement +meta: Example code for understanding how to use the ClauseElement class from the sqlalchemy.sql.expression module of the SQLAlchemy project. + + +`ClauseElement` is a class within the `sqlalchemy.sql.expression` module of the SQLAlchemy project. + +ColumnClause, +ColumnElement, +Executable, +FunctionElement, +and UnaryExpression +are several other callables with code examples from the same `sqlalchemy.sql.expression` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / mssql.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/mssql.py) + +```python +# mssql.py +from sqlalchemy import types as sqltypes +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.schema import Column +from sqlalchemy.schema import CreateIndex +~~from sqlalchemy.sql.expression import ClauseElement +from sqlalchemy.sql.expression import Executable + +from .base import AddColumn +from .base import alter_column +from .base import alter_table +from .base import ColumnDefault +from .base import ColumnName +from .base import ColumnNullable +from .base import ColumnType +from .base import format_column_name +from .base import format_server_default +from .base import format_table_name +from .base import format_type +from .base import RenameTable +from .impl import DefaultImpl +from .. import util + + +class MSSQLImpl(DefaultImpl): + __dialect__ = "mssql" + transactional_ddl = True + batch_separator = "GO" + + type_synonyms = DefaultImpl.type_synonyms + ({"VARCHAR", "NVARCHAR"},) + + +## ... source file abbreviated to get to ClauseElement examples ... + + + super(MSSQLImpl, self).bulk_insert(table, rows, **kw) + + def drop_column(self, table_name, column, schema=None, **kw): + drop_default = kw.pop("mssql_drop_default", False) + if drop_default: + self._exec( + _ExecDropConstraint( + table_name, column, "sys.default_constraints", schema + ) + ) + drop_check = kw.pop("mssql_drop_check", False) + if drop_check: + self._exec( + _ExecDropConstraint( + table_name, column, "sys.check_constraints", schema + ) + ) + drop_fks = kw.pop("mssql_drop_foreign_key", False) + if drop_fks: + self._exec(_ExecDropFKConstraint(table_name, column, schema)) + super(MSSQLImpl, self).drop_column( + table_name, column, schema=schema, **kw + ) + + +~~class _ExecDropConstraint(Executable, ClauseElement): + def __init__(self, tname, colname, type_, schema): + self.tname = tname + self.colname = colname + self.type_ = type_ + self.schema = schema + + +~~class _ExecDropFKConstraint(Executable, ClauseElement): + def __init__(self, tname, colname, schema): + self.tname = tname + self.colname = colname + self.schema = schema + + +@compiles(_ExecDropConstraint, "mssql") +def _exec_drop_col_constraint(element, compiler, **kw): + schema, tname, colname, type_ = ( + element.schema, + element.tname, + element.colname, + element.type_, + ) + return """declare @const_name varchar(256) +select @const_name = [name] from %(type)s +where parent_object_id = object_id('%(schema_dot)s%(tname)s') +and col_name(parent_object_id, parent_column_id) = '%(colname)s' +exec('alter table %(tname_quoted)s drop constraint ' + @const_name)""" % { + "type": type_, + "tname": tname, + "colname": colname, + "tname_quoted": format_table_name(compiler, tname, schema), + "schema_dot": schema + "." if schema else "", + + +## ... source file continues with no further ClauseElement examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-columnclause.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-columnclause.markdown new file mode 100644 index 000000000..6684cd644 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-columnclause.markdown @@ -0,0 +1,114 @@ +title: sqlalchemy.sql.expression ColumnClause Example Code +category: page +slug: sqlalchemy-sql-expression-columnclause-examples +sortorder: 500031122 +toc: False +sidebartitle: sqlalchemy.sql.expression ColumnClause +meta: Example code for understanding how to use the ColumnClause class from the sqlalchemy.sql.expression module of the SQLAlchemy project. + + +`ColumnClause` is a class within the `sqlalchemy.sql.expression` module of the SQLAlchemy project. + +ClauseElement, +ColumnElement, +Executable, +FunctionElement, +and UnaryExpression +are several other callables with code examples from the same `sqlalchemy.sql.expression` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / postgresql.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/postgresql.py) + +```python +# postgresql.py +import logging +import re + +from sqlalchemy import Column +from sqlalchemy import Numeric +from sqlalchemy import text +from sqlalchemy import types as sqltypes +from sqlalchemy.dialects.postgresql import BIGINT +from sqlalchemy.dialects.postgresql import ExcludeConstraint +from sqlalchemy.dialects.postgresql import INTEGER +~~from sqlalchemy.sql.expression import ColumnClause +from sqlalchemy.sql.expression import UnaryExpression +from sqlalchemy.types import NULLTYPE + +from .base import alter_column +from .base import alter_table +from .base import AlterColumn +from .base import ColumnComment +from .base import compiles +from .base import format_column_name +from .base import format_table_name +from .base import format_type +from .base import RenameTable +from .impl import DefaultImpl +from .. import util +from ..autogenerate import render +from ..operations import ops +from ..operations import schemaobj +from ..operations.base import BatchOperations +from ..operations.base import Operations +from ..util import compat +from ..util import sqla_compat + + +log = logging.getLogger(__name__) + + +## ... source file abbreviated to get to ColumnClause examples ... + + + return "%(prefix)screate_exclude_constraint(%(args)s)" % { + "prefix": render._alembic_autogenerate_prefix(autogen_context), + "args": ", ".join(args), + } + else: + args = [ + "(%s, %r)" + % (_render_potential_column(sqltext, autogen_context), opstring) + for sqltext, name, opstring in constraint._render_exprs + ] + if constraint.where is not None: + args.append( + "where=%s" + % render._render_potential_expr( + constraint.where, autogen_context + ) + ) + args.extend(["%s=%r" % (k, v) for k, v in opts]) + return "%(prefix)sExcludeConstraint(%(args)s)" % { + "prefix": _postgresql_autogenerate_prefix(autogen_context), + "args": ", ".join(args), + } + + +def _render_potential_column(value, autogen_context): +~~ if isinstance(value, ColumnClause): + template = "%(prefix)scolumn(%(name)r)" + + return template % { + "prefix": render._sqlalchemy_autogenerate_prefix(autogen_context), + "name": value.name, + } + + else: + return render._render_potential_expr( + value, autogen_context, wrap_in_text=False + ) + + + +## ... source file continues with no further ColumnClause examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-columnelement.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-columnelement.markdown new file mode 100644 index 000000000..ea587137d --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-columnelement.markdown @@ -0,0 +1,103 @@ +title: sqlalchemy.sql.expression ColumnElement Example Code +category: page +slug: sqlalchemy-sql-expression-columnelement-examples +sortorder: 500031123 +toc: False +sidebartitle: sqlalchemy.sql.expression ColumnElement +meta: Example code for understanding how to use the ColumnElement class from the sqlalchemy.sql.expression module of the SQLAlchemy project. + + +`ColumnElement` is a class within the `sqlalchemy.sql.expression` module of the SQLAlchemy project. + +ClauseElement, +ColumnClause, +Executable, +FunctionElement, +and UnaryExpression +are several other callables with code examples from the same `sqlalchemy.sql.expression` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / expressions.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./expressions.py) + +```python +# expressions.py +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql +from sqlalchemy.ext.compiler import compiles +~~from sqlalchemy.sql.expression import ColumnElement, FunctionElement +from sqlalchemy.sql.functions import GenericFunction + +from .functions.orm import quote + + +class array_get(FunctionElement): + name = 'array_get' + + +@compiles(array_get) +def compile_array_get(element, compiler, **kw): + args = list(element.clauses) + if len(args) != 2: + raise Exception( + "Function 'array_get' expects two arguments (%d given)." % + len(args) + ) + + if not hasattr(args[1], 'value') or not isinstance(args[1].value, int): + raise Exception( + "Second argument should be an integer." + ) + return '(%s)[%s]' % ( + compiler.process(args[0]), + sa.text(str(args[1].value + 1)) + ) + + +class row_to_json(GenericFunction): + name = 'row_to_json' + type = postgresql.JSON + + +@compiles(row_to_json, 'postgresql') +def compile_row_to_json(element, compiler, **kw): + return "%s(%s)" % (element.name, compiler.process(element.clauses)) + + +class json_array_length(GenericFunction): + name = 'json_array_length' + type = sa.Integer + + +@compiles(json_array_length, 'postgresql') +def compile_json_array_length(element, compiler, **kw): + return "%s(%s)" % (element.name, compiler.process(element.clauses)) + + +~~class Asterisk(ColumnElement): + def __init__(self, selectable): + self.selectable = selectable + + +@compiles(Asterisk) +def compile_asterisk(element, compiler, **kw): + return '%s.*' % quote(compiler.dialect, element.selectable.name) + + + +## ... source file continues with no further ColumnElement examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-executable.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-executable.markdown new file mode 100644 index 000000000..f12f928a2 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-executable.markdown @@ -0,0 +1,129 @@ +title: sqlalchemy.sql.expression Executable Example Code +category: page +slug: sqlalchemy-sql-expression-executable-examples +sortorder: 500031124 +toc: False +sidebartitle: sqlalchemy.sql.expression Executable +meta: Example code for understanding how to use the Executable class from the sqlalchemy.sql.expression module of the SQLAlchemy project. + + +`Executable` is a class within the `sqlalchemy.sql.expression` module of the SQLAlchemy project. + +ClauseElement, +ColumnClause, +ColumnElement, +FunctionElement, +and UnaryExpression +are several other callables with code examples from the same `sqlalchemy.sql.expression` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / mssql.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/mssql.py) + +```python +# mssql.py +from sqlalchemy import types as sqltypes +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.schema import Column +from sqlalchemy.schema import CreateIndex +from sqlalchemy.sql.expression import ClauseElement +~~from sqlalchemy.sql.expression import Executable + +from .base import AddColumn +from .base import alter_column +from .base import alter_table +from .base import ColumnDefault +from .base import ColumnName +from .base import ColumnNullable +from .base import ColumnType +from .base import format_column_name +from .base import format_server_default +from .base import format_table_name +from .base import format_type +from .base import RenameTable +from .impl import DefaultImpl +from .. import util + + +class MSSQLImpl(DefaultImpl): + __dialect__ = "mssql" + transactional_ddl = True + batch_separator = "GO" + + type_synonyms = DefaultImpl.type_synonyms + ({"VARCHAR", "NVARCHAR"},) + + + +## ... source file abbreviated to get to Executable examples ... + + + super(MSSQLImpl, self).bulk_insert(table, rows, **kw) + + def drop_column(self, table_name, column, schema=None, **kw): + drop_default = kw.pop("mssql_drop_default", False) + if drop_default: + self._exec( + _ExecDropConstraint( + table_name, column, "sys.default_constraints", schema + ) + ) + drop_check = kw.pop("mssql_drop_check", False) + if drop_check: + self._exec( + _ExecDropConstraint( + table_name, column, "sys.check_constraints", schema + ) + ) + drop_fks = kw.pop("mssql_drop_foreign_key", False) + if drop_fks: + self._exec(_ExecDropFKConstraint(table_name, column, schema)) + super(MSSQLImpl, self).drop_column( + table_name, column, schema=schema, **kw + ) + + +~~class _ExecDropConstraint(Executable, ClauseElement): + def __init__(self, tname, colname, type_, schema): + self.tname = tname + self.colname = colname + self.type_ = type_ + self.schema = schema + + +~~class _ExecDropFKConstraint(Executable, ClauseElement): + def __init__(self, tname, colname, schema): + self.tname = tname + self.colname = colname + self.schema = schema + + +@compiles(_ExecDropConstraint, "mssql") +def _exec_drop_col_constraint(element, compiler, **kw): + schema, tname, colname, type_ = ( + element.schema, + element.tname, + element.colname, + element.type_, + ) + return """declare @const_name varchar(256) +select @const_name = [name] from %(type)s +where parent_object_id = object_id('%(schema_dot)s%(tname)s') +and col_name(parent_object_id, parent_column_id) = '%(colname)s' +exec('alter table %(tname_quoted)s drop constraint ' + @const_name)""" % { + "type": type_, + "tname": tname, + "colname": colname, + "tname_quoted": format_table_name(compiler, tname, schema), + "schema_dot": schema + "." if schema else "", + + +## ... source file continues with no further Executable examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-function.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-function.markdown new file mode 100644 index 000000000..8ddefab5e --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-function.markdown @@ -0,0 +1,97 @@ +title: sqlalchemy.sql.expression Function code examples +category: page +slug: sqlalchemy-sql-expression-function-examples +sortorder: 500031004 +toc: False +sidebartitle: sqlalchemy.sql.expression Function +meta: Python example code for the Function class from the sqlalchemy.sql.expression module of the SQLAlchemy project. + + +Function is a class within the sqlalchemy.sql.expression module of the SQLAlchemy project. + + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlachemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / expressions.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./expressions.py) + +```python +# expressions.py +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql +from sqlalchemy.ext.compiler import compiles +~~from sqlalchemy.sql.expression import ColumnElement, FunctionElement +~~from sqlalchemy.sql.functions import GenericFunction + +from .functions.orm import quote + + +~~class array_get(FunctionElement): + name = 'array_get' + + +@compiles(array_get) +def compile_array_get(element, compiler, **kw): + args = list(element.clauses) + if len(args) != 2: + raise Exception( +~~ "Function 'array_get' expects two arguments (%d given)." % + len(args) + ) + + if not hasattr(args[1], 'value') or not isinstance(args[1].value, int): + raise Exception( + "Second argument should be an integer." + ) + return '(%s)[%s]' % ( + compiler.process(args[0]), + sa.text(str(args[1].value + 1)) + ) + + +~~class row_to_json(GenericFunction): + name = 'row_to_json' + type = postgresql.JSON + + +@compiles(row_to_json, 'postgresql') +def compile_row_to_json(element, compiler, **kw): + return "%s(%s)" % (element.name, compiler.process(element.clauses)) + + +~~class json_array_length(GenericFunction): + name = 'json_array_length' + type = sa.Integer + + +@compiles(json_array_length, 'postgresql') +def compile_json_array_length(element, compiler, **kw): + return "%s(%s)" % (element.name, compiler.process(element.clauses)) + + +class Asterisk(ColumnElement): + def __init__(self, selectable): + self.selectable = selectable + + +@compiles(Asterisk) +def compile_asterisk(element, compiler, **kw): + return '%s.*' % quote(compiler.dialect, element.selectable.name) + + +## ... source file continues with no further Function examples... + + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-functionelement.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-functionelement.markdown new file mode 100644 index 000000000..4a9d94c0e --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-functionelement.markdown @@ -0,0 +1,174 @@ +title: sqlalchemy.sql.expression FunctionElement Example Code +category: page +slug: sqlalchemy-sql-expression-functionelement-examples +sortorder: 500031125 +toc: False +sidebartitle: sqlalchemy.sql.expression FunctionElement +meta: Example code for understanding how to use the FunctionElement class from the sqlalchemy.sql.expression module of the SQLAlchemy project. + + +`FunctionElement` is a class within the `sqlalchemy.sql.expression` module of the SQLAlchemy project. + +ClauseElement, +ColumnClause, +ColumnElement, +Executable, +and UnaryExpression +are several other callables with code examples from the same `sqlalchemy.sql.expression` package. + +## Example 1 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / elements.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./elements.py) + +```python +# elements.py +import binascii +import struct + +try: + from sqlalchemy.sql import functions + from sqlalchemy.sql.functions import FunctionElement +except ImportError: # SQLA < 0.9 # pragma: no cover + from sqlalchemy.sql import expression as functions +~~ from sqlalchemy.sql.expression import FunctionElement +from sqlalchemy.types import to_instance +from sqlalchemy.ext.compiler import compiles + +from .compat import PY3, str as str_ +from .exc import ArgumentError + + +if PY3: + BinasciiError = binascii.Error +else: + BinasciiError = TypeError + + +class HasFunction(object): + pass + + +class _SpatialElement(HasFunction): + + def __init__(self, data, srid=-1, extended=False): + self.srid = srid + self.data = data + self.extended = extended + + + +## ... source file abbreviated to get to FunctionElement examples ... + + + + geom_from_extended_version = 'raster' + + def __init__(self, data): + try: + bin_data = binascii.unhexlify(data[:114]) + except BinasciiError: + bin_data = data + data = str(binascii.hexlify(data).decode(encoding='utf-8')) + byte_order = bin_data[0] + srid = bin_data[53:57] + if not PY3: + byte_order = bytearray(byte_order)[0] + srid = struct.unpack('I', srid)[0] + _SpatialElement.__init__(self, data, srid, True) + + @property + def desc(self): + return self.data + + @staticmethod + def _data_from_desc(desc): + return desc + + +~~class CompositeElement(FunctionElement): + + def __init__(self, base, field, type_): + self.name = field + self.type = to_instance(type_) + + super(CompositeElement, self).__init__(base) + + +@compiles(CompositeElement) +def _compile_pgelem(expr, compiler, **kw): + return '(%s).%s' % (compiler.process(expr.clauses, **kw), expr.name) + + + +## ... source file continues with no further FunctionElement examples... + +``` + + +## Example 2 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / expressions.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./expressions.py) + +```python +# expressions.py +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql +from sqlalchemy.ext.compiler import compiles +~~from sqlalchemy.sql.expression import ColumnElement, FunctionElement +from sqlalchemy.sql.functions import GenericFunction + +from .functions.orm import quote + + +~~class array_get(FunctionElement): + name = 'array_get' + + +@compiles(array_get) +def compile_array_get(element, compiler, **kw): + args = list(element.clauses) + if len(args) != 2: + raise Exception( + "Function 'array_get' expects two arguments (%d given)." % + len(args) + ) + + if not hasattr(args[1], 'value') or not isinstance(args[1].value, int): + raise Exception( + "Second argument should be an integer." + ) + return '(%s)[%s]' % ( + compiler.process(args[0]), + sa.text(str(args[1].value + 1)) + ) + + +class row_to_json(GenericFunction): + name = 'row_to_json' + + +## ... source file continues with no further FunctionElement examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-unaryexpression.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-unaryexpression.markdown new file mode 100644 index 000000000..3eabb755d --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression-unaryexpression.markdown @@ -0,0 +1,127 @@ +title: sqlalchemy.sql.expression UnaryExpression Example Code +category: page +slug: sqlalchemy-sql-expression-unaryexpression-examples +sortorder: 500031126 +toc: False +sidebartitle: sqlalchemy.sql.expression UnaryExpression +meta: Example code for understanding how to use the UnaryExpression class from the sqlalchemy.sql.expression module of the SQLAlchemy project. + + +`UnaryExpression` is a class within the `sqlalchemy.sql.expression` module of the SQLAlchemy project. + +ClauseElement, +ColumnClause, +ColumnElement, +Executable, +and FunctionElement +are several other callables with code examples from the same `sqlalchemy.sql.expression` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / postgresql.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/postgresql.py) + +```python +# postgresql.py +import logging +import re + +from sqlalchemy import Column +from sqlalchemy import Numeric +from sqlalchemy import text +from sqlalchemy import types as sqltypes +from sqlalchemy.dialects.postgresql import BIGINT +from sqlalchemy.dialects.postgresql import ExcludeConstraint +from sqlalchemy.dialects.postgresql import INTEGER +from sqlalchemy.sql.expression import ColumnClause +~~from sqlalchemy.sql.expression import UnaryExpression +from sqlalchemy.types import NULLTYPE + +from .base import alter_column +from .base import alter_table +from .base import AlterColumn +from .base import ColumnComment +from .base import compiles +from .base import format_column_name +from .base import format_table_name +from .base import format_type +from .base import RenameTable +from .impl import DefaultImpl +from .. import util +from ..autogenerate import render +from ..operations import ops +from ..operations import schemaobj +from ..operations.base import BatchOperations +from ..operations.base import Operations +from ..util import compat +from ..util import sqla_compat + + +log = logging.getLogger(__name__) + + + +## ... source file abbreviated to get to UnaryExpression examples ... + + + + def correct_for_autogen_constraints( + self, + conn_unique_constraints, + conn_indexes, + metadata_unique_constraints, + metadata_indexes, + ): + + conn_indexes_by_name = dict((c.name, c) for c in conn_indexes) + + doubled_constraints = set( + index + for index in conn_indexes + if index.info.get("duplicates_constraint") + ) + + for ix in doubled_constraints: + conn_indexes.remove(ix) + + for idx in list(metadata_indexes): + if idx.name in conn_indexes_by_name: + continue + exprs = idx.expressions + for expr in exprs: +~~ while isinstance(expr, UnaryExpression): + expr = expr.element + if not isinstance(expr, Column): + util.warn( + "autogenerate skipping functional index %s; " + "not supported by SQLAlchemy reflection" % idx.name + ) + metadata_indexes.discard(idx) + + def render_type(self, type_, autogen_context): + mod = type(type_).__module__ + if not mod.startswith("sqlalchemy.dialects.postgresql"): + return False + + if hasattr(self, "_render_%s_type" % type_.__visit_name__): + meth = getattr(self, "_render_%s_type" % type_.__visit_name__) + return meth(type_, autogen_context) + + return False + + def _render_HSTORE_type(self, type_, autogen_context): + return render._render_type_w_subtype( + type_, autogen_context, "text_type", r"(.+?\(.*text_type=)" + ) + + + +## ... source file continues with no further UnaryExpression examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression.markdown new file mode 100644 index 000000000..ea70ede10 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-expression.markdown @@ -0,0 +1,117 @@ +title: sqlalchemy.sql expression Example Code +category: page +slug: sqlalchemy-sql-expression-examples +sortorder: 500031110 +toc: False +sidebartitle: sqlalchemy.sql expression +meta: Python example code that shows how to use the expression callable from the sqlalchemy.sql module of the SQLAlchemy project. + + +`expression` is a callable within the `sqlalchemy.sql` module of the SQLAlchemy project. + +ClauseElement, +Select, +column, +extract, +functions, +operators, +schema, +select, +sqltypes, +and table +are several other callables with code examples from the same `sqlalchemy.sql` package. + +## Example 1 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / __init__.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./__init__.py) + +```python +# __init__.py +from .types import ( # NOQA + Geometry, + Geography, + Raster + ) + +from .elements import ( # NOQA + WKTElement, + WKBElement, + RasterElement + ) + +from .exc import ArgumentError + +from . import functions # NOQA +from . import types # NOQA + +from sqlalchemy import Table, event +~~from sqlalchemy.sql import select, func, expression + + +def _setup_ddl_event_listeners(): + @event.listens_for(Table, "before_create") + def before_create(target, connection, **kw): + dispatch("before-create", target, connection) + + @event.listens_for(Table, "after_create") + def after_create(target, connection, **kw): + dispatch("after-create", target, connection) + + @event.listens_for(Table, "before_drop") + def before_drop(target, connection, **kw): + dispatch("before-drop", target, connection) + + @event.listens_for(Table, "after_drop") + def after_drop(target, connection, **kw): + dispatch("after-drop", target, connection) + + def dispatch(event, table, bind): + if event in ('before-create', 'before-drop'): + gis_cols = [c for c in table.c if + isinstance(c.type, Geometry) and + c.type.management is True] + + regular_cols = [x for x in table.c if x not in gis_cols] + + table.info["_saved_columns"] = table.c + +~~ column_collection = expression.ColumnCollection() + for col in regular_cols: + column_collection.add(col) + table.columns = column_collection + + if event == 'before-drop': + for c in gis_cols: + if bind.dialect.name == 'sqlite': + drop_func = 'DiscardGeometryColumn' + elif bind.dialect.name == 'postgresql': + drop_func = 'DropGeometryColumn' + else: + raise ArgumentError('dialect {} is not supported'.format(bind.dialect.name)) + args = [table.schema] if table.schema else [] + args.extend([table.name, c.name]) + + stmt = select([getattr(func, drop_func)(*args)]) + stmt = stmt.execution_options(autocommit=True) + bind.execute(stmt) + + elif event == 'after-create': + table.columns = table.info.pop('_saved_columns') + + for c in table.c: + if isinstance(c.type, Geometry) and c.type.management is True: + + +## ... source file continues with no further expression examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-extract.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-extract.markdown new file mode 100644 index 000000000..8a8bae618 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-extract.markdown @@ -0,0 +1,153 @@ +title: sqlalchemy.sql extract Example Code +category: page +slug: sqlalchemy-sql-extract-examples +sortorder: 500031111 +toc: False +sidebartitle: sqlalchemy.sql extract +meta: Python example code that shows how to use the extract callable from the sqlalchemy.sql module of the SQLAlchemy project. + + +`extract` is a callable within the `sqlalchemy.sql` module of the SQLAlchemy project. + +ClauseElement, +Select, +column, +expression, +functions, +operators, +schema, +select, +sqltypes, +and table +are several other callables with code examples from the same `sqlalchemy.sql` package. + +## Example 1 from SQLAlchemy Mixins +[SQLAlchemy Mixins](https://github.com/absent1706/sqlalchemy-mixins) +([PyPI package information](https://pypi.org/project/sqlalchemy-mixins/)) +is a collection of +[mixins](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful) +useful for extending [SQLAlchemy](/sqlalchemy.html) and simplifying +your [database](/databases.html)-interacting code for some common +use cases. SQLAlchemy Mixins is open sourced under the +[MIT license](https://github.com/absent1706/sqlalchemy-mixins/blob/master/LICENSE.txt). + +[**SQLAlchemy Mixins / sqlalchemy_mixins / smartquery.py**](https://github.com/absent1706/sqlalchemy-mixins/blob/master/sqlalchemy_mixins/./smartquery.py) + +```python +# smartquery.py +try: + from typing import List +except ImportError: # pragma: no cover + pass + +from collections import OrderedDict + +import sqlalchemy +from sqlalchemy import asc, desc, inspect +from sqlalchemy.orm import aliased, contains_eager +from sqlalchemy.orm.util import AliasedClass +~~from sqlalchemy.sql import operators, extract + +from .eagerload import _flatten_schema, _eager_expr_from_flat_schema, \ + EagerLoadMixin +from .inspection import InspectionMixin +from .utils import classproperty + +RELATION_SPLITTER = '___' +OPERATOR_SPLITTER = '__' + +DESC_PREFIX = '-' + + +def _parse_path_and_make_aliases(entity, entity_path, attrs, aliases): + relations = {} + for attr in attrs: + if RELATION_SPLITTER in attr: + relation_name, nested_attr = attr.split(RELATION_SPLITTER, 1) + if relation_name in relations: + relations[relation_name].append(nested_attr) + else: + relations[relation_name] = [nested_attr] + + for relation_name, nested_attrs in relations.items(): + path = entity_path + RELATION_SPLITTER + relation_name \ + + +## ... source file abbreviated to get to extract examples ... + + +class SmartQueryMixin(InspectionMixin, EagerLoadMixin): + __abstract__ = True + + _operators = { + 'isnull': lambda c, v: (c == None) if v else (c != None), + 'exact': operators.eq, + 'ne': operators.ne, # not equal or is not (for None) + + 'gt': operators.gt, # greater than , > + 'ge': operators.ge, # greater than or equal, >= + 'lt': operators.lt, # lower than, < + 'le': operators.le, # lower than or equal, <= + + 'in': operators.in_op, + 'notin': operators.notin_op, + 'between': lambda c, v: c.between(v[0], v[1]), + + 'like': operators.like_op, + 'ilike': operators.ilike_op, + 'startswith': operators.startswith_op, + 'istartswith': lambda c, v: c.ilike(v + '%'), + 'endswith': operators.endswith_op, + 'iendswith': lambda c, v: c.ilike('%' + v), + 'contains': lambda c, v: c.ilike('%{v}%'.format(v=v)), + +~~ 'year': lambda c, v: extract('year', c) == v, +~~ 'year_ne': lambda c, v: extract('year', c) != v, +~~ 'year_gt': lambda c, v: extract('year', c) > v, +~~ 'year_ge': lambda c, v: extract('year', c) >= v, +~~ 'year_lt': lambda c, v: extract('year', c) < v, +~~ 'year_le': lambda c, v: extract('year', c) <= v, + +~~ 'month': lambda c, v: extract('month', c) == v, +~~ 'month_ne': lambda c, v: extract('month', c) != v, +~~ 'month_gt': lambda c, v: extract('month', c) > v, +~~ 'month_ge': lambda c, v: extract('month', c) >= v, +~~ 'month_lt': lambda c, v: extract('month', c) < v, +~~ 'month_le': lambda c, v: extract('month', c) <= v, + +~~ 'day': lambda c, v: extract('day', c) == v, +~~ 'day_ne': lambda c, v: extract('day', c) != v, +~~ 'day_gt': lambda c, v: extract('day', c) > v, +~~ 'day_ge': lambda c, v: extract('day', c) >= v, +~~ 'day_lt': lambda c, v: extract('day', c) < v, +~~ 'day_le': lambda c, v: extract('day', c) <= v, + } + + @classproperty + def filterable_attributes(cls): + return cls.relations + cls.columns + \ + cls.hybrid_properties + cls.hybrid_methods + + @classproperty + def sortable_attributes(cls): + return cls.columns + cls.hybrid_properties + + @classmethod + def filter_expr(cls_or_alias, **filters): + if isinstance(cls_or_alias, AliasedClass): + mapper, cls = cls_or_alias, inspect(cls_or_alias).mapper.class_ + else: + mapper = cls = cls_or_alias + + expressions = [] + valid_attributes = cls.filterable_attributes + for attr, value in filters.items(): + if attr in cls.hybrid_methods: + method = getattr(cls, attr) + expressions.append(method(value, mapper=mapper)) + + +## ... source file continues with no further extract examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-functions-functionelement.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-functions-functionelement.markdown new file mode 100644 index 000000000..f372489d3 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-functions-functionelement.markdown @@ -0,0 +1,108 @@ +title: sqlalchemy.sql.functions FunctionElement Example Code +category: page +slug: sqlalchemy-sql-functions-functionelement-examples +sortorder: 500031127 +toc: False +sidebartitle: sqlalchemy.sql.functions FunctionElement +meta: Example code for understanding how to use the FunctionElement class from the sqlalchemy.sql.functions module of the SQLAlchemy project. + + +`FunctionElement` is a class within the `sqlalchemy.sql.functions` module of the SQLAlchemy project. + +GenericFunction +is another callable from the `sqlalchemy.sql.functions` package with code examples. + +## Example 1 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / elements.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./elements.py) + +```python +# elements.py +import binascii +import struct + +try: + from sqlalchemy.sql import functions +~~ from sqlalchemy.sql.functions import FunctionElement +except ImportError: # SQLA < 0.9 # pragma: no cover + from sqlalchemy.sql import expression as functions + from sqlalchemy.sql.expression import FunctionElement +from sqlalchemy.types import to_instance +from sqlalchemy.ext.compiler import compiles + +from .compat import PY3, str as str_ +from .exc import ArgumentError + + +if PY3: + BinasciiError = binascii.Error +else: + BinasciiError = TypeError + + +class HasFunction(object): + pass + + +class _SpatialElement(HasFunction): + + def __init__(self, data, srid=-1, extended=False): + self.srid = srid + + +## ... source file abbreviated to get to FunctionElement examples ... + + + + geom_from_extended_version = 'raster' + + def __init__(self, data): + try: + bin_data = binascii.unhexlify(data[:114]) + except BinasciiError: + bin_data = data + data = str(binascii.hexlify(data).decode(encoding='utf-8')) + byte_order = bin_data[0] + srid = bin_data[53:57] + if not PY3: + byte_order = bytearray(byte_order)[0] + srid = struct.unpack('I', srid)[0] + _SpatialElement.__init__(self, data, srid, True) + + @property + def desc(self): + return self.data + + @staticmethod + def _data_from_desc(desc): + return desc + + +~~class CompositeElement(FunctionElement): + + def __init__(self, base, field, type_): + self.name = field + self.type = to_instance(type_) + + super(CompositeElement, self).__init__(base) + + +@compiles(CompositeElement) +def _compile_pgelem(expr, compiler, **kw): + return '(%s).%s' % (compiler.process(expr.clauses, **kw), expr.name) + + + +## ... source file continues with no further FunctionElement examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-functions-genericfunction.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-functions-genericfunction.markdown new file mode 100644 index 000000000..fb73febd8 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-functions-genericfunction.markdown @@ -0,0 +1,99 @@ +title: sqlalchemy.sql.functions GenericFunction Example Code +category: page +slug: sqlalchemy-sql-functions-genericfunction-examples +sortorder: 500031128 +toc: False +sidebartitle: sqlalchemy.sql.functions GenericFunction +meta: Example code for understanding how to use the GenericFunction class from the sqlalchemy.sql.functions module of the SQLAlchemy project. + + +`GenericFunction` is a class within the `sqlalchemy.sql.functions` module of the SQLAlchemy project. + +FunctionElement +is another callable from the `sqlalchemy.sql.functions` package with code examples. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / expressions.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./expressions.py) + +```python +# expressions.py +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.sql.expression import ColumnElement, FunctionElement +~~from sqlalchemy.sql.functions import GenericFunction + +from .functions.orm import quote + + +class array_get(FunctionElement): + name = 'array_get' + + +@compiles(array_get) +def compile_array_get(element, compiler, **kw): + args = list(element.clauses) + if len(args) != 2: + raise Exception( + "Function 'array_get' expects two arguments (%d given)." % + len(args) + ) + + if not hasattr(args[1], 'value') or not isinstance(args[1].value, int): + raise Exception( + "Second argument should be an integer." + ) + return '(%s)[%s]' % ( + compiler.process(args[0]), + sa.text(str(args[1].value + 1)) + ) + + +~~class row_to_json(GenericFunction): + name = 'row_to_json' + type = postgresql.JSON + + +@compiles(row_to_json, 'postgresql') +def compile_row_to_json(element, compiler, **kw): + return "%s(%s)" % (element.name, compiler.process(element.clauses)) + + +~~class json_array_length(GenericFunction): + name = 'json_array_length' + type = sa.Integer + + +@compiles(json_array_length, 'postgresql') +def compile_json_array_length(element, compiler, **kw): + return "%s(%s)" % (element.name, compiler.process(element.clauses)) + + +class Asterisk(ColumnElement): + def __init__(self, selectable): + self.selectable = selectable + + +@compiles(Asterisk) +def compile_asterisk(element, compiler, **kw): + return '%s.*' % quote(compiler.dialect, element.selectable.name) + + + +## ... source file continues with no further GenericFunction examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-functions.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-functions.markdown new file mode 100644 index 000000000..45c8d808e --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-functions.markdown @@ -0,0 +1,160 @@ +title: sqlalchemy.sql functions Example Code +category: page +slug: sqlalchemy-sql-functions-examples +sortorder: 500031112 +toc: False +sidebartitle: sqlalchemy.sql functions +meta: Python example code that shows how to use the functions callable from the sqlalchemy.sql module of the SQLAlchemy project. + + +`functions` is a callable within the `sqlalchemy.sql` module of the SQLAlchemy project. + +ClauseElement, +Select, +column, +expression, +extract, +operators, +schema, +select, +sqltypes, +and table +are several other callables with code examples from the same `sqlalchemy.sql` package. + +## Example 1 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / functions.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./functions.py) + +```python +# functions.py +import re + +from sqlalchemy import inspect +~~from sqlalchemy.sql import functions +from sqlalchemy.sql.elements import ColumnElement +from sqlalchemy.ext.compiler import compiles + +from . import types +from . import elements + + +class TableRowElement(ColumnElement): + def __init__(self, selectable): + self.selectable = selectable + + @property + def _from_objects(self): + return [self.selectable] + + +class ST_AsGeoJSON(functions.GenericFunction): + + name = "ST_AsGeoJSON" + + def __init__(self, *args, **kwargs): + expr = kwargs.pop('expr', None) + args = list(args) + if expr is not None: + args = [expr] + args + for idx, element in enumerate(args): +~~ if isinstance(element, functions.Function): + continue + elif isinstance(element, elements.HasFunction): + if element.extended: + func_name = element.geom_from_extended_version + func_args = [element.data] + else: + func_name = element.geom_from + func_args = [element.data, element.srid] + args[idx] = getattr(functions.func, func_name)(*func_args) + else: + try: + insp = inspect(element) + if hasattr(insp, "selectable"): + args[idx] = TableRowElement(insp.selectable) + except Exception: + continue + +~~ functions.GenericFunction.__init__(self, *args, **kwargs) + + __doc__ = ( + 'Return the geometry as a GeoJSON "geometry" object, or the row as a ' + 'GeoJSON feature" object (PostGIS 3 only). (Cf GeoJSON specifications RFC ' + '7946). 2D and 3D Geometries are both supported. GeoJSON only support SFS ' + '1.1 geometry types (no curve support for example). ' + 'See https://postgis.net/docs/ST_AsGeoJSON.html') + + +@compiles(TableRowElement) +def _compile_table_row_thing(element, compiler, **kw): + + compiled = compiler.process(list(element.selectable.columns)[0], **kw) + + schema = getattr(element.selectable, "schema", "") + name = element.selectable.name + pattern = r"(.?%s.?\.)?(.?%s.?)\." % (schema, name) + m = re.match(pattern, compiled) + if m: + return m.group(2) + + return compiled.split(".")[0] + + +class GenericFunction(functions.GenericFunction): + + _register = False + + def __init__(self, *args, **kwargs): + expr = kwargs.pop('expr', None) + args = list(args) + if expr is not None: + args = [expr] + args + for idx, elem in enumerate(args): + if isinstance(elem, elements.HasFunction): + if elem.extended: + func_name = elem.geom_from_extended_version + func_args = [elem.data] + else: + func_name = elem.geom_from + func_args = [elem.data, elem.srid] + args[idx] = getattr(functions.func, func_name)(*func_args) +~~ functions.GenericFunction.__init__(self, *args, **kwargs) + + + + +_FUNCTIONS = [ + + ('ST_Collect', types.Geometry, + 'Return a specified ST_Geometry value from a collection of other geometries.'), + + ('ST_BdPolyFromText', types.Geometry, + 'Construct a Polygon given an arbitrary collection of closed linestrings' + 'as a MultiLineString Well-Known text representation.'), + + ('ST_BdMPolyFromText', types.Geometry, + 'Construct a MultiPolygon given an arbitrary collection of closed ' + 'linestrings as a MultiLineString text representation Well-Known text ' + 'representation.'), + + ('ST_Box2dFromGeoHash', types.Geometry, + 'Return a BOX2D from a GeoHash string.'), + + ('ST_GeogFromText', types.Geography, + 'Return a specified geography value from Well-Known Text representation ' + 'or extended (WKT).'), + + +## ... source file continues with no further functions examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-naming-conv.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-naming-conv.markdown new file mode 100644 index 000000000..bcb154186 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-naming-conv.markdown @@ -0,0 +1,125 @@ +title: sqlalchemy.sql.naming conv Example Code +category: page +slug: sqlalchemy-sql-naming-conv-examples +sortorder: 500031129 +toc: False +sidebartitle: sqlalchemy.sql.naming conv +meta: Python example code that shows how to use the conv callable from the sqlalchemy.sql.naming module of the SQLAlchemy project. + + +`conv` is a callable within the `sqlalchemy.sql.naming` module of the SQLAlchemy project. + + + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / operations / base.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/operations/base.py) + +```python +# base.py +from contextlib import contextmanager +import textwrap + +from . import batch +from . import schemaobj +from .. import util +from ..util import sqla_compat +from ..util.compat import exec_ +from ..util.compat import inspect_formatargspec +from ..util.compat import inspect_getargspec + +__all__ = ("Operations", "BatchOperations") + +try: +~~ from sqlalchemy.sql.naming import conv +except: + conv = None + + +class Operations(util.ModuleClsProxy): + + + _to_impl = util.Dispatcher() + + def __init__(self, migration_context, impl=None): + self.migration_context = migration_context + if impl is None: + self.impl = migration_context.impl + else: + self.impl = impl + + self.schema_obj = schemaobj.SchemaObjects(migration_context) + + @classmethod + def register_operation(cls, name, sourcename=None): + + def register(op_cls): + if sourcename is None: + fn = getattr(op_cls, name) + + +## ... source file abbreviated to get to conv examples ... + + + recreate, + copy_from, + table_args, + table_kwargs, + reflect_args, + reflect_kwargs, + naming_convention, + partial_reordering, + ) + batch_op = BatchOperations(self.migration_context, impl=impl) + yield batch_op + impl.flush() + + def get_context(self): + + return self.migration_context + + def invoke(self, operation): + fn = self._to_impl.dispatch( + operation, self.migration_context.impl.__dialect__ + ) + return fn(self, operation) + + def f(self, name): + if conv: +~~ return conv(name) + else: + raise NotImplementedError( + "op.f() feature requires SQLAlchemy 0.9.4 or greater." + ) + + def inline_literal(self, value, type_=None): + r"""Produce an 'inline literal' expression, suitable for + using in an INSERT, UPDATE, or DELETE statement. + + When using Alembic in "offline" mode, CRUD operations + aren't compatible with SQLAlchemy's default behavior surrounding + literal values, + which is that they are converted into bound values and passed + separately into the ``execute()`` method of the DBAPI cursor. + An offline SQL + script needs to have these rendered inline. While it should + always be noted that inline literal values are an **enormous** + security hole in an application that handles untrusted input, + a schema migration is not run in this context, so + literals are safe to render inline, with the caveat that + advanced types like dates may not be supported directly + by SQLAlchemy. + + See :meth:`.execute` for an example usage of + + +## ... source file continues with no further conv examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-operators.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-operators.markdown new file mode 100644 index 000000000..9af0e7212 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-operators.markdown @@ -0,0 +1,276 @@ +title: sqlalchemy.sql operators Example Code +category: page +slug: sqlalchemy-sql-operators-examples +sortorder: 500031113 +toc: False +sidebartitle: sqlalchemy.sql operators +meta: Python example code that shows how to use the operators callable from the sqlalchemy.sql module of the SQLAlchemy project. + + +`operators` is a callable within the `sqlalchemy.sql` module of the SQLAlchemy project. + +ClauseElement, +Select, +column, +expression, +extract, +functions, +schema, +select, +sqltypes, +and table +are several other callables with code examples from the same `sqlalchemy.sql` package. + +## Example 1 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / comparator.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./comparator.py) + +```python +# comparator.py + +from sqlalchemy import types as sqltypes +from sqlalchemy.types import UserDefinedType +from sqlalchemy.dialects.postgresql import DOUBLE_PRECISION +~~from sqlalchemy.sql import operators +try: + from sqlalchemy.sql.functions import _FunctionGenerator +except ImportError: # SQLA < 0.9 # pragma: no cover + from sqlalchemy.sql.expression import _FunctionGenerator + + +~~INTERSECTS = operators.custom_op('&&') +~~OVERLAPS_OR_TO_LEFT = operators.custom_op('&<') +~~OVERLAPS_OR_TO_RIGHT = operators.custom_op('&>') +~~OVERLAPS_OR_BELOW = operators.custom_op('&<|') +~~TO_LEFT = operators.custom_op('<<') +~~BELOW = operators.custom_op('<<|') +~~TO_RIGHT = operators.custom_op('>>') +~~CONTAINED = operators.custom_op('@') +~~OVERLAPS_OR_ABOVE = operators.custom_op('|&>') +~~ABOVE = operators.custom_op('|>>') +~~CONTAINS = operators.custom_op('-') +~~SAME = operators.custom_op('-=') +~~DISTANCE_CENTROID = operators.custom_op('<->') +~~DISTANCE_BOX = operators.custom_op('<#>') + + +class BaseComparator(UserDefinedType.Comparator): + + key = None + + def __getattr__(self, name): + + + if not name.lower().startswith('st_'): + raise AttributeError + + + func_ = _FunctionGenerator(expr=self.expr) + return getattr(func_, name) + + def intersects(self, other): + return self.operate(INTERSECTS, other, result_type=sqltypes.Boolean) + + def overlaps_or_to_left(self, other): + return self.operate(OVERLAPS_OR_TO_LEFT, other, + result_type=sqltypes.Boolean) + + def overlaps_or_to_right(self, other): + + +## ... source file continues with no further operators examples... + +``` + + +## Example 2 from SQLAlchemy Mixins +[SQLAlchemy Mixins](https://github.com/absent1706/sqlalchemy-mixins) +([PyPI package information](https://pypi.org/project/sqlalchemy-mixins/)) +is a collection of +[mixins](https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful) +useful for extending [SQLAlchemy](/sqlalchemy.html) and simplifying +your [database](/databases.html)-interacting code for some common +use cases. SQLAlchemy Mixins is open sourced under the +[MIT license](https://github.com/absent1706/sqlalchemy-mixins/blob/master/LICENSE.txt). + +[**SQLAlchemy Mixins / sqlalchemy_mixins / smartquery.py**](https://github.com/absent1706/sqlalchemy-mixins/blob/master/sqlalchemy_mixins/./smartquery.py) + +```python +# smartquery.py +try: + from typing import List +except ImportError: # pragma: no cover + pass + +from collections import OrderedDict + +import sqlalchemy +from sqlalchemy import asc, desc, inspect +from sqlalchemy.orm import aliased, contains_eager +from sqlalchemy.orm.util import AliasedClass +~~from sqlalchemy.sql import operators, extract + +from .eagerload import _flatten_schema, _eager_expr_from_flat_schema, \ + EagerLoadMixin +from .inspection import InspectionMixin +from .utils import classproperty + +RELATION_SPLITTER = '___' +OPERATOR_SPLITTER = '__' + +DESC_PREFIX = '-' + + +def _parse_path_and_make_aliases(entity, entity_path, attrs, aliases): + relations = {} + for attr in attrs: + if RELATION_SPLITTER in attr: + relation_name, nested_attr = attr.split(RELATION_SPLITTER, 1) + if relation_name in relations: + relations[relation_name].append(nested_attr) + else: + relations[relation_name] = [nested_attr] + + for relation_name, nested_attrs in relations.items(): + path = entity_path + RELATION_SPLITTER + relation_name \ + + +## ... source file abbreviated to get to operators examples ... + + + attr = attr.lstrip(DESC_PREFIX) + parts = attr.rsplit(RELATION_SPLITTER, 1) + entity, attr_name = aliases[parts[0]][0], prefix + parts[1] + else: + entity, attr_name = root_cls, attr + try: + query = query.order_by(*entity.order_expr(attr_name)) + except KeyError as e: + raise KeyError("Incorrect order path `{}`: {}".format(attr, e)) + + if schema: + flat_schema = _flatten_schema(schema) + not_loaded_part = {path: v for path, v in flat_schema.items() + if path not in loaded_paths} + query = query.options(*_eager_expr_from_flat_schema( + not_loaded_part)) + + return query + + +class SmartQueryMixin(InspectionMixin, EagerLoadMixin): + __abstract__ = True + + _operators = { + 'isnull': lambda c, v: (c == None) if v else (c != None), +~~ 'exact': operators.eq, +~~ 'ne': operators.ne, # not equal or is not (for None) + +~~ 'gt': operators.gt, # greater than , > +~~ 'ge': operators.ge, # greater than or equal, >= +~~ 'lt': operators.lt, # lower than, < +~~ 'le': operators.le, # lower than or equal, <= + +~~ 'in': operators.in_op, +~~ 'notin': operators.notin_op, + 'between': lambda c, v: c.between(v[0], v[1]), + +~~ 'like': operators.like_op, +~~ 'ilike': operators.ilike_op, +~~ 'startswith': operators.startswith_op, + 'istartswith': lambda c, v: c.ilike(v + '%'), +~~ 'endswith': operators.endswith_op, + 'iendswith': lambda c, v: c.ilike('%' + v), + 'contains': lambda c, v: c.ilike('%{v}%'.format(v=v)), + + 'year': lambda c, v: extract('year', c) == v, + 'year_ne': lambda c, v: extract('year', c) != v, + 'year_gt': lambda c, v: extract('year', c) > v, + 'year_ge': lambda c, v: extract('year', c) >= v, + 'year_lt': lambda c, v: extract('year', c) < v, + 'year_le': lambda c, v: extract('year', c) <= v, + + 'month': lambda c, v: extract('month', c) == v, + 'month_ne': lambda c, v: extract('month', c) != v, + 'month_gt': lambda c, v: extract('month', c) > v, + 'month_ge': lambda c, v: extract('month', c) >= v, + 'month_lt': lambda c, v: extract('month', c) < v, + 'month_le': lambda c, v: extract('month', c) <= v, + + 'day': lambda c, v: extract('day', c) == v, + 'day_ne': lambda c, v: extract('day', c) != v, + 'day_gt': lambda c, v: extract('day', c) > v, + 'day_ge': lambda c, v: extract('day', c) >= v, + 'day_lt': lambda c, v: extract('day', c) < v, + 'day_le': lambda c, v: extract('day', c) <= v, + } + + +## ... source file abbreviated to get to operators examples ... + + + @classproperty + def sortable_attributes(cls): + return cls.columns + cls.hybrid_properties + + @classmethod + def filter_expr(cls_or_alias, **filters): + if isinstance(cls_or_alias, AliasedClass): + mapper, cls = cls_or_alias, inspect(cls_or_alias).mapper.class_ + else: + mapper = cls = cls_or_alias + + expressions = [] + valid_attributes = cls.filterable_attributes + for attr, value in filters.items(): + if attr in cls.hybrid_methods: + method = getattr(cls, attr) + expressions.append(method(value, mapper=mapper)) + else: + if OPERATOR_SPLITTER in attr: + attr_name, op_name = attr.rsplit(OPERATOR_SPLITTER, 1) + if op_name not in cls._operators: + raise KeyError('Expression `{}` has incorrect ' + 'operator `{}`'.format(attr, op_name)) + op = cls._operators[op_name] + else: +~~ attr_name, op = attr, operators.eq + + if attr_name not in valid_attributes: + raise KeyError('Expression `{}` ' + 'has incorrect attribute `{}`' + .format(attr, attr_name)) + + column = getattr(mapper, attr_name) + expressions.append(op(column, value)) + + return expressions + + @classmethod + def order_expr(cls_or_alias, *columns): + if isinstance(cls_or_alias, AliasedClass): + mapper, cls = cls_or_alias, inspect(cls_or_alias).mapper.class_ + else: + mapper = cls = cls_or_alias + + expressions = [] + for attr in columns: + fn, attr = (desc, attr[1:]) if attr.startswith(DESC_PREFIX) \ + else (asc, attr) + if attr not in cls.sortable_attributes: + raise KeyError('Cant order {} by {}'.format(cls, attr)) + + +## ... source file continues with no further operators examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-schema-column.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-schema-column.markdown new file mode 100644 index 000000000..da5ef47ef --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-schema-column.markdown @@ -0,0 +1,126 @@ +title: sqlalchemy.sql.schema Column Example Code +category: page +slug: sqlalchemy-sql-schema-column-examples +sortorder: 500031130 +toc: False +sidebartitle: sqlalchemy.sql.schema Column +meta: Example code for understanding how to use the Column class from the sqlalchemy.sql.schema module of the SQLAlchemy project. + + +`Column` is a class within the `sqlalchemy.sql.schema` module of the SQLAlchemy project. + +SchemaItem +is another callable from the `sqlalchemy.sql.schema` package with code examples. + +## Example 1 from databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + +[**databases / databases / backends / postgres.py**](https://github.com/encode/databases/blob/master/databases/backends/postgres.py) + +```python +# postgres.py +import logging +import typing +from collections.abc import Mapping + +import asyncpg +from sqlalchemy.dialects.postgresql import pypostgresql +from sqlalchemy.engine.interfaces import Dialect +from sqlalchemy.sql import ClauseElement +~~from sqlalchemy.sql.schema import Column +from sqlalchemy.types import TypeEngine + +from databases.core import LOG_EXTRA, DatabaseURL +from databases.interfaces import ConnectionBackend, DatabaseBackend, TransactionBackend + +logger = logging.getLogger("databases") + + +_result_processors = {} # type: dict + + +class PostgresBackend(DatabaseBackend): + def __init__( + self, database_url: typing.Union[DatabaseURL, str], **options: typing.Any + ) -> None: + self._database_url = DatabaseURL(database_url) + self._options = options + self._dialect = self._get_dialect() + self._pool = None + + def _get_dialect(self) -> Dialect: + dialect = pypostgresql.dialect(paramstyle="pyformat") + + dialect.implicit_returning = True + + +## ... source file abbreviated to get to Column examples ... + + + "_column_map_full", + ) + + def __init__( + self, + row: asyncpg.Record, + result_columns: tuple, + dialect: Dialect, + column_maps: typing.Tuple[ + typing.Mapping[typing.Any, typing.Tuple[int, TypeEngine]], + typing.Mapping[int, typing.Tuple[int, TypeEngine]], + typing.Mapping[str, typing.Tuple[int, TypeEngine]], + ], + ) -> None: + self._row = row + self._result_columns = result_columns + self._dialect = dialect + self._column_map, self._column_map_int, self._column_map_full = column_maps + + def values(self) -> typing.ValuesView: + return self._row.values() + + def __getitem__(self, key: typing.Any) -> typing.Any: + if len(self._column_map) == 0: # raw query + return self._row[key] +~~ elif isinstance(key, Column): + idx, datatype = self._column_map_full[str(key)] + elif isinstance(key, int): + idx, datatype = self._column_map_int[key] + else: + idx, datatype = self._column_map[key] + raw = self._row[idx] + try: + processor = _result_processors[datatype] + except KeyError: + processor = datatype.result_processor(self._dialect, None) + _result_processors[datatype] = processor + + if processor is not None: + return processor(raw) + return raw + + def __iter__(self) -> typing.Iterator: + return iter(self._row.keys()) + + def __len__(self) -> int: + return len(self._row) + + +class PostgresConnection(ConnectionBackend): + + +## ... source file continues with no further Column examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-schema-schemaitem.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-schema-schemaitem.markdown new file mode 100644 index 000000000..870442e75 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-schema-schemaitem.markdown @@ -0,0 +1,121 @@ +title: sqlalchemy.sql.schema SchemaItem Example Code +category: page +slug: sqlalchemy-sql-schema-schemaitem-examples +sortorder: 500031131 +toc: False +sidebartitle: sqlalchemy.sql.schema SchemaItem +meta: Example code for understanding how to use the SchemaItem class from the sqlalchemy.sql.schema module of the SQLAlchemy project. + + +`SchemaItem` is a class within the `sqlalchemy.sql.schema` module of the SQLAlchemy project. + +Column +is another callable from the `sqlalchemy.sql.schema` package with code examples. + +## Example 1 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / api.py**](https://github.com/python-gino/gino/blob/master/src/gino/./api.py) + +```python +# api.py +import weakref + +import sqlalchemy as sa +from sqlalchemy.engine.url import make_url, URL +from sqlalchemy.sql.base import Executable +~~from sqlalchemy.sql.schema import SchemaItem + +from . import json_support +from .crud import CRUDModel +from .declarative import declarative_base, declared_attr +from .exceptions import UninitializedError +from .schema import GinoSchemaVisitor, patch_schema + + +class GinoExecutor: + + __slots__ = ("_query",) + + def __init__(self, query): + self._query = query + + @property + def query(self): + return self._query + + def model(self, model): + if model is not None: + model = weakref.ref(model) + return self.execution_options(model=model) + + + +## ... source file abbreviated to get to SchemaItem examples ... + + + self, + bind=None, + model_classes=None, + query_ext=True, + schema_ext=True, + ext=True, + **kwargs + ): + super().__init__(bind=bind, **kwargs) + if model_classes is None: + model_classes = self.model_base_classes + self._model = declarative_base(self, model_classes) + self.declared_attr = declared_attr + self.quoted_name = sa.sql.quoted_name + from .bakery import Bakery + + self._bakery = Bakery() + for mod in json_support, sa: + for key in mod.__all__: + if not hasattr(self, key) and key not in self.no_delegate: + setattr(self, key, getattr(mod, key)) + if ext: + if query_ext: + Executable.gino = property(self.query_executor) + if schema_ext: +~~ SchemaItem.gino = property(self.schema_visitor) + patch_schema(self) + + @property + def Model(self): + return self._model + + @property + def bind(self): + if self._bind is None: + return _PlaceHolder(UninitializedError("Gino engine is not initialized.")) + return self._bind + + @bind.setter + def bind(self, bind): + self._bind = bind + + async def set_bind(self, bind, loop=None, **kwargs): + if isinstance(bind, str): + bind = make_url(bind) + if isinstance(bind, URL): + from . import create_engine + + bind = await create_engine(bind, loop=loop, bakery=self._bakery, **kwargs) + self.bind = bind + + +## ... source file continues with no further SchemaItem examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-schema.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-schema.markdown new file mode 100644 index 000000000..93157e8b5 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-schema.markdown @@ -0,0 +1,134 @@ +title: sqlalchemy.sql schema Example Code +category: page +slug: sqlalchemy-sql-schema-examples +sortorder: 500031114 +toc: False +sidebartitle: sqlalchemy.sql schema +meta: Python example code that shows how to use the schema callable from the sqlalchemy.sql module of the SQLAlchemy project. + + +`schema` is a callable within the `sqlalchemy.sql` module of the SQLAlchemy project. + +ClauseElement, +Select, +column, +expression, +extract, +functions, +operators, +select, +sqltypes, +and table +are several other callables with code examples from the same `sqlalchemy.sql` package. + +## Example 1 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / engine.py**](https://github.com/python-gino/gino/blob/master/src/gino/./engine.py) + +```python +# engine.py +import asyncio +import collections +import functools +import sys +import time +from contextvars import ContextVar + +from sqlalchemy.cutils import _distill_params +from sqlalchemy.engine import Engine, Connection +~~from sqlalchemy.sql import schema + +from .aiocontextvars import patch_asyncio +from .exceptions import MultipleResultsFound, NoResultFound +from .transaction import GinoTransaction + +patch_asyncio() + + +class _BaseDBAPIConnection: + _reset_agent = None + gino_conn = None + + def __init__(self, cursor_cls): + self._cursor_cls = cursor_cls + self._closed = False + + def commit(self): + pass + + def cursor(self): + return self._cursor_cls(self) + + @property + def raw_connection(self): + + +## ... source file abbreviated to get to schema examples ... + + + self._tx_ctx = args + + async def __aenter__(self): + conn = await self._conn_ctx.__aenter__() + try: + args, kwargs = self._tx_ctx + self._tx_ctx = conn.transaction(*args, **kwargs) + return await self._tx_ctx.__aenter__() + except Exception: + await self._conn_ctx.__aexit__(*sys.exc_info()) + raise + + async def __aexit__(self, *exc_info): + try: + tx, self._tx_ctx = self._tx_ctx, None + return await tx.__aexit__(*exc_info) + except Exception: + exc_info = sys.exc_info() + raise + finally: + await self._conn_ctx.__aexit__(*exc_info) + + +class GinoConnection: + +~~ schema_for_object = schema._schema_getter(None) + + def __init__(self, dialect, sa_conn, stack=None): + self._dialect = dialect + self._sa_conn = sa_conn + self._stack = stack + + @property + def _dbapi_conn(self): + return self._sa_conn.connection + + @property + def raw_connection(self): + return self._dbapi_conn.raw_connection + + async def get_raw_connection(self, *, timeout=None): + return await self._dbapi_conn.acquire(timeout=timeout) + + async def release(self, *, permanent=True): + if permanent and self._stack is not None: + dbapi_conn = self._stack.remove(lambda x: x.gino_conn is self) + if dbapi_conn: + await dbapi_conn.release(True) + else: + raise ValueError("This connection is already released.") + + +## ... source file continues with no further schema examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-select.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-select.markdown new file mode 100644 index 000000000..93a7cde3c --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-select.markdown @@ -0,0 +1,160 @@ +title: sqlalchemy.sql select Example Code +category: page +slug: sqlalchemy-sql-select-examples +sortorder: 500031115 +toc: False +sidebartitle: sqlalchemy.sql select +meta: Python example code that shows how to use the select callable from the sqlalchemy.sql module of the SQLAlchemy project. + + +`select` is a callable within the `sqlalchemy.sql` module of the SQLAlchemy project. + +ClauseElement, +column, +expression, +extract, +functions, +operators, +schema, +select, +sqltypes, +and table +are several other callables with code examples from the same `sqlalchemy.sql` package. + +## Example 1 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / __init__.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./__init__.py) + +```python +# __init__.py +from .types import ( # NOQA + Geometry, + Geography, + Raster + ) + +from .elements import ( # NOQA + WKTElement, + WKBElement, + RasterElement + ) + +from .exc import ArgumentError + +from . import functions # NOQA +from . import types # NOQA + +from sqlalchemy import Table, event +~~from sqlalchemy.sql import select, func, expression + + +def _setup_ddl_event_listeners(): + @event.listens_for(Table, "before_create") + def before_create(target, connection, **kw): + dispatch("before-create", target, connection) + + @event.listens_for(Table, "after_create") + def after_create(target, connection, **kw): + dispatch("after-create", target, connection) + + @event.listens_for(Table, "before_drop") + def before_drop(target, connection, **kw): + dispatch("before-drop", target, connection) + + @event.listens_for(Table, "after_drop") + def after_drop(target, connection, **kw): + dispatch("after-drop", target, connection) + + def dispatch(event, table, bind): + if event in ('before-create', 'before-drop'): + gis_cols = [c for c in table.c if + isinstance(c.type, Geometry) and + c.type.management is True] + + regular_cols = [x for x in table.c if x not in gis_cols] + + table.info["_saved_columns"] = table.c + + column_collection = expression.ColumnCollection() + for col in regular_cols: + column_collection.add(col) + table.columns = column_collection + + if event == 'before-drop': + for c in gis_cols: + if bind.dialect.name == 'sqlite': + drop_func = 'DiscardGeometryColumn' + elif bind.dialect.name == 'postgresql': + drop_func = 'DropGeometryColumn' + else: + raise ArgumentError('dialect {} is not supported'.format(bind.dialect.name)) + args = [table.schema] if table.schema else [] + args.extend([table.name, c.name]) + +~~ stmt = select([getattr(func, drop_func)(*args)]) + stmt = stmt.execution_options(autocommit=True) + bind.execute(stmt) + + elif event == 'after-create': + table.columns = table.info.pop('_saved_columns') + + for c in table.c: + if isinstance(c.type, Geometry) and c.type.management is True: + args = [table.schema] if table.schema else [] + args.extend([ + table.name, + c.name, + c.type.srid, + c.type.geometry_type, + c.type.dimension + ]) + if c.type.use_typmod is not None: + args.append(c.type.use_typmod) + +~~ stmt = select([func.AddGeometryColumn(*args)]) + stmt = stmt.execution_options(autocommit=True) + bind.execute(stmt) + + if isinstance(c.type, (Geometry, Geography)) and \ + c.type.spatial_index is True: + if bind.dialect.name == 'sqlite': +~~ stmt = select([func.CreateSpatialIndex(table.name, c.name)]) + stmt = stmt.execution_options(autocommit=True) + bind.execute(stmt) + elif bind.dialect.name == 'postgresql': + if table.schema: + bind.execute('CREATE INDEX "idx_%s_%s" ON "%s"."%s" ' + 'USING GIST ("%s")' % + (table.name, c.name, table.schema, + table.name, c.name)) + else: + bind.execute('CREATE INDEX "idx_%s_%s" ON "%s" ' + 'USING GIST ("%s")' % + (table.name, c.name, table.name, c.name)) + else: + raise ArgumentError('dialect {} is not supported'.format(bind.dialect.name)) + + if isinstance(c.type, Raster) and c.type.spatial_index is True: + if table.schema: + bind.execute('CREATE INDEX "idx_%s_%s" ON "%s"."%s" ' + 'USING GIST (ST_ConvexHull("%s"))' % + (table.name, c.name, table.schema, + table.name, c.name)) + else: + bind.execute('CREATE INDEX "idx_%s_%s" ON "%s" ' + 'USING GIST (ST_ConvexHull("%s"))' % + + +## ... source file continues with no further select examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-sqltypes-nulltype.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-sqltypes-nulltype.markdown new file mode 100644 index 000000000..65e3dc2f4 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-sqltypes-nulltype.markdown @@ -0,0 +1,131 @@ +title: sqlalchemy.sql.sqltypes NullType Example Code +category: page +slug: sqlalchemy-sql-sqltypes-nulltype-examples +sortorder: 500031132 +toc: False +sidebartitle: sqlalchemy.sql.sqltypes NullType +meta: Example code for understanding how to use the NullType class from the sqlalchemy.sql.sqltypes module of the SQLAlchemy project. + + +`NullType` is a class within the `sqlalchemy.sql.sqltypes` module of the SQLAlchemy project. + +NullType +is another callable from the `sqlalchemy.sql.sqltypes` package with code examples. + +## Example 1 from sqlacodegen +[sqlacodegen](https://github.com/agronholm/sqlacodegen) +([PyPI package information](https://pypi.org/project/sqlacodegen/)) +is a tool for +reading from an existing [relational database](/databases.html) to +generate code to create [SQLAlchemy](/sqlalchemy.html) models based +on that database. The project is primarily written and maintained +by [Alex Grönholm (agronholm)](https://github.com/agronholm) and it +is open sourced under the +[MIT license](https://github.com/agronholm/sqlacodegen/blob/master/LICENSE). + +[**sqlacodegen / sqlacodegen / codegen.py**](https://github.com/agronholm/sqlacodegen/blob/master/sqlacodegen/./codegen.py) + +```python +# codegen.py +from __future__ import unicode_literals, division, print_function, absolute_import + +import inspect +import re +import sys +from collections import defaultdict +from importlib import import_module +from inspect import ArgSpec +from keyword import iskeyword + +import sqlalchemy +import sqlalchemy.exc +from sqlalchemy import ( + Enum, ForeignKeyConstraint, PrimaryKeyConstraint, CheckConstraint, UniqueConstraint, Table, + Column, Float) +from sqlalchemy.schema import ForeignKey +~~from sqlalchemy.sql.sqltypes import NullType +from sqlalchemy.types import Boolean, String +from sqlalchemy.util import OrderedDict + +try: + from sqlalchemy import ARRAY +except ImportError: + from sqlalchemy.dialects.postgresql import ARRAY + +try: + from sqlalchemy import Computed +except ImportError: + Computed = None + +try: + import geoalchemy2 # noqa: F401 +except ImportError: + pass + +_re_boolean_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \(0, 1\)") +_re_column_name = re.compile(r'(?:(["`]?)(?:.*)\1\.)?(["`]?)(.*)\2') +_re_enum_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \((.+)\)") +_re_enum_item = re.compile(r"'(.*?)(?ClauseElement, +Select, +column, +expression, +extract, +functions, +operators, +schema, +select, +and table +are several other callables with code examples from the same `sqlalchemy.sql` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / oracle.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/oracle.py) + +```python +# oracle.py +from sqlalchemy.ext.compiler import compiles +~~from sqlalchemy.sql import sqltypes + +from .base import AddColumn +from .base import alter_table +from .base import ColumnComment +from .base import ColumnDefault +from .base import ColumnName +from .base import ColumnNullable +from .base import ColumnType +from .base import format_column_name +from .base import format_server_default +from .base import format_table_name +from .base import format_type +from .base import RenameTable +from .impl import DefaultImpl + + +class OracleImpl(DefaultImpl): + __dialect__ = "oracle" + transactional_ddl = False + batch_separator = "/" + command_terminator = "" + type_synonyms = DefaultImpl.type_synonyms + ( + {"VARCHAR", "VARCHAR2"}, + {"BIGINT", "INTEGER", "SMALLINT", "DECIMAL", "NUMERIC", "NUMBER"}, + + +## ... source file abbreviated to get to sqltypes examples ... + + +def visit_column_name(element, compiler, **kw): + return "%s RENAME COLUMN %s TO %s" % ( + alter_table(compiler, element.table_name, element.schema), + format_column_name(compiler, element.column_name), + format_column_name(compiler, element.newname), + ) + + +@compiles(ColumnDefault, "oracle") +def visit_column_default(element, compiler, **kw): + return "%s %s %s" % ( + alter_table(compiler, element.table_name, element.schema), + alter_column(compiler, element.column_name), + "DEFAULT %s" % format_server_default(compiler, element.default) + if element.default is not None + else "DEFAULT NULL", + ) + + +@compiles(ColumnComment, "oracle") +def visit_column_comment(element, compiler, **kw): + ddl = "COMMENT ON COLUMN {table_name}.{column_name} IS {comment}" + + comment = compiler.sql_compiler.render_literal_value( + (element.comment if element.comment is not None else ""), +~~ sqltypes.String(), + ) + + return ddl.format( + table_name=element.table_name, + column_name=element.column_name, + comment=comment, + ) + + +@compiles(RenameTable, "oracle") +def visit_rename_table(element, compiler, **kw): + return "%s RENAME TO %s" % ( + alter_table(compiler, element.table_name, element.schema), + format_table_name(compiler, element.new_table_name, None), + ) + + +def alter_column(compiler, name): + return "MODIFY %s" % format_column_name(compiler, name) + + +def add_column(compiler, column, **kw): + return "ADD %s" % compiler.get_column_specification(column, **kw) + + + +## ... source file continues with no further sqltypes examples... + +``` + + +## Example 2 from GINO +[GINO](https://github.com/fantix/gino) +([project documentation](https://python-gino.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/gino/)) +is an [object-relational mapper (ORM)](/object-relational-mappers-orms.html) +built on SQLAlchemy that is non-blocking and therefore designed to work properly +with asynchronously-run code, for example, an application written with +[asyncio](https://docs.python.org/3/library/asyncio.html). + +GINO is open sourced under the [BSD License](https://github.com/python-gino/gino/blob/master/LICENSE). + +[**GINO / src/gino / dialects / asyncpg.py**](https://github.com/python-gino/gino/blob/master/src/gino/dialects/asyncpg.py) + +```python +# asyncpg.py +import inspect +import itertools +import time +import warnings + +import asyncpg +from sqlalchemy import util, exc, sql +from sqlalchemy.dialects.postgresql import ( # noqa: F401 + ARRAY, + CreateEnumType, + DropEnumType, + JSON, + JSONB, + json, +) +from sqlalchemy.dialects.postgresql.base import ( + ENUM, + PGCompiler, + PGDialect, + PGExecutionContext, +) +~~from sqlalchemy.sql import sqltypes + +from . import base + +try: + import click +except ImportError: + click = None +JSON_COLTYPE = 114 +JSONB_COLTYPE = 3802 + + +class AsyncpgDBAPI(base.BaseDBAPI): + Error = asyncpg.PostgresError, asyncpg.InterfaceError + + +class AsyncpgCompiler(PGCompiler): + @property + def bindtemplate(self): + return self._bindtemplate + + @bindtemplate.setter + def bindtemplate(self, val): + self._bindtemplate = val.replace(":", "$") + + + +## ... source file abbreviated to get to sqltypes examples ... + + + return [util.text_type(elem) for elem in value] + + return process + + +class AsyncpgDialect(PGDialect, base.AsyncDialectMixin): + driver = "asyncpg" + supports_native_decimal = True + dbapi_class = AsyncpgDBAPI + statement_compiler = AsyncpgCompiler + execution_ctx_cls = AsyncpgExecutionContext + cursor_cls = DBAPICursor + init_kwargs = set( + itertools.chain( + ("bakery", "prebake"), + *[ + inspect.getfullargspec(f).kwonlydefaults.keys() + for f in [asyncpg.create_pool, asyncpg.connect] + ], + ) + ) + colspecs = util.update_copy( + PGDialect.colspecs, + { + ENUM: AsyncEnum, +~~ sqltypes.Enum: AsyncEnum, +~~ sqltypes.NullType: GinoNullType, +~~ sqltypes.JSON.JSONPathType: AsyncpgJSONPathType, + }, + ) + + def __init__(self, *args, bakery=None, **kwargs): + self._pool_kwargs = {} + self._init_hook = None + for k in self.init_kwargs: + if k in kwargs: + if k == "init": + self._init_hook = kwargs.pop(k) + else: + self._pool_kwargs[k] = kwargs.pop(k) + super().__init__(*args, **kwargs) + self._init_mixin(bakery) + + async def init_pool(self, url, loop, pool_class=None): + if pool_class is None: + pool_class = Pool + return await pool_class( + url, loop, bakery=self._bakery, init=self.on_connect(), **self._pool_kwargs + ) + + def transaction(self, raw_conn, args, kwargs): + return Transaction(raw_conn.transaction(*args, **kwargs)) + + +## ... source file abbreviated to get to sqltypes examples ... + + + return self._init_hook + + async def set_isolation_level(self, connection, level): + level = level.replace("_", " ") + if level not in self._isolation_lookup: + raise exc.ArgumentError( + "Invalid value '%s' for isolation_level. " + "Valid isolation levels for %s are %s" + % (level, self.name, ", ".join(self._isolation_lookup)) + ) + await connection.execute( + "SET SESSION CHARACTERISTICS AS TRANSACTION " "ISOLATION LEVEL %s" % level + ) + await connection.execute("COMMIT") + + async def get_isolation_level(self, connection): + val = await connection.fetchval("show transaction isolation level") + return val.upper() + + async def has_schema(self, connection, schema): + row = await connection.first( + sql.text( + "select nspname from pg_namespace " "where lower(nspname)=:schema" + ).bindparams( + sql.bindparam( +~~ "schema", util.text_type(schema.lower()), type_=sqltypes.Unicode, + ) + ) + ) + + return bool(row) + + async def has_table(self, connection, table_name, schema=None): + if schema is None: + row = await connection.first( + sql.text( + "select relname from pg_class c join pg_namespace n on " + "n.oid=c.relnamespace where " + "pg_catalog.pg_table_is_visible(c.oid) " + "and relname=:name" + ).bindparams( + sql.bindparam( +~~ "name", util.text_type(table_name), type_=sqltypes.Unicode + ), + ) + ) + else: + row = await connection.first( + sql.text( + "select relname from pg_class c join pg_namespace n on " + "n.oid=c.relnamespace where n.nspname=:schema and " + "relname=:name" + ).bindparams( + sql.bindparam( +~~ "name", util.text_type(table_name), type_=sqltypes.Unicode, + ), + sql.bindparam( +~~ "schema", util.text_type(schema), type_=sqltypes.Unicode, + ), + ) + ) + return bool(row) + + async def has_sequence(self, connection, sequence_name, schema=None): + if schema is None: + row = await connection.first( + sql.text( + "SELECT relname FROM pg_class c join pg_namespace n on " + "n.oid=c.relnamespace where relkind='S' and " + "n.nspname=current_schema() " + "and relname=:name" + ).bindparams( + sql.bindparam( +~~ "name", util.text_type(sequence_name), type_=sqltypes.Unicode, + ) + ) + ) + else: + row = await connection.first( + sql.text( + "SELECT relname FROM pg_class c join pg_namespace n on " + "n.oid=c.relnamespace where relkind='S' and " + "n.nspname=:schema and relname=:name" + ).bindparams( + sql.bindparam( +~~ "name", util.text_type(sequence_name), type_=sqltypes.Unicode, + ), + sql.bindparam( +~~ "schema", util.text_type(schema), type_=sqltypes.Unicode, + ), + ) + ) + + return bool(row) + + async def has_type(self, connection, type_name, schema=None): + if schema is not None: + query = """ + SELECT EXISTS ( + SELECT * FROM pg_catalog.pg_type t, pg_catalog.pg_namespace n + WHERE t.typnamespace = n.oid + AND t.typname = :typname + AND n.nspname = :nspname + ) + SELECT EXISTS ( + SELECT * FROM pg_catalog.pg_type t + WHERE t.typname = :typname + AND pg_type_is_visible(t.oid) + ) + + + +## ... source file continues with no further sqltypes examples... + +``` + + +## Example 3 from sandman2 +[sandman2](https://github.com/jeffknupp/sandman2) +([project documentation](https://sandman2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/sandman2/)) +is a code library for automatically generating +[RESTful APIs](/application-programming-interfaces.html) from +existing database schemas. This approach is handy for solving +straightforward situations where you want to put an abstraction +layer between one or more applications and your +[relational database](/databases.html) to prevent or reduce +direct database access. + +The sandman2 project is provided under the +[Apache License 2.0](https://github.com/jeffknupp/sandman2/blob/master/LICENSE). + +[**sandman2 / sandman2 / app.py**](https://github.com/jeffknupp/sandman2/blob/master/sandman2/./app.py) + +```python +# app.py + +from flask import Flask, current_app, jsonify +~~from sqlalchemy.sql import sqltypes + +from sandman2.exception import ( + BadRequestException, + ForbiddenException, + NotFoundException, + NotAcceptableException, + NotImplementedException, + ConflictException, + ServerErrorException, + ServiceUnavailableException, + ) +from sandman2.service import Service +from sandman2.model import db, Model, AutomapModel +from sandman2.admin import CustomAdminView +from flask_admin import Admin +from flask_httpauth import HTTPBasicAuth + +auth = HTTPBasicAuth() + +def get_app( + database_uri, + exclude_tables=None, + user_models=None, + reflect_all=True, + + +## ... source file abbreviated to get to sqltypes examples ... + + +def _reflect_all(exclude_tables=None, admin=None, read_only=False, schema=None): + AutomapModel.prepare( # pylint:disable=maybe-no-member + db.engine, reflect=True, schema=schema) + for cls in AutomapModel.classes: + if exclude_tables and cls.__table__.name in exclude_tables: + continue + if read_only: + cls.__methods__ = {'GET'} + register_model(cls, admin) + + +def register_model(cls, admin=None): + cls.__url__ = '/{}'.format(cls.__name__.lower()) + service_class = type( + cls.__name__ + 'Service', + (Service,), + { + '__model__': cls, + }) + + cols = list(cls().__table__.primary_key.columns) + + primary_key_type = 'string' + if len(cols) == 1: + col_type = cols[0].type +~~ if isinstance(col_type, sqltypes.String): + primary_key_type = 'string' +~~ elif isinstance(col_type, sqltypes.Integer): + primary_key_type = 'int' +~~ elif isinstance(col_type, sqltypes.Numeric): + primary_key_type = 'float' + + register_service(service_class, primary_key_type) + if admin is not None: + admin.add_view(CustomAdminView(cls, db.session)) + + +def _register_user_models(user_models, admin=None, schema=None): + if any([issubclass(cls, AutomapModel) for cls in user_models]): + AutomapModel.prepare( # pylint:disable=maybe-no-member + db.engine, reflect=True, schema=schema) + + for user_model in user_models: + register_model(user_model, admin) + + + +## ... source file continues with no further sqltypes examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-table.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-table.markdown new file mode 100644 index 000000000..aa1b77129 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-table.markdown @@ -0,0 +1,471 @@ +title: sqlalchemy.sql table Example Code +category: page +slug: sqlalchemy-sql-table-examples +sortorder: 500031117 +toc: False +sidebartitle: sqlalchemy.sql table +meta: Python example code that shows how to use the table callable from the sqlalchemy.sql module of the SQLAlchemy project. + + +`table` is a callable within the `sqlalchemy.sql` module of the SQLAlchemy project. + +ClauseElement, +Select, +column, +expression, +extract, +functions, +operators, +schema, +select, +and sqltypes +are several other callables with code examples from the same `sqlalchemy.sql` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / operations / ops.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/operations/ops.py) + +```python +# ops.py +import re + +from sqlalchemy.types import NULLTYPE + +from . import schemaobj +from .base import BatchOperations +from .base import Operations +from .. import util +from ..util import sqla_compat + + +class MigrateOperation(object): + + @util.memoized_property + def info(self): + return {} + + _mutations = frozenset() + + +class AddConstraintOp(MigrateOperation): + + add_constraint_ops = util.Dispatcher() + + @property + def constraint_type(self): + raise NotImplementedError() + + @classmethod + def register_add_constraint(cls, type_): + def go(klass): + cls.add_constraint_ops.dispatch_for(type_)(klass.from_constraint) + return klass + + return go + + +## ... source file abbreviated to get to table examples ... + + + @classmethod + def bulk_insert(cls, operations, table, rows, multiinsert=True): + + op = cls(table, rows, multiinsert=multiinsert) + operations.invoke(op) + + +@Operations.register_operation("execute") +class ExecuteSQLOp(MigrateOperation): + + def __init__(self, sqltext, execution_options=None): + self.sqltext = sqltext + self.execution_options = execution_options + + @classmethod + def execute(cls, operations, sqltext, execution_options=None): + r"""Execute the given SQL using the current migration context. + + The given SQL can be a plain string, e.g.:: + + op.execute("INSERT INTO table (foo) VALUES ('some value')") + + Or it can be any kind of Core SQL Expression construct, such as + below where we use an update construct:: + +~~ from sqlalchemy.sql import table, column + from sqlalchemy import String + from alembic import op + +~~ account = table('account', + column('name', String) + ) + op.execute( + account.update().\\ + where(account.c.name==op.inline_literal('account 1')).\\ + values({'name':op.inline_literal('account 2')}) + ) + + Above, we made use of the SQLAlchemy + :func:`sqlalchemy.sql.expression.table` and + :func:`sqlalchemy.sql.expression.column` constructs to make a brief, + ad-hoc table construct just for our UPDATE statement. A full + :class:`-sqlalchemy.schema.Table` construct of course works perfectly + fine as well, though note it's a recommended practice to at least + ensure the definition of a table is self-contained within the migration + script, rather than imported from a module that may break compatibility + with older migrations. + + In a SQL script context, the statement is emitted directly to the + output stream. There is *no* return result, however, as this + function is oriented towards generating a change script + that can run in "offline" mode. Additionally, parameterized + statements are discouraged here, as they *will not work* in offline + mode. Above, we use :meth:`.inline_literal` where parameters are + unique=False, + **kw + ): + r"""Issue a "create index" instruction using the current + migration context. + + e.g.:: + + from alembic import op + op.create_index('ik_test', 't1', ['foo', 'bar']) + + Functional indexes can be produced by using the + :func:`sqlalchemy.sql.expression.text` construct:: + + from alembic import op + from sqlalchemy import text + op.create_index('ik_test', 't1', [text('lower(foo)')]) + + .. versionadded:: 0.6.7 support for making use of the + :func:`-sqlalchemy.sql.expression.text` construct in + conjunction with + :meth:`.Operations.create_index` in + order to produce functional expressions within CREATE INDEX. + + :param index_name: name of the index. +~~ :param table_name: name of the owning table. + :param columns: a list consisting of string column names and/or + :func:`-sqlalchemy.sql.expression.text` constructs. + :param schema: Optional schema name to operate within. To control + quoting of the schema outside of the default behavior, use + the SQLAlchemy construct + :class:`-sqlalchemy.sql.elements.quoted_name`. + + .. versionadded:: 0.7.0 'schema' can now accept a + :class:`-sqlalchemy.sql.elements.quoted_name` construct. + + :param unique: If True, create a unique index. + + :param quote: + Force quoting of this column's name on or off, corresponding + to ``True`` or ``False``. When left at its default + of ``None``, the column identifier will be quoted according to + whether the name is case sensitive (identifiers with at least one + upper case character are treated as case sensitive), or if it's a + reserved word. This flag is only needed to force quoting of a + reserved word which is not known by the SQLAlchemy dialect. + + :param \**kw: Additional keyword arguments not mentioned above are + dialect specific, and passed in the form + ``_``. + + +## ... source file abbreviated to get to table examples ... + + + schema_obj = schemaobj.SchemaObjects(migration_context) + + return schema_obj.index( + self.index_name, + self.table_name, + ["x"], + schema=self.schema, + **self.kw + ) + + @classmethod + @util._with_legacy_names( + [("name", "index_name"), ("tablename", "table_name")] + ) + def drop_index( + cls, operations, index_name, table_name=None, schema=None, **kw + ): + r"""Issue a "drop index" instruction using the current + migration context. + + e.g.:: + + drop_index("accounts") + + :param index_name: name of the index. +~~ :param table_name: name of the owning table. Some + backends such as Microsoft SQL Server require this. + :param schema: Optional schema name to operate within. To control + quoting of the schema outside of the default behavior, use + the SQLAlchemy construct + :class:`-sqlalchemy.sql.elements.quoted_name`. + + .. versionadded:: 0.7.0 'schema' can now accept a + :class:`-sqlalchemy.sql.elements.quoted_name` construct. + + :param \**kw: Additional keyword arguments not mentioned above are + dialect specific, and passed in the form + ``_``. + See the documentation regarding an individual dialect at + :ref:`dialect_toplevel` for detail on documented arguments. + + .. versionadded:: 0.9.5 Support for dialect-specific keyword + arguments for DROP INDEX + + .. versionchanged:: 0.8.0 The following positional argument names + have been changed: + + * name -> index_name + + current batch migration context. + + +## ... source file abbreviated to get to table examples ... + + + + .. versionchanged:: 0.8.0 The following positional argument names + have been changed: + + * name -> index_name + + + def __init__( + self, table_name, columns, schema=None, _orig_table=None, **kw + ): + self.table_name = table_name + self.columns = columns + self.schema = schema + self.kw = kw + self._orig_table = _orig_table + + def reverse(self): + return DropTableOp.from_table(self.to_table()) + + def to_diff_tuple(self): + return ("add_table", self.to_table()) + + @classmethod + def from_table(cls, table): + return cls( +~~ table.name, + list(table.c) + list(table.constraints), +~~ schema=table.schema, + _orig_table=table, + **table.kwargs + ) + + def to_table(self, migration_context=None): + if self._orig_table is not None: + return self._orig_table + schema_obj = schemaobj.SchemaObjects(migration_context) + + return schema_obj.table( + self.table_name, *self.columns, schema=self.schema, **self.kw + ) + + @classmethod + @util._with_legacy_names([("name", "table_name")]) + def create_table(cls, operations, table_name, *columns, **kw): + r"""Issue a "create table" instruction using the current migration + context. + + This directive receives an argument list similar to that of the + traditional :class:`sqlalchemy.schema.Table` construct, but without the + metadata:: + + +## ... source file abbreviated to get to table examples ... + + + current migration context. + + Generally, only that aspect of the column which + is being changed, i.e. name, type, nullability, + default, needs to be specified. Multiple changes + can also be specified at once and the backend should + "do the right thing", emitting each change either + separately or together as the backend allows. + + MySQL has special requirements here, since MySQL + cannot ALTER a column without a full specification. + When producing MySQL-compatible migration files, + it is recommended that the ``existing_type``, + ``existing_server_default``, and ``existing_nullable`` + parameters be present, if not being altered. + + Type changes which are against the SQLAlchemy + "schema" types :class:`-sqlalchemy.types.Boolean` + and :class:`-sqlalchemy.types.Enum` may also + add or drop constraints which accompany those + types on backends that don't support them natively. + The ``existing_type`` argument is + used in this case to identify and remove a previous + constraint that was bound to the type object. + +~~ :param table_name: string name of the target table. + :param column_name: string name of the target column, + as it exists before the operation begins. + :param nullable: Optional; specify ``True`` or ``False`` + to alter the column's nullability. + :param server_default: Optional; specify a string + SQL expression, :func:`-sqlalchemy.sql.expression.text`, + or :class:`-sqlalchemy.schema.DefaultClause` to indicate + an alteration to the column's default value. + Set to ``None`` to have the default removed. + :param comment: optional string text of a new comment to add to the + column. + + .. versionadded:: 1.0.6 + + :param new_column_name: Optional; specify a string name here to + indicate the new name within a column rename operation. + :param type\_: Optional; a :class:`-sqlalchemy.types.TypeEngine` + type object to specify a change to the column's type. + For SQLAlchemy types that also indicate a constraint (i.e. + :class:`-sqlalchemy.types.Boolean`, :class:`-sqlalchemy.types.Enum`), + the constraint is also generated. + :param autoincrement: set the ``AUTO_INCREMENT`` flag of the column; + currently understood by the MySQL dialect. + :param existing_type: Optional; a + + +## ... source file abbreviated to get to table examples ... + + + + .. versionadded:: 1.0.6 + + :param schema: Optional schema name to operate within. To control + quoting of the schema outside of the default behavior, use + the SQLAlchemy construct + :class:`-sqlalchemy.sql.elements.quoted_name`. + + .. versionadded:: 0.7.0 'schema' can now accept a + :class:`-sqlalchemy.sql.elements.quoted_name` construct. + + :param postgresql_using: String argument which will indicate a + SQL expression to render within the Postgresql-specific USING clause + within ALTER COLUMN. This string is taken directly as raw SQL which + must explicitly include any necessary quoting or escaping of tokens + within the expression. + + .. versionadded:: 0.8.8 + + batch migration context. + + Parameters are the same as that of :meth:`.Operations.alter_column`, + as well as the following option(s): + + :param insert_before: String name of an existing column which this +~~ column should be placed before, when creating the new table. + + .. versionadded:: 1.4.0 + + :param insert_before: String name of an existing column which this +~~ column should be placed after, when creating the new table. If + both :paramref:`.BatchOperations.alter_column.insert_before` + and :paramref:`.BatchOperations.alter_column.insert_after` are + omitted, the column is inserted after the last existing column +~~ in the table. + + .. versionadded:: 1.4.0 + + .. seealso:: + + :meth:`.Operations.alter_column` + + + + def __init__(self, table_name, column, schema=None, **kw): + super(AddColumnOp, self).__init__(table_name, schema=schema) + self.column = column + self.kw = kw + + def reverse(self): + return DropColumnOp.from_column_and_tablename( + self.schema, self.table_name, self.column + ) + + def to_diff_tuple(self): + return ("add_column", self.schema, self.table_name, self.column) + + def to_column(self): + return self.column + + from sqlalchemy import INTEGER, VARCHAR, NVARCHAR, Column + + +## ... source file abbreviated to get to table examples ... + + + have been changed: + + * name -> table_name + + + def __init__( + self, table_name, schema=None, table_kw=None, _orig_table=None + ): + self.table_name = table_name + self.schema = schema + self.table_kw = table_kw or {} + self._orig_table = _orig_table + + def to_diff_tuple(self): + return ("remove_table", self.to_table()) + + def reverse(self): + if self._orig_table is None: + raise ValueError( + "operation is not reversible; " "original table is not present" + ) + return CreateTableOp.from_table(self._orig_table) + + @classmethod + def from_table(cls, table): +~~ return cls(table.name, schema=table.schema, _orig_table=table) + + def to_table(self, migration_context=None): + if self._orig_table is not None: + return self._orig_table + schema_obj = schemaobj.SchemaObjects(migration_context) + return schema_obj.table( + self.table_name, schema=self.schema, **self.table_kw + ) + + @classmethod + @util._with_legacy_names([("name", "table_name")]) + def drop_table(cls, operations, table_name, schema=None, **kw): + r"""Issue a "drop table" instruction using the current + migration context. + + + e.g.:: + + drop_table("accounts") + + :param table_name: Name of the table + :param schema: Optional schema name to operate within. To control + quoting of the schema outside of the default behavior, use + the SQLAlchemy construct + + +## ... source file continues with no further table examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-util-clauseadapter.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-util-clauseadapter.markdown new file mode 100644 index 000000000..3e109aa04 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-util-clauseadapter.markdown @@ -0,0 +1,79 @@ +title: sqlalchemy.sql.util ClauseAdapter Example Code +category: page +slug: sqlalchemy-sql-util-clauseadapter-examples +sortorder: 500031133 +toc: False +sidebartitle: sqlalchemy.sql.util ClauseAdapter +meta: Example code for understanding how to use the ClauseAdapter class from the sqlalchemy.sql.util module of the SQLAlchemy project. + + +`ClauseAdapter` is a class within the `sqlalchemy.sql.util` module of the SQLAlchemy project. + + + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / relationships / __init__.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/relationships/__init__.py) + +```python +# __init__.py +import sqlalchemy as sa +~~from sqlalchemy.sql.util import ClauseAdapter + +from .chained_join import chained_join # noqa + + +def path_to_relationships(path, cls): + relationships = [] + for path_name in path.split('.'): + rel = getattr(cls, path_name) + relationships.append(rel) + cls = rel.mapper.class_ + return relationships + + +def adapt_expr(expr, *selectables): + for selectable in selectables: +~~ expr = ClauseAdapter(selectable).traverse(expr) + return expr + + +def inverse_join(selectable, left_alias, right_alias, relationship): + if relationship.property.secondary is not None: + secondary_alias = sa.alias(relationship.property.secondary) + return selectable.join( + secondary_alias, + adapt_expr( + relationship.property.secondaryjoin, + sa.inspect(left_alias).selectable, + secondary_alias + ) + ).join( + right_alias, + adapt_expr( + relationship.property.primaryjoin, + sa.inspect(right_alias).selectable, + secondary_alias + ) + ) + else: + join = sa.orm.join(right_alias, left_alias, relationship) + onclause = join.onclause + + +## ... source file continues with no further ClauseAdapter examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-sql-visitors-traverse.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-sql-visitors-traverse.markdown new file mode 100644 index 000000000..383be298e --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-sql-visitors-traverse.markdown @@ -0,0 +1,125 @@ +title: sqlalchemy.sql.visitors traverse Example Code +category: page +slug: sqlalchemy-sql-visitors-traverse-examples +sortorder: 500031134 +toc: False +sidebartitle: sqlalchemy.sql.visitors traverse +meta: Python example code that shows how to use the traverse callable from the sqlalchemy.sql.visitors module of the SQLAlchemy project. + + +`traverse` is a callable within the `sqlalchemy.sql.visitors` module of the SQLAlchemy project. + + + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / util / sqla_compat.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/util/sqla_compat.py) + +```python +# sqla_compat.py +import re + +from sqlalchemy import __version__ +from sqlalchemy import inspect +from sqlalchemy import schema +from sqlalchemy import sql +from sqlalchemy import types as sqltypes +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.schema import CheckConstraint +from sqlalchemy.schema import Column +from sqlalchemy.schema import ForeignKeyConstraint +from sqlalchemy.sql.elements import quoted_name +from sqlalchemy.sql.expression import _BindParamClause +from sqlalchemy.sql.expression import _TextClause as TextClause +~~from sqlalchemy.sql.visitors import traverse + +from . import compat + + +def _safe_int(value): + try: + return int(value) + except: + return value + + +_vers = tuple( + [_safe_int(x) for x in re.findall(r"(\d+|[abc]\d)", __version__)] +) +sqla_110 = _vers >= (1, 1, 0) +sqla_1115 = _vers >= (1, 1, 15) +sqla_120 = _vers >= (1, 2, 0) +sqla_1216 = _vers >= (1, 2, 16) +sqla_13 = _vers >= (1, 3) +sqla_14 = _vers >= (1, 4) +try: + from sqlalchemy import Computed # noqa + + has_computed = True + + +## ... source file abbreviated to get to traverse examples ... + + + target_schema, + target_table, + target_columns, + onupdate, + ondelete, + deferrable, + initially, + ) + + +def _fk_is_self_referential(constraint): + spec = constraint.elements[0]._get_colspec() + tokens = spec.split(".") + tokens.pop(-1) # colname + tablekey = ".".join(tokens) + return tablekey == constraint.parent.key + + +def _is_type_bound(constraint): + return constraint._type_bound + + +def _find_columns(clause): + + cols = set() +~~ traverse(clause, {}, {"column": cols.add}) + return cols + + +def _remove_column_from_collection(collection, column): + + to_remove = collection[column.key] + collection.remove(to_remove) + + +def _textual_index_column(table, text_): + if isinstance(text_, compat.string_types): + c = Column(text_, sqltypes.NULLTYPE) + table.append_column(c) + return c + elif isinstance(text_, TextClause): + return _textual_index_element(table, text_) + else: + raise ValueError("String or text() construct expected") + + +class _textual_index_element(sql.ColumnElement): + + __visit_name__ = "_textual_idx_element" + + + +## ... source file continues with no further traverse examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-boolean.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-boolean.markdown new file mode 100644 index 000000000..947dfc426 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-boolean.markdown @@ -0,0 +1,216 @@ +title: sqlalchemy.types Boolean Example Code +category: page +slug: sqlalchemy-types-boolean-examples +sortorder: 500031135 +toc: False +sidebartitle: sqlalchemy.types Boolean +meta: Example code for understanding how to use the Boolean class from the sqlalchemy.types module of the SQLAlchemy project. + + +`Boolean` is a class within the `sqlalchemy.types` module of the SQLAlchemy project. + +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TEXT, +TIME, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from sqlacodegen +[sqlacodegen](https://github.com/agronholm/sqlacodegen) +([PyPI package information](https://pypi.org/project/sqlacodegen/)) +is a tool for +reading from an existing [relational database](/databases.html) to +generate code to create [SQLAlchemy](/sqlalchemy.html) models based +on that database. The project is primarily written and maintained +by [Alex Grönholm (agronholm)](https://github.com/agronholm) and it +is open sourced under the +[MIT license](https://github.com/agronholm/sqlacodegen/blob/master/LICENSE). + +[**sqlacodegen / sqlacodegen / codegen.py**](https://github.com/agronholm/sqlacodegen/blob/master/sqlacodegen/./codegen.py) + +```python +# codegen.py +from __future__ import unicode_literals, division, print_function, absolute_import + +import inspect +import re +import sys +from collections import defaultdict +from importlib import import_module +from inspect import ArgSpec +from keyword import iskeyword + +import sqlalchemy +import sqlalchemy.exc +from sqlalchemy import ( + Enum, ForeignKeyConstraint, PrimaryKeyConstraint, CheckConstraint, UniqueConstraint, Table, + Column, Float) +from sqlalchemy.schema import ForeignKey +from sqlalchemy.sql.sqltypes import NullType +~~from sqlalchemy.types import Boolean, String +from sqlalchemy.util import OrderedDict + +try: + from sqlalchemy import ARRAY +except ImportError: + from sqlalchemy.dialects.postgresql import ARRAY + +try: + from sqlalchemy import Computed +except ImportError: + Computed = None + +try: + import geoalchemy2 # noqa: F401 +except ImportError: + pass + +_re_boolean_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \(0, 1\)") +_re_column_name = re.compile(r'(?:(["`]?)(?:.*)\1\.)?(["`]?)(.*)\2') +_re_enum_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \((.+)\)") +_re_enum_item = re.compile(r"'(.*?)(?BOOLEAN, +Boolean, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TEXT, +TIME, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / default_deserializers.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./default_deserializers.py) + +```python +# default_deserializers.py + + +import datetime +import io + +from validator_collection import validators, checkers + +from sqlathanor._compat import json +from sqlathanor.utilities import format_to_tuple, get_class_type_key, \ + raise_UnsupportedSerializationError, raise_UnsupportedDeserializationError +from sqlathanor.errors import UnsupportedValueTypeError + +~~from sqlalchemy.types import Boolean, Date, DateTime, Float, Integer, Text, Time, Interval + +DEFAULT_PYTHON_SQL_TYPE_MAPPING = { + 'bool': Boolean, + 'str': Text, + 'int': Integer, + 'float': Float, + 'datetime': DateTime, + 'date': Date, + 'time': Time, + 'timedelta': Interval +} + +def get_default_deserializer(class_attribute = None, + format = None): + format_to_tuple(format) + format = format.lower() + + class_type_key = get_class_type_key(class_attribute, None) + + deserializer_dict = DEFAULT_DESERIALIZERS.get(class_type_key, None) + + if deserializer_dict is None: + return None + + + +## ... source file continues with no further Date examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-datetime.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-datetime.markdown new file mode 100644 index 000000000..f588bfb5e --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-datetime.markdown @@ -0,0 +1,97 @@ +title: sqlalchemy.types DateTime Example Code +category: page +slug: sqlalchemy-types-datetime-examples +sortorder: 500031137 +toc: False +sidebartitle: sqlalchemy.types DateTime +meta: Example code for understanding how to use the DateTime class from the sqlalchemy.types module of the SQLAlchemy project. + + +`DateTime` is a class within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TEXT, +TIME, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / default_deserializers.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./default_deserializers.py) + +```python +# default_deserializers.py + + +import datetime +import io + +from validator_collection import validators, checkers + +from sqlathanor._compat import json +from sqlathanor.utilities import format_to_tuple, get_class_type_key, \ + raise_UnsupportedSerializationError, raise_UnsupportedDeserializationError +from sqlathanor.errors import UnsupportedValueTypeError + +~~from sqlalchemy.types import Boolean, Date, DateTime, Float, Integer, Text, Time, Interval + +DEFAULT_PYTHON_SQL_TYPE_MAPPING = { + 'bool': Boolean, + 'str': Text, + 'int': Integer, + 'float': Float, + 'datetime': DateTime, + 'date': Date, + 'time': Time, + 'timedelta': Interval +} + +def get_default_deserializer(class_attribute = None, + format = None): + format_to_tuple(format) + format = format.lower() + + class_type_key = get_class_type_key(class_attribute, None) + + deserializer_dict = DEFAULT_DESERIALIZERS.get(class_type_key, None) + + if deserializer_dict is None: + return None + + + +## ... source file continues with no further DateTime examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-enum.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-enum.markdown new file mode 100644 index 000000000..9799bde6b --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-enum.markdown @@ -0,0 +1,170 @@ +title: sqlalchemy.types Enum Example Code +category: page +slug: sqlalchemy-types-enum-examples +sortorder: 500031138 +toc: False +sidebartitle: sqlalchemy.types Enum +meta: Example code for understanding how to use the Enum class from the sqlalchemy.types module of the SQLAlchemy project. + + +`Enum` is a class within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TEXT, +TIME, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from graphene-sqlalchemy +[graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy) +([project documentation](https://docs.graphene-python.org/projects/sqlalchemy/en/latest/) +and +[PyPI package information](https://pypi.org/project/graphene-sqlalchemy/)) +is a [SQLAlchemy](/sqlalchemy.html) integration for +[Graphene](https://graphene-python.org/), which makes it easier to build +GraphQL-based [APIs](/application-programming-interfaces.html) into Python +[web applications](/web-development.html). The package allows you to +subclass SQLAlchemy classes and build queries around them with custom +code to match the backend queries with the GraphQL-based request queries. +The project is provided as open source under the +[MIT license](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/LICENSE.md). + +[**graphene-sqlalchemy / graphene_sqlalchemy / enums.py**](https://github.com/graphql-python/graphene-sqlalchemy/blob/master/graphene_sqlalchemy/./enums.py) + +```python +# enums.py +import six +from sqlalchemy.orm import ColumnProperty +~~from sqlalchemy.types import Enum as SQLAlchemyEnumType + +from graphene import Argument, Enum, List + +from .utils import EnumValue, to_enum_value_name, to_type_name + + +def _convert_sa_to_graphene_enum(sa_enum, fallback_name=None): + if not isinstance(sa_enum, SQLAlchemyEnumType): + raise TypeError( + "Expected sqlalchemy.types.Enum, but got: {!r}".format(sa_enum) + ) + enum_class = sa_enum.enum_class + if enum_class: + if all(to_enum_value_name(key) == key for key in enum_class.__members__): +~~ return Enum.from_enum(enum_class) + name = enum_class.__name__ + members = [ + (to_enum_value_name(key), value.value) + for key, value in enum_class.__members__.items() + ] + else: + sql_enum_name = sa_enum.name + if sql_enum_name: + name = to_type_name(sql_enum_name) + elif fallback_name: + name = fallback_name + else: + raise TypeError("No type name specified for {!r}".format(sa_enum)) + members = [(to_enum_value_name(key), key) for key in sa_enum.enums] +~~ return Enum(name, members) + + +def enum_for_sa_enum(sa_enum, registry): + if not isinstance(sa_enum, SQLAlchemyEnumType): + raise TypeError( + "Expected sqlalchemy.types.Enum, but got: {!r}".format(sa_enum) + ) + enum = registry.get_graphene_enum_for_sa_enum(sa_enum) + if not enum: + enum = _convert_sa_to_graphene_enum(sa_enum) + registry.register_enum(sa_enum, enum) + return enum + + +def enum_for_field(obj_type, field_name): + from .types import SQLAlchemyObjectType + + if not isinstance(obj_type, type) or not issubclass(obj_type, SQLAlchemyObjectType): + raise TypeError( + "Expected SQLAlchemyObjectType, but got: {!r}".format(obj_type)) + if not field_name or not isinstance(field_name, six.string_types): + raise TypeError( + "Expected a field name, but got: {!r}".format(field_name)) + registry = obj_type._meta.registry + + +## ... source file abbreviated to get to Enum examples ... + + + if name != enum.__name__ or custom_options != enum.custom_options: + raise ValueError( + "Sort enum for {} has already been customized".format(obj_type) + ) + else: + members = [] + default = [] + fields = obj_type._meta.fields + get_name = get_symbol_name or _default_sort_enum_symbol_name + for field_name in fields: + if only_fields and field_name not in only_fields: + continue + orm_field = registry.get_orm_field_for_graphene_field(obj_type, field_name) + if not isinstance(orm_field, ColumnProperty): + continue + column = orm_field.columns[0] + if only_indexed and not (column.primary_key or column.index): + continue + asc_name = get_name(column.name, True) + asc_value = EnumValue(asc_name, column.asc()) + desc_name = get_name(column.name, False) + desc_value = EnumValue(desc_name, column.desc()) + if column.primary_key: + default.append(asc_value) + members.extend(((asc_name, asc_value), (desc_name, desc_value))) +~~ enum = Enum(name, members) + enum.default = default # store default as attribute + enum.custom_options = custom_options + registry.register_sort_enum(obj_type, enum) + return enum + + +def sort_argument_for_object_type( + obj_type, + enum_name=None, + only_fields=None, + only_indexed=None, + get_symbol_name=None, + has_default=True, +): + enum = sort_enum_for_object_type( + obj_type, + enum_name, + only_fields=only_fields, + only_indexed=only_indexed, + get_symbol_name=get_symbol_name, + ) + if not has_default: + enum.default = None + + + +## ... source file continues with no further Enum examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-float.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-float.markdown new file mode 100644 index 000000000..6ae56700a --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-float.markdown @@ -0,0 +1,97 @@ +title: sqlalchemy.types Float Example Code +category: page +slug: sqlalchemy-types-float-examples +sortorder: 500031139 +toc: False +sidebartitle: sqlalchemy.types Float +meta: Example code for understanding how to use the Float class from the sqlalchemy.types module of the SQLAlchemy project. + + +`Float` is a class within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TEXT, +TIME, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / default_deserializers.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./default_deserializers.py) + +```python +# default_deserializers.py + + +import datetime +import io + +from validator_collection import validators, checkers + +from sqlathanor._compat import json +from sqlathanor.utilities import format_to_tuple, get_class_type_key, \ + raise_UnsupportedSerializationError, raise_UnsupportedDeserializationError +from sqlathanor.errors import UnsupportedValueTypeError + +~~from sqlalchemy.types import Boolean, Date, DateTime, Float, Integer, Text, Time, Interval + +DEFAULT_PYTHON_SQL_TYPE_MAPPING = { + 'bool': Boolean, + 'str': Text, + 'int': Integer, + 'float': Float, + 'datetime': DateTime, + 'date': Date, + 'time': Time, + 'timedelta': Interval +} + +def get_default_deserializer(class_attribute = None, + format = None): + format_to_tuple(format) + format = format.lower() + + class_type_key = get_class_type_key(class_attribute, None) + + deserializer_dict = DEFAULT_DESERIALIZERS.get(class_type_key, None) + + if deserializer_dict is None: + return None + + + +## ... source file continues with no further Float examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-integer.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-integer.markdown new file mode 100644 index 000000000..3d72e2a57 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-integer.markdown @@ -0,0 +1,228 @@ +title: sqlalchemy.types Integer Example Code +category: page +slug: sqlalchemy-types-integer-examples +sortorder: 500031140 +toc: False +sidebartitle: sqlalchemy.types Integer +meta: Example code for understanding how to use the Integer class from the sqlalchemy.types module of the SQLAlchemy project. + + +`Integer` is a class within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TEXT, +TIME, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / operations / schemaobj.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/operations/schemaobj.py) + +```python +# schemaobj.py +from sqlalchemy import schema as sa_schema +~~from sqlalchemy.types import Integer +from sqlalchemy.types import NULLTYPE + +from .. import util +from ..util.compat import string_types + + +class SchemaObjects(object): + def __init__(self, migration_context=None): + self.migration_context = migration_context + + def primary_key_constraint(self, name, table_name, cols, schema=None): + m = self.metadata() + columns = [sa_schema.Column(n, NULLTYPE) for n in cols] + t = sa_schema.Table(table_name, m, *columns, schema=schema) + p = sa_schema.PrimaryKeyConstraint(*[t.c[n] for n in cols], name=name) + t.append_constraint(p) + return p + + def foreign_key_constraint( + self, + name, + source, + referent, + local_cols, + + +## ... source file continues with no further Integer examples... + +``` + + +## Example 2 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / types.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./types.py) + +```python +# types.py +import warnings + +~~from sqlalchemy.types import UserDefinedType, Integer +from sqlalchemy.sql import func +from sqlalchemy.dialects import postgresql +from sqlalchemy.dialects.postgresql.base import ischema_names + +try: + from .shape import to_shape + SHAPELY = True +except ImportError: + SHAPELY = False + + +from .comparator import BaseComparator, Comparator +from .elements import WKBElement, WKTElement, RasterElement, CompositeElement +from .exc import ArgumentError + + +class _GISType(UserDefinedType): + + name = None + + from_text = None + + as_binary = None + + + +## ... source file abbreviated to get to Integer examples ... + + + + def __init__(self, *args, **kwargs): + kwargs['geometry_type'] = None + kwargs['srid'] = -1 + super(Raster, self).__init__(*args, **kwargs) + self.extended = None + + +class CompositeType(UserDefinedType): + + typemap = {} + + class comparator_factory(UserDefinedType.Comparator): + def __getattr__(self, key): + try: + type_ = self.type.typemap[key] + except KeyError: + raise KeyError("Type '%s' doesn't have an attribute: '%s'" + % (self.type, key)) + + return CompositeElement(self.expr, key, type_) + + +class GeometryDump(CompositeType): + +~~ typemap = {'path': postgresql.ARRAY(Integer), 'geom': Geometry} + + +ischema_names['geometry'] = Geometry +ischema_names['geography'] = Geography +ischema_names['raster'] = Raster + + + +## ... source file continues with no further Integer examples... + +``` + + +## Example 3 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / default_deserializers.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./default_deserializers.py) + +```python +# default_deserializers.py + + +import datetime +import io + +from validator_collection import validators, checkers + +from sqlathanor._compat import json +from sqlathanor.utilities import format_to_tuple, get_class_type_key, \ + raise_UnsupportedSerializationError, raise_UnsupportedDeserializationError +from sqlathanor.errors import UnsupportedValueTypeError + +~~from sqlalchemy.types import Boolean, Date, DateTime, Float, Integer, Text, Time, Interval + +DEFAULT_PYTHON_SQL_TYPE_MAPPING = { + 'bool': Boolean, + 'str': Text, + 'int': Integer, + 'float': Float, + 'datetime': DateTime, + 'date': Date, + 'time': Time, + 'timedelta': Interval +} + +def get_default_deserializer(class_attribute = None, + format = None): + format_to_tuple(format) + format = format.lower() + + class_type_key = get_class_type_key(class_attribute, None) + + deserializer_dict = DEFAULT_DESERIALIZERS.get(class_type_key, None) + + if deserializer_dict is None: + return None + + + +## ... source file continues with no further Integer examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-interval.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-interval.markdown new file mode 100644 index 000000000..80a350118 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-interval.markdown @@ -0,0 +1,97 @@ +title: sqlalchemy.types Interval Example Code +category: page +slug: sqlalchemy-types-interval-examples +sortorder: 500031141 +toc: False +sidebartitle: sqlalchemy.types Interval +meta: Example code for understanding how to use the Interval class from the sqlalchemy.types module of the SQLAlchemy project. + + +`Interval` is a class within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +NULLTYPE, +NullType, +String, +TEXT, +TIME, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / default_deserializers.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./default_deserializers.py) + +```python +# default_deserializers.py + + +import datetime +import io + +from validator_collection import validators, checkers + +from sqlathanor._compat import json +from sqlathanor.utilities import format_to_tuple, get_class_type_key, \ + raise_UnsupportedSerializationError, raise_UnsupportedDeserializationError +from sqlathanor.errors import UnsupportedValueTypeError + +~~from sqlalchemy.types import Boolean, Date, DateTime, Float, Integer, Text, Time, Interval + +DEFAULT_PYTHON_SQL_TYPE_MAPPING = { + 'bool': Boolean, + 'str': Text, + 'int': Integer, + 'float': Float, + 'datetime': DateTime, + 'date': Date, + 'time': Time, + 'timedelta': Interval +} + +def get_default_deserializer(class_attribute = None, + format = None): + format_to_tuple(format) + format = format.lower() + + class_type_key = get_class_type_key(class_attribute, None) + + deserializer_dict = DEFAULT_DESERIALIZERS.get(class_type_key, None) + + if deserializer_dict is None: + return None + + + +## ... source file continues with no further Interval examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-nulltype.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-nulltype.markdown new file mode 100644 index 000000000..605e44fda --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-nulltype.markdown @@ -0,0 +1,89 @@ +title: sqlalchemy.types NULLTYPE Example Code +category: page +slug: sqlalchemy-types-nulltype-examples +sortorder: 500031142 +toc: False +sidebartitle: sqlalchemy.types NULLTYPE +meta: Python example code that shows how to use the NULLTYPE constant from the sqlalchemy.types module of the SQLAlchemy project. + + +`NULLTYPE` is a constant within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NullType, +String, +TEXT, +TIME, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / ddl / postgresql.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/ddl/postgresql.py) + +```python +# postgresql.py +import logging +import re + +from sqlalchemy import Column +from sqlalchemy import Numeric +from sqlalchemy import text +from sqlalchemy import types as sqltypes +from sqlalchemy.dialects.postgresql import BIGINT +from sqlalchemy.dialects.postgresql import ExcludeConstraint +from sqlalchemy.dialects.postgresql import INTEGER +from sqlalchemy.sql.expression import ColumnClause +from sqlalchemy.sql.expression import UnaryExpression +~~from sqlalchemy.types import NULLTYPE + +from .base import alter_column +from .base import alter_table +from .base import AlterColumn +from .base import ColumnComment +from .base import compiles +from .base import format_column_name +from .base import format_table_name +from .base import format_type +from .base import RenameTable +from .impl import DefaultImpl +from .. import util +from ..autogenerate import render +from ..operations import ops +from ..operations import schemaobj +from ..operations.base import BatchOperations +from ..operations.base import Operations +from ..util import compat +from ..util import sqla_compat + + +log = logging.getLogger(__name__) + + + + +## ... source file continues with no further NULLTYPE examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-string.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-string.markdown new file mode 100644 index 000000000..49783e79b --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-string.markdown @@ -0,0 +1,210 @@ +title: sqlalchemy.types String Example Code +category: page +slug: sqlalchemy-types-string-examples +sortorder: 500031143 +toc: False +sidebartitle: sqlalchemy.types String +meta: Example code for understanding how to use the String class from the sqlalchemy.types module of the SQLAlchemy project. + + +`String` is a class within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +TEXT, +TIME, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from PyHive +[PyHive](https://github.com/dropbox/PyHive) +([PyPI package information](https://pypi.org/project/PyHive/)) +is a set of [DB-API](https://www.python.org/dev/peps/pep-0249/) +and +[SQLAlchemy](/sqlalchemy.html) +interfaces that make it easier to use [Presto](https://prestodb.io/) +and [Apache Hive](http://hive.apache.org/) with Python. +[Dropbox's engineering team](https://www.dropbox.com/jobs/teams/engineering) +created this code library, open sourced it and put it out under +the [Apache 2.0 license](https://github.com/dropbox/PyHive/blob/master/LICENSE). + +[**PyHive / pyhive / tests / test_sqlalchemy_presto.py**](https://github.com/dropbox/PyHive/blob/master/pyhive/tests/test_sqlalchemy_presto.py) + +```python +# test_sqlalchemy_presto.py +from __future__ import absolute_import +from __future__ import unicode_literals +from builtins import str +from pyhive.tests.sqlalchemy_test_case import SqlAlchemyTestCase +from pyhive.tests.sqlalchemy_test_case import with_engine_connection +from sqlalchemy import types +from sqlalchemy.engine import create_engine +from sqlalchemy.schema import Column +from sqlalchemy.schema import MetaData +from sqlalchemy.schema import Table +~~from sqlalchemy.types import String + +import contextlib +import unittest + + +class TestSqlAlchemyPresto(unittest.TestCase, SqlAlchemyTestCase): + def create_engine(self): + return create_engine('presto://localhost:8080/hive/default?source={}'.format(self.id())) + + def test_bad_format(self): + self.assertRaises( + ValueError, + lambda: create_engine('presto://localhost:8080/hive/default/what'), + ) + + @with_engine_connection + def test_reflect_select(self, engine, connection): + one_row_complex = Table('one_row_complex', MetaData(bind=engine), autoload=True) + self.assertEqual(len(one_row_complex.c), 15 - 1) + self.assertIsInstance(one_row_complex.c.string, Column) + rows = one_row_complex.select().execute().fetchall() + self.assertEqual(len(rows), 1) + self.assertEqual(list(rows[0]), [ + True, + + +## ... source file continues with no further String examples... + +``` + + +## Example 2 from sqlacodegen +[sqlacodegen](https://github.com/agronholm/sqlacodegen) +([PyPI package information](https://pypi.org/project/sqlacodegen/)) +is a tool for +reading from an existing [relational database](/databases.html) to +generate code to create [SQLAlchemy](/sqlalchemy.html) models based +on that database. The project is primarily written and maintained +by [Alex Grönholm (agronholm)](https://github.com/agronholm) and it +is open sourced under the +[MIT license](https://github.com/agronholm/sqlacodegen/blob/master/LICENSE). + +[**sqlacodegen / sqlacodegen / codegen.py**](https://github.com/agronholm/sqlacodegen/blob/master/sqlacodegen/./codegen.py) + +```python +# codegen.py +from __future__ import unicode_literals, division, print_function, absolute_import + +import inspect +import re +import sys +from collections import defaultdict +from importlib import import_module +from inspect import ArgSpec +from keyword import iskeyword + +import sqlalchemy +import sqlalchemy.exc +from sqlalchemy import ( + Enum, ForeignKeyConstraint, PrimaryKeyConstraint, CheckConstraint, UniqueConstraint, Table, + Column, Float) +from sqlalchemy.schema import ForeignKey +from sqlalchemy.sql.sqltypes import NullType +~~from sqlalchemy.types import Boolean, String +from sqlalchemy.util import OrderedDict + +try: + from sqlalchemy import ARRAY +except ImportError: + from sqlalchemy.dialects.postgresql import ARRAY + +try: + from sqlalchemy import Computed +except ImportError: + Computed = None + +try: + import geoalchemy2 # noqa: F401 +except ImportError: + pass + +_re_boolean_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \(0, 1\)") +_re_column_name = re.compile(r'(?:(["`]?)(?:.*)\1\.)?(["`]?)(.*)\2') +_re_enum_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \((.+)\)") +_re_enum_item = re.compile(r"'(.*?)(?BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TIME, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / default_deserializers.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./default_deserializers.py) + +```python +# default_deserializers.py + + +import datetime +import io + +from validator_collection import validators, checkers + +from sqlathanor._compat import json +from sqlathanor.utilities import format_to_tuple, get_class_type_key, \ + raise_UnsupportedSerializationError, raise_UnsupportedDeserializationError +from sqlathanor.errors import UnsupportedValueTypeError + +~~from sqlalchemy.types import Boolean, Date, DateTime, Float, Integer, Text, Time, Interval + +DEFAULT_PYTHON_SQL_TYPE_MAPPING = { + 'bool': Boolean, + 'str': Text, + 'int': Integer, + 'float': Float, + 'datetime': DateTime, + 'date': Date, + 'time': Time, + 'timedelta': Interval +} + +def get_default_deserializer(class_attribute = None, + format = None): + format_to_tuple(format) + format = format.lower() + + class_type_key = get_class_type_key(class_attribute, None) + + deserializer_dict = DEFAULT_DESERIALIZERS.get(class_type_key, None) + + if deserializer_dict is None: + return None + + + +## ... source file continues with no further Text examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-time.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-time.markdown new file mode 100644 index 000000000..473c3478d --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-time.markdown @@ -0,0 +1,97 @@ +title: sqlalchemy.types Time Example Code +category: page +slug: sqlalchemy-types-time-examples +sortorder: 500031145 +toc: False +sidebartitle: sqlalchemy.types Time +meta: Example code for understanding how to use the Time class from the sqlalchemy.types module of the SQLAlchemy project. + + +`Time` is a class within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TEXT, +Text, +Time, +TypeEngine, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / default_deserializers.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./default_deserializers.py) + +```python +# default_deserializers.py + + +import datetime +import io + +from validator_collection import validators, checkers + +from sqlathanor._compat import json +from sqlathanor.utilities import format_to_tuple, get_class_type_key, \ + raise_UnsupportedSerializationError, raise_UnsupportedDeserializationError +from sqlathanor.errors import UnsupportedValueTypeError + +~~from sqlalchemy.types import Boolean, Date, DateTime, Float, Integer, Text, Time, Interval + +DEFAULT_PYTHON_SQL_TYPE_MAPPING = { + 'bool': Boolean, + 'str': Text, + 'int': Integer, + 'float': Float, + 'datetime': DateTime, + 'date': Date, + 'time': Time, + 'timedelta': Interval +} + +def get_default_deserializer(class_attribute = None, + format = None): + format_to_tuple(format) + format = format.lower() + + class_type_key = get_class_type_key(class_attribute, None) + + deserializer_dict = DEFAULT_DESERIALIZERS.get(class_type_key, None) + + if deserializer_dict is None: + return None + + + +## ... source file continues with no further Time examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-to-instance.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-to-instance.markdown new file mode 100644 index 000000000..5f3085270 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-to-instance.markdown @@ -0,0 +1,128 @@ +title: sqlalchemy.types to_instance Example Code +category: page +slug: sqlalchemy-types-to-instance-examples +sortorder: 500031148 +toc: False +sidebartitle: sqlalchemy.types to_instance +meta: Python example code that shows how to use the to_instance callable from the sqlalchemy.types module of the SQLAlchemy project. + + +`to_instance` is a callable within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TEXT, +TIME, +Text, +Time, +TypeEngine, +and UserDefinedType +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / elements.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./elements.py) + +```python +# elements.py +import binascii +import struct + +try: + from sqlalchemy.sql import functions + from sqlalchemy.sql.functions import FunctionElement +except ImportError: # SQLA < 0.9 # pragma: no cover + from sqlalchemy.sql import expression as functions + from sqlalchemy.sql.expression import FunctionElement +~~from sqlalchemy.types import to_instance +from sqlalchemy.ext.compiler import compiles + +from .compat import PY3, str as str_ +from .exc import ArgumentError + + +if PY3: + BinasciiError = binascii.Error +else: + BinasciiError = TypeError + + +class HasFunction(object): + pass + + +class _SpatialElement(HasFunction): + + def __init__(self, data, srid=-1, extended=False): + self.srid = srid + self.data = data + self.extended = extended + + def __str__(self): + + +## ... source file abbreviated to get to to_instance examples ... + + + try: + bin_data = binascii.unhexlify(data[:114]) + except BinasciiError: + bin_data = data + data = str(binascii.hexlify(data).decode(encoding='utf-8')) + byte_order = bin_data[0] + srid = bin_data[53:57] + if not PY3: + byte_order = bytearray(byte_order)[0] + srid = struct.unpack('I', srid)[0] + _SpatialElement.__init__(self, data, srid, True) + + @property + def desc(self): + return self.data + + @staticmethod + def _data_from_desc(desc): + return desc + + +class CompositeElement(FunctionElement): + + def __init__(self, base, field, type_): + self.name = field +~~ self.type = to_instance(type_) + + super(CompositeElement, self).__init__(base) + + +@compiles(CompositeElement) +def _compile_pgelem(expr, compiler, **kw): + return '(%s).%s' % (compiler.process(expr.clauses, **kw), expr.name) + + + +## ... source file continues with no further to_instance examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-typeengine.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-typeengine.markdown new file mode 100644 index 000000000..7ad16f983 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-typeengine.markdown @@ -0,0 +1,92 @@ +title: sqlalchemy.types TypeEngine Example Code +category: page +slug: sqlalchemy-types-typeengine-examples +sortorder: 500031146 +toc: False +sidebartitle: sqlalchemy.types TypeEngine +meta: Example code for understanding how to use the TypeEngine class from the sqlalchemy.types module of the SQLAlchemy project. + + +`TypeEngine` is a class within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TEXT, +TIME, +Text, +Time, +UserDefinedType, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from databases +[databases](https://github.com/encode/databases) +([project homepage](https://www.encode.io/databases/) +and +[PyPI page](https://pypi.org/project/databases/) provides +[asyncio](https://docs.python.org/3/library/asyncio.html) support +with an [SQLALchemy](/sqlalchemy.html) Core interface for common +[relational databases](/databases.html) such as [MySQL](/mysql.html), +[PostgreSQL](/postgresql.html) and [SQLite](/sqlite.html). This is +handy for integrating with asynchronous I/O +[web frameworks](/web-frameworks.html) like [Sanic](/sanic.html). +The project is open sourced under the +[BSD 3-Clause "New" or "Revised" License](https://github.com/encode/databases/blob/master/LICENSE.md). + +[**databases / databases / backends / sqlite.py**](https://github.com/encode/databases/blob/master/databases/backends/sqlite.py) + +```python +# sqlite.py +import logging +import typing +import uuid + +import aiosqlite +from sqlalchemy.dialects.sqlite import pysqlite +from sqlalchemy.engine.interfaces import Dialect, ExecutionContext +from sqlalchemy.engine.result import ResultMetaData, RowProxy +from sqlalchemy.sql import ClauseElement +~~from sqlalchemy.types import TypeEngine + +from databases.core import LOG_EXTRA, DatabaseURL +from databases.interfaces import ConnectionBackend, DatabaseBackend, TransactionBackend + +logger = logging.getLogger("databases") + + +class SQLiteBackend(DatabaseBackend): + def __init__( + self, database_url: typing.Union[DatabaseURL, str], **options: typing.Any + ) -> None: + self._database_url = DatabaseURL(database_url) + self._options = options + self._dialect = pysqlite.dialect(paramstyle="qmark") + self._dialect.supports_native_decimal = False + self._pool = SQLitePool(self._database_url, **self._options) + + async def connect(self) -> None: + pass + + async def disconnect(self) -> None: + pass + + def connection(self) -> "SQLiteConnection": + + +## ... source file continues with no further TypeEngine examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-types-userdefinedtype.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-types-userdefinedtype.markdown new file mode 100644 index 000000000..31eadc7ad --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-types-userdefinedtype.markdown @@ -0,0 +1,82 @@ +title: sqlalchemy.types UserDefinedType Example Code +category: page +slug: sqlalchemy-types-userdefinedtype-examples +sortorder: 500031147 +toc: False +sidebartitle: sqlalchemy.types UserDefinedType +meta: Example code for understanding how to use the UserDefinedType class from the sqlalchemy.types module of the SQLAlchemy project. + + +`UserDefinedType` is a class within the `sqlalchemy.types` module of the SQLAlchemy project. + +BOOLEAN, +Boolean, +DATE, +DATETIME, +Date, +DateTime, +Enum, +FLOAT, +Float, +INTEGER, +Integer, +Interval, +NULLTYPE, +NullType, +String, +TEXT, +TIME, +Text, +Time, +TypeEngine, +and to_instance +are several other callables with code examples from the same `sqlalchemy.types` package. + +## Example 1 from GeoAlchemy2 +[GeoAlchemy2](https://github.com/geoalchemy/geoalchemy2) +([project documentation](https://geoalchemy-2.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/GeoAlchemy2/)) +extends [SQLAlchemy](/sqlalchemy.html) with new data types for working +with geospatial databases, particularly [PostGIS](http://postgis.net/), +which is a spatial database extender for [PostgreSQL](/postgresql.html). +The project is provided as open source under the +[MIT license](https://github.com/geoalchemy/geoalchemy2/blob/master/COPYING.rst). + +[**GeoAlchemy2 / geoalchemy2 / comparator.py**](https://github.com/geoalchemy/geoalchemy2/blob/master/geoalchemy2/./comparator.py) + +```python +# comparator.py + +from sqlalchemy import types as sqltypes +~~from sqlalchemy.types import UserDefinedType +from sqlalchemy.dialects.postgresql import DOUBLE_PRECISION +from sqlalchemy.sql import operators +try: + from sqlalchemy.sql.functions import _FunctionGenerator +except ImportError: # SQLA < 0.9 # pragma: no cover + from sqlalchemy.sql.expression import _FunctionGenerator + + +INTERSECTS = operators.custom_op('&&') +OVERLAPS_OR_TO_LEFT = operators.custom_op('&<') +OVERLAPS_OR_TO_RIGHT = operators.custom_op('&>') +OVERLAPS_OR_BELOW = operators.custom_op('&<|') +TO_LEFT = operators.custom_op('<<') +BELOW = operators.custom_op('<<|') +TO_RIGHT = operators.custom_op('>>') +CONTAINED = operators.custom_op('@') +OVERLAPS_OR_ABOVE = operators.custom_op('|&>') +ABOVE = operators.custom_op('|>>') +CONTAINS = operators.custom_op('-') +SAME = operators.custom_op('-=') +DISTANCE_CENTROID = operators.custom_op('<->') +DISTANCE_BOX = operators.custom_op('<#>') + + + + +## ... source file continues with no further UserDefinedType examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-util-langhelpers-public-factory.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-util-langhelpers-public-factory.markdown new file mode 100644 index 000000000..67b4b2580 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-util-langhelpers-public-factory.markdown @@ -0,0 +1,129 @@ +title: sqlalchemy.util.langhelpers public_factory Example Code +category: page +slug: sqlalchemy-util-langhelpers-public-factory-examples +sortorder: 500031154 +toc: False +sidebartitle: sqlalchemy.util.langhelpers public_factory +meta: Python example code that shows how to use the public_factory callable from the sqlalchemy.util.langhelpers module of the SQLAlchemy project. + + +`public_factory` is a callable within the `sqlalchemy.util.langhelpers` module of the SQLAlchemy project. + +symbol +is another callable from the `sqlalchemy.util.langhelpers` package with code examples. + +## Example 1 from SQLAthanor +[SQLAthanor](https://github.com/insightindustry/sqlathanor) +([PyPI package information](https://pypi.org/project/sqlathanor/) +and +[project documentation](https://sqlathanor.readthedocs.io/en/latest/index.html)) +is a [SQLAlchemy](/sqlalchemy.html) extension that provides serialization and +deserialization support for JSON, CSV, YAML and Python dictionaries. +This project is similar to [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) +with one major difference: SQLAthanor works through SQLAlchemy models +while Marshmallow is less coupled to SQLAlchemy because it requires +separate representations of the serialization objects. Both libraries +have their uses depending on whether the project plans to use SQLAlchemy +for object representations or would prefer to avoid that couping. +SQLAthanor is open sourced under the +[MIT license](https://github.com/insightindustry/sqlathanor/blob/master/LICENSE). + +[**SQLAthanor / sqlathanor / schema.py**](https://github.com/insightindustry/sqlathanor/blob/master/sqlathanor/./schema.py) + +```python +# schema.py + + +import functools +import operator + +from sqlalchemy import Column as SA_Column +from sqlalchemy import Table as SA_Table +from sqlalchemy.orm import class_mapper +from sqlalchemy.orm.relationships import RelationshipProperty as SA_RelationshipProperty +~~from sqlalchemy.util.langhelpers import public_factory +from sqlalchemy.ext.hybrid import hybrid_property as SA_hybrid_property + +from sqlalchemy import exc, orm, util, inspect + + +from validator_collection import checkers, validators + +from sqlathanor import attributes +from sqlathanor._serialization_support import SerializationMixin +from sqlathanor.default_deserializers import get_type_mapping +from sqlathanor.utilities import parse_json, parse_yaml, parse_csv, read_csv_data +from sqlathanor.errors import SQLAthanorError + + +class Column(SerializationMixin, SA_Column): + + + def __init__(self, *args, **kwargs): + super(Column, self).__init__(*args, **kwargs) + + +class RelationshipProperty(SA_RelationshipProperty): + + def __init__(self, + + +## ... source file abbreviated to get to public_factory examples ... + + + @property + def csv_sequence(self): + return self.prop.csv_sequence + + @property + def supports_json(self): + return self.prop.supports_json + + @property + def supports_yaml(self): + return self.prop.supports_yaml + + @property + def supports_dict(self): + return self.prop.supports_dict + + @property + def on_serialize(self): + return self.prop.on_serialize + + @property + def on_deserialize(self): + return self.prop.on_deserialize + + +~~relationship = public_factory(RelationshipProperty, ".orm.relationship") + + +class Table(SA_Table): + + + def __init__(self, *args, **kwargs): + super(Table, self).__init__(*args, **kwargs) + + @classmethod + def from_dict(cls, + serialized, + tablename, + metadata, + primary_key, + column_kwargs = None, + skip_nested = True, + default_to_str = False, + type_mapping = None, + **kwargs): + if not isinstance(serialized, dict): + raise ValueError('serialized must be a dict') + + if not serialized: + raise ValueError('serialized cannot be empty') + + +## ... source file continues with no further public_factory examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-util-langhelpers-symbol.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-util-langhelpers-symbol.markdown new file mode 100644 index 000000000..004c78e6f --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-util-langhelpers-symbol.markdown @@ -0,0 +1,80 @@ +title: sqlalchemy.util.langhelpers symbol Example Code +category: page +slug: sqlalchemy-util-langhelpers-symbol-examples +sortorder: 500031155 +toc: False +sidebartitle: sqlalchemy.util.langhelpers symbol +meta: Python example code that shows how to use the symbol callable from the sqlalchemy.util.langhelpers module of the SQLAlchemy project. + + +`symbol` is a callable within the `sqlalchemy.util.langhelpers` module of the SQLAlchemy project. + +public_factory +is another callable from the `sqlalchemy.util.langhelpers` package with code examples. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / models.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./models.py) + +```python +# models.py +from datetime import datetime + +import sqlalchemy as sa +~~from sqlalchemy.util.langhelpers import symbol + + +class Timestamp(object): + + created = sa.Column(sa.DateTime, default=datetime.utcnow, nullable=False) + updated = sa.Column(sa.DateTime, default=datetime.utcnow, nullable=False) + + +@sa.event.listens_for(Timestamp, 'before_update', propagate=True) +def timestamp_before_update(mapper, connection, target): + target.updated = datetime.utcnow() + + +~~NO_VALUE = symbol('NO_VALUE') +NOT_LOADED_REPR = '' + + +def _generic_repr_method(self, fields): + state = sa.inspect(self) + field_reprs = [] + if not fields: + fields = state.mapper.columns.keys() + for key in fields: + value = state.attrs[key].loaded_value + if value == NO_VALUE: + value = NOT_LOADED_REPR + else: + value = repr(value) + field_reprs.append('='.join((key, value))) + + return '%s(%s)' % (self.__class__.__name__, ', '.join(field_reprs)) + + +def generic_repr(*fields): + if len(fields) == 1 and callable(fields[0]): + target = fields[0] + target.__repr__ = lambda self: _generic_repr_method(self, fields=None) + return target + + +## ... source file continues with no further symbol examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-util-ordereddict.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-util-ordereddict.markdown new file mode 100644 index 000000000..1b3acc263 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-util-ordereddict.markdown @@ -0,0 +1,407 @@ +title: sqlalchemy.util OrderedDict Example Code +category: page +slug: sqlalchemy-util-ordereddict-examples +sortorder: 500031149 +toc: False +sidebartitle: sqlalchemy.util OrderedDict +meta: Example code for understanding how to use the OrderedDict class from the sqlalchemy.util module of the SQLAlchemy project. + + +`OrderedDict` is a class within the `sqlalchemy.util` module of the SQLAlchemy project. + +OrderedSet, +set_creation_order, +symbol, +and topological +are several other callables with code examples from the same `sqlalchemy.util` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / operations / batch.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/operations/batch.py) + +```python +# batch.py +from sqlalchemy import CheckConstraint +from sqlalchemy import Column +from sqlalchemy import ForeignKeyConstraint +from sqlalchemy import Index +from sqlalchemy import MetaData +from sqlalchemy import PrimaryKeyConstraint +from sqlalchemy import schema as sql_schema +from sqlalchemy import select +from sqlalchemy import Table +from sqlalchemy import types as sqltypes +from sqlalchemy.events import SchemaEventTarget +~~from sqlalchemy.util import OrderedDict +from sqlalchemy.util import topological + +from ..util import exc +from ..util.sqla_compat import _columns_for_constraint +from ..util.sqla_compat import _fk_is_self_referential +from ..util.sqla_compat import _is_type_bound +from ..util.sqla_compat import _remove_column_from_collection + + +class BatchOperationsImpl(object): + def __init__( + self, + operations, + table_name, + schema, + recreate, + copy_from, + table_args, + table_kwargs, + reflect_args, + reflect_kwargs, + naming_convention, + partial_reordering, + ): + + +## ... source file abbreviated to get to OrderedDict examples ... + + + + def drop_table(self, table): + raise NotImplementedError("Can't drop table in batch mode") + + +class ApplyBatchImpl(object): + def __init__( + self, + impl, + table, + table_args, + table_kwargs, + reflected, + partial_reordering=(), + ): + self.impl = impl + self.table = table # this is a Table object + self.table_args = table_args + self.table_kwargs = table_kwargs + self.temp_table_name = self._calc_temp_name(table.name) + self.new_table = None + + self.partial_reordering = partial_reordering # tuple of tuples + self.add_col_ordering = () # tuple of tuples + +~~ self.column_transfers = OrderedDict( + (c.name, {"expr": c}) for c in self.table.c + ) + self.existing_ordering = list(self.column_transfers) + + self.reflected = reflected + self._grab_table_elements() + + @classmethod + def _calc_temp_name(cls, tablename): + return ("_alembic_tmp_%s" % tablename)[0:50] + + def _grab_table_elements(self): + schema = self.table.schema +~~ self.columns = OrderedDict() + for c in self.table.c: + c_copy = c.copy(schema=schema) + c_copy.unique = c_copy.index = False + if isinstance(c.type, SchemaEventTarget): + assert c_copy.type is not c.type + self.columns[c.name] = c_copy + self.named_constraints = {} + self.unnamed_constraints = [] + self.indexes = {} + self.new_indexes = {} + for const in self.table.constraints: + if _is_type_bound(const): + continue + elif self.reflected and isinstance(const, CheckConstraint): + pass + elif const.name: + self.named_constraints[const.name] = const + else: + self.unnamed_constraints.append(const) + + for idx in self.table.indexes: + self.indexes[idx.name] = idx + + for k in self.table.kwargs: + self.table_kwargs.setdefault(k, self.table.kwargs[k]) + + def _adjust_self_columns_for_partial_reordering(self): + pairs = set() + + col_by_idx = list(self.columns) + + if self.partial_reordering: + for tuple_ in self.partial_reordering: + for index, elem in enumerate(tuple_): + if index > 0: + pairs.add((tuple_[index - 1], elem)) + else: + for index, elem in enumerate(self.existing_ordering): + if index > 0: + pairs.add((col_by_idx[index - 1], elem)) + + pairs.update(self.add_col_ordering) + + pairs = [p for p in pairs if p[0] != p[1]] + + sorted_ = list( + topological.sort(pairs, col_by_idx, deterministic_order=True) + ) +~~ self.columns = OrderedDict((k, self.columns[k]) for k in sorted_) +~~ self.column_transfers = OrderedDict( + (k, self.column_transfers[k]) for k in sorted_ + ) + + def _transfer_elements_to_new_table(self): + assert self.new_table is None, "Can only create new table once" + + m = MetaData() + schema = self.table.schema + + if self.partial_reordering or self.add_col_ordering: + self._adjust_self_columns_for_partial_reordering() + + self.new_table = new_table = Table( + self.temp_table_name, + m, + *(list(self.columns.values()) + list(self.table_args)), + schema=schema, + **self.table_kwargs + ) + + for const in ( + list(self.named_constraints.values()) + self.unnamed_constraints + ): + + + +## ... source file continues with no further OrderedDict examples... + +``` + + +## Example 2 from sqlacodegen +[sqlacodegen](https://github.com/agronholm/sqlacodegen) +([PyPI package information](https://pypi.org/project/sqlacodegen/)) +is a tool for +reading from an existing [relational database](/databases.html) to +generate code to create [SQLAlchemy](/sqlalchemy.html) models based +on that database. The project is primarily written and maintained +by [Alex Grönholm (agronholm)](https://github.com/agronholm) and it +is open sourced under the +[MIT license](https://github.com/agronholm/sqlacodegen/blob/master/LICENSE). + +[**sqlacodegen / sqlacodegen / codegen.py**](https://github.com/agronholm/sqlacodegen/blob/master/sqlacodegen/./codegen.py) + +```python +# codegen.py +from __future__ import unicode_literals, division, print_function, absolute_import + +import inspect +import re +import sys +from collections import defaultdict +from importlib import import_module +from inspect import ArgSpec +from keyword import iskeyword + +import sqlalchemy +import sqlalchemy.exc +from sqlalchemy import ( + Enum, ForeignKeyConstraint, PrimaryKeyConstraint, CheckConstraint, UniqueConstraint, Table, + Column, Float) +from sqlalchemy.schema import ForeignKey +from sqlalchemy.sql.sqltypes import NullType +from sqlalchemy.types import Boolean, String +~~from sqlalchemy.util import OrderedDict + +try: + from sqlalchemy import ARRAY +except ImportError: + from sqlalchemy.dialects.postgresql import ARRAY + +try: + from sqlalchemy import Computed +except ImportError: + Computed = None + +try: + import geoalchemy2 # noqa: F401 +except ImportError: + pass + +_re_boolean_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \(0, 1\)") +_re_column_name = re.compile(r'(?:(["`]?)(?:.*)\1\.)?(["`]?)(.*)\2') +_re_enum_check_constraint = re.compile(r"(?:(?:.*?)\.)?(.*?) IN \((.+)\)") +_re_enum_item = re.compile(r"'(.*?)(?OrderedDict, +set_creation_order, +symbol, +and topological +are several other callables with code examples from the same `sqlalchemy.util` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / autogenerate / compare.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/autogenerate/compare.py) + +```python +# compare.py +import contextlib +import logging +import re + +from sqlalchemy import event +from sqlalchemy import inspect +from sqlalchemy import schema as sa_schema +from sqlalchemy import types as sqltypes +~~from sqlalchemy.util import OrderedSet + +from alembic.ddl.base import _fk_spec +from .render import _user_defined_render +from .. import util +from ..operations import ops +from ..util import compat +from ..util import sqla_compat + +log = logging.getLogger(__name__) + + +def _populate_migration_script(autogen_context, migration_script): + upgrade_ops = migration_script.upgrade_ops_list[-1] + downgrade_ops = migration_script.downgrade_ops_list[-1] + + _produce_net_changes(autogen_context, upgrade_ops) + upgrade_ops.reverse_into(downgrade_ops) + + +comparators = util.Dispatcher(uselist=True) + + +def _produce_net_changes(autogen_context, upgrade_ops): + + + +## ... source file abbreviated to get to OrderedSet examples ... + + + + comparators.dispatch("schema", autogen_context.dialect.name)( + autogen_context, upgrade_ops, schemas + ) + + +@comparators.dispatch_for("schema") +def _autogen_for_tables(autogen_context, upgrade_ops, schemas): + inspector = autogen_context.inspector + + conn_table_names = set() + + version_table_schema = ( + autogen_context.migration_context.version_table_schema + ) + version_table = autogen_context.migration_context.version_table + + for s in schemas: + tables = set(inspector.get_table_names(schema=s)) + if s == version_table_schema: + tables = tables.difference( + [autogen_context.migration_context.version_table] + ) + conn_table_names.update(zip([s] * len(tables), tables)) + +~~ metadata_table_names = OrderedSet( + [(table.schema, table.name) for table in autogen_context.sorted_tables] + ).difference([(version_table_schema, version_table)]) + + _compare_tables( + conn_table_names, + metadata_table_names, + inspector, + upgrade_ops, + autogen_context, + ) + + +def _compare_tables( + conn_table_names, + metadata_table_names, + inspector, + upgrade_ops, + autogen_context, +): + + default_schema = inspector.bind.dialect.default_schema_name + +~~ metadata_table_names_no_dflt_schema = OrderedSet( + [ + (schema if schema != default_schema else None, tname) + for schema, tname in metadata_table_names + ] + ) + + tname_to_table = dict( + ( + no_dflt_schema, + autogen_context.table_key_to_table[ + sa_schema._get_table_key(tname, schema) + ], + ) + for no_dflt_schema, (schema, tname) in zip( + metadata_table_names_no_dflt_schema, metadata_table_names + ) + ) + metadata_table_names = metadata_table_names_no_dflt_schema + + for s, tname in metadata_table_names.difference(conn_table_names): + name = "%s.%s" % (s, tname) if s else tname + metadata_table = tname_to_table[(s, tname)] + if autogen_context.run_filters( + metadata_table, tname, "table", False, None + + +## ... source file abbreviated to get to OrderedSet examples ... + + + onupdate=options.get("onupdate"), + ondelete=options.get("ondelete"), + deferrable=options.get("deferrable"), + initially=options.get("initially"), + name=params["name"], + ) + conn_table.append_constraint(const) + return const + + +@contextlib.contextmanager +def _compare_columns( + schema, + tname, + conn_table, + metadata_table, + modify_table_ops, + autogen_context, + inspector, +): + name = "%s.%s" % (schema, tname) if schema else tname + metadata_cols_by_name = dict( + (c.name, c) for c in metadata_table.c if not c.system + ) + conn_col_names = dict((c.name, c) for c in conn_table.c) +~~ metadata_col_names = OrderedSet(sorted(metadata_cols_by_name)) + + for cname in metadata_col_names.difference(conn_col_names): + if autogen_context.run_filters( + metadata_cols_by_name[cname], cname, "column", False, None + ): + modify_table_ops.ops.append( + ops.AddColumnOp.from_column_and_tablename( + schema, tname, metadata_cols_by_name[cname] + ) + ) + log.info("Detected added column '%s.%s'", name, cname) + + for colname in metadata_col_names.intersection(conn_col_names): + metadata_col = metadata_cols_by_name[colname] + conn_col = conn_table.c[colname] + if not autogen_context.run_filters( + metadata_col, colname, "column", False, conn_col + ): + continue + alter_column_op = ops.AlterColumnOp(tname, colname, schema=schema) + + comparators.dispatch("column")( + autogen_context, + alter_column_op, + + +## ... source file continues with no further OrderedSet examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-util-set-creation-order.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-util-set-creation-order.markdown new file mode 100644 index 000000000..49b464d4d --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-util-set-creation-order.markdown @@ -0,0 +1,129 @@ +title: sqlalchemy.util set_creation_order Example Code +category: page +slug: sqlalchemy-util-set-creation-order-examples +sortorder: 500031151 +toc: False +sidebartitle: sqlalchemy.util set_creation_order +meta: Python example code that shows how to use the set_creation_order callable from the sqlalchemy.util module of the SQLAlchemy project. + + +`set_creation_order` is a callable within the `sqlalchemy.util` module of the SQLAlchemy project. + +OrderedDict, +OrderedSet, +symbol, +and topological +are several other callables with code examples from the same `sqlalchemy.util` package. + +## Example 1 from sqlalchemy-utils +[sqlalchemy-utils](https://github.com/kvesteri/sqlalchemy-utils) +([project documentation](https://sqlalchemy-utils.readthedocs.io/en/latest/) +and +[PyPI package information](https://pypi.org/project/SQLAlchemy-Utils/)) +is a code library with various helper functions and new data types +that make it easier to use [SQLAlchemy](/sqlalchemy.html) when building +projects that involve more specific storage requirements such as +[currency](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.currency). +The wide array of +[data types](https://sqlalchemy-utils.readthedocs.io/en/latest/data_types.html) +includes [ranged values](https://sqlalchemy-utils.readthedocs.io/en/latest/range_data_types.html) +and [aggregated attributes](https://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html). + +[**sqlalchemy-utils / sqlalchemy_utils / generic.py**](https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/./generic.py) + +```python +# generic.py +from collections.abc import Iterable + +import six +import sqlalchemy as sa +from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import attributes, class_mapper, ColumnProperty +from sqlalchemy.orm.interfaces import MapperProperty, PropComparator +from sqlalchemy.orm.session import _state_session +~~from sqlalchemy.util import set_creation_order + +from .exceptions import ImproperlyConfigured +from .functions import identity + + +class GenericAttributeImpl(attributes.ScalarAttributeImpl): + def get(self, state, dict_, passive=attributes.PASSIVE_OFF): + if self.key in dict_: + return dict_[self.key] + + session = _state_session(state) + if session is None: + return None + + discriminator = self.get_state_discriminator(state) + target_class = state.class_._decl_class_registry.get(discriminator) + + if target_class is None: + return None + + id = self.get_state_id(state) + + target = session.query(target_class).get(id) + + + +## ... source file abbreviated to get to set_creation_order examples ... + + + dict_[id.key] = None + dict_[self.parent_token.discriminator.key] = None + else: + class_ = type(initiator) + mapper = class_mapper(class_) + + pk = mapper.identity_key_from_instance(initiator)[1] + + discriminator = six.text_type(class_.__name__) + + for index, id in enumerate(self.parent_token.id): + dict_[id.key] = pk[index] + dict_[self.parent_token.discriminator.key] = discriminator + + +class GenericRelationshipProperty(MapperProperty): + + def __init__(self, discriminator, id, doc=None): + super(GenericRelationshipProperty, self).__init__() + self._discriminator_col = discriminator + self._id_cols = id + self._id = None + self._discriminator = None + self.doc = doc + +~~ set_creation_order(self) + + def _column_to_property(self, column): + if isinstance(column, hybrid_property): + attr_key = column.__name__ + for key, attr in self.parent.all_orm_descriptors.items(): + if key == attr_key: + return attr + else: + for key, attr in self.parent.attrs.items(): + if isinstance(attr, ColumnProperty): + if attr.columns[0].name == column.name: + return attr + + def init(self): + def convert_strings(column): + if isinstance(column, six.string_types): + return self.parent.columns[column] + return column + + self._discriminator_col = convert_strings(self._discriminator_col) + self._id_cols = convert_strings(self._id_cols) + + if isinstance(self._id_cols, Iterable): + self._id_cols = list(map(convert_strings, self._id_cols)) + + +## ... source file continues with no further set_creation_order examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-util-symbol.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-util-symbol.markdown new file mode 100644 index 000000000..c3978b6c2 --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-util-symbol.markdown @@ -0,0 +1,108 @@ +title: sqlalchemy.util symbol Example Code +category: page +slug: sqlalchemy-util-symbol-examples +sortorder: 500031152 +toc: False +sidebartitle: sqlalchemy.util symbol +meta: Python example code that shows how to use the symbol callable from the sqlalchemy.util module of the SQLAlchemy project. + + +`symbol` is a callable within the `sqlalchemy.util` module of the SQLAlchemy project. + +OrderedDict, +OrderedSet, +set_creation_order, +and topological +are several other callables with code examples from the same `sqlalchemy.util` package. + +## Example 1 from SQLAlchemy filters +[SQLAlchemy filters](https://github.com/juliotrigo/sqlalchemy-filters) + provides filtering, sorting and pagination for [SQLAlchemy](/sqlalchemy.html) + query objects, which is particularly useful when building + [web APIs](/application-programming-interfaces.html). SQLAlchemy filters + is open sourced under the + [Apache License version 2.0](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/LICENSE). + +[**SQLAlchemy filters / sqlalchemy_filters / models.py**](https://github.com/juliotrigo/sqlalchemy-filters/blob/master/sqlalchemy_filters/./models.py) + +```python +# models.py +from sqlalchemy.exc import InvalidRequestError +from sqlalchemy.inspection import inspect +from sqlalchemy.orm.mapper import Mapper +~~from sqlalchemy.util import symbol +import types + +from .exceptions import BadQuery, FieldNotFound, BadSpec + + +class Field(object): + + def __init__(self, model, field_name): + self.model = model + self.field_name = field_name + + def get_sqlalchemy_field(self): + if self.field_name not in self._get_valid_field_names(): + raise FieldNotFound( + 'Model {} has no column `{}`.'.format( + self.model, self.field_name + ) + ) + sqlalchemy_field = getattr(self.model, self.field_name) + + if isinstance(sqlalchemy_field, types.MethodType): + sqlalchemy_field = sqlalchemy_field() + + return sqlalchemy_field + + def _get_valid_field_names(self): + inspect_mapper = inspect(self.model) + columns = inspect_mapper.columns + orm_descriptors = inspect_mapper.all_orm_descriptors + + column_names = columns.keys() + hybrid_names = [ + key for key, item in orm_descriptors.items() + if _is_hybrid_property(item) or _is_hybrid_method(item) + ] + + return set(column_names) | set(hybrid_names) + + +def _is_hybrid_property(orm_descriptor): +~~ return orm_descriptor.extension_type == symbol('HYBRID_PROPERTY') + + +def _is_hybrid_method(orm_descriptor): +~~ return orm_descriptor.extension_type == symbol('HYBRID_METHOD') + + +def get_query_models(query): + models = [col_desc['entity'] for col_desc in query.column_descriptions] + models.extend(mapper.class_ for mapper in query._join_entities) + + if ( + hasattr(query, '_select_from_entity') and + (query._select_from_entity is not None) + ): + model_class = ( + query._select_from_entity.class_ + if isinstance(query._select_from_entity, Mapper) # sqlalchemy>=1.1 + else query._select_from_entity # sqlalchemy==1.0 + ) + if model_class not in models: + models.append(model_class) + + return {model.__name__: model for model in models} + + +def get_model_from_spec(spec, query, default_model=None): + models = get_query_models(query) + if not models: + + +## ... source file continues with no further symbol examples... + +``` + diff --git a/content/pages/examples/sqlalchemy/sqlalchemy-util-topological.markdown b/content/pages/examples/sqlalchemy/sqlalchemy-util-topological.markdown new file mode 100644 index 000000000..1aafda00c --- /dev/null +++ b/content/pages/examples/sqlalchemy/sqlalchemy-util-topological.markdown @@ -0,0 +1,127 @@ +title: sqlalchemy.util topological Example Code +category: page +slug: sqlalchemy-util-topological-examples +sortorder: 500031153 +toc: False +sidebartitle: sqlalchemy.util topological +meta: Python example code that shows how to use the topological callable from the sqlalchemy.util module of the SQLAlchemy project. + + +`topological` is a callable within the `sqlalchemy.util` module of the SQLAlchemy project. + +OrderedDict, +OrderedSet, +set_creation_order, +and symbol +are several other callables with code examples from the same `sqlalchemy.util` package. + +## Example 1 from alembic +[Alembic](https://github.com/sqlalchemy/alembic) +([project documentation](https://alembic.sqlalchemy.org/) and +[PyPI page](https://pypi.org/project/alembic/)) +is a data migrations tool used with [SQLAlchemy](/sqlalchemy.html) to make +database schema changes. The Alembic project is open sourced under the +[MIT license](https://github.com/sqlalchemy/alembic/blob/master/LICENSE). + +[**alembic / alembic / operations / batch.py**](https://github.com/sqlalchemy/alembic/blob/master/alembic/operations/batch.py) + +```python +# batch.py +from sqlalchemy import CheckConstraint +from sqlalchemy import Column +from sqlalchemy import ForeignKeyConstraint +from sqlalchemy import Index +from sqlalchemy import MetaData +from sqlalchemy import PrimaryKeyConstraint +from sqlalchemy import schema as sql_schema +from sqlalchemy import select +from sqlalchemy import Table +from sqlalchemy import types as sqltypes +from sqlalchemy.events import SchemaEventTarget +from sqlalchemy.util import OrderedDict +~~from sqlalchemy.util import topological + +from ..util import exc +from ..util.sqla_compat import _columns_for_constraint +from ..util.sqla_compat import _fk_is_self_referential +from ..util.sqla_compat import _is_type_bound +from ..util.sqla_compat import _remove_column_from_collection + + +class BatchOperationsImpl(object): + def __init__( + self, + operations, + table_name, + schema, + recreate, + copy_from, + table_args, + table_kwargs, + reflect_args, + reflect_kwargs, + naming_convention, + partial_reordering, + ): + self.operations = operations + + +## ... source file abbreviated to get to topological examples ... + + + self.indexes[idx.name] = idx + + for k in self.table.kwargs: + self.table_kwargs.setdefault(k, self.table.kwargs[k]) + + def _adjust_self_columns_for_partial_reordering(self): + pairs = set() + + col_by_idx = list(self.columns) + + if self.partial_reordering: + for tuple_ in self.partial_reordering: + for index, elem in enumerate(tuple_): + if index > 0: + pairs.add((tuple_[index - 1], elem)) + else: + for index, elem in enumerate(self.existing_ordering): + if index > 0: + pairs.add((col_by_idx[index - 1], elem)) + + pairs.update(self.add_col_ordering) + + pairs = [p for p in pairs if p[0] != p[1]] + + sorted_ = list( +~~ topological.sort(pairs, col_by_idx, deterministic_order=True) + ) + self.columns = OrderedDict((k, self.columns[k]) for k in sorted_) + self.column_transfers = OrderedDict( + (k, self.column_transfers[k]) for k in sorted_ + ) + + def _transfer_elements_to_new_table(self): + assert self.new_table is None, "Can only create new table once" + + m = MetaData() + schema = self.table.schema + + if self.partial_reordering or self.add_col_ordering: + self._adjust_self_columns_for_partial_reordering() + + self.new_table = new_table = Table( + self.temp_table_name, + m, + *(list(self.columns.values()) + list(self.table_args)), + schema=schema, + **self.table_kwargs + ) + + for const in ( + + +## ... source file continues with no further topological examples... + +``` + diff --git a/content/pages/meta/00-change-log.markdown b/content/pages/meta/00-change-log.markdown index 0adee05de..bf6137a13 100644 --- a/content/pages/meta/00-change-log.markdown +++ b/content/pages/meta/00-change-log.markdown @@ -13,7 +13,195 @@ view commit-level changes via the [source repository's commit log](https://github.com/mattmakai/fullstackpython.com/commits/) on GitHub. +## 2022 +### October +* Starting to get back into updating this site again! Note that I'll probably + spend most of my side project time on [Plushcap](https://www.plushcap.com/) + but I'm removing old resources and adding new good ones on here to keep the + site maintained. + +### March +* I decided to go so minimal that I removed the logo to make the site load + faster, and also got rid of some unncessary CSS on front page. + +### February +* Still on break, but updated the header and footer. Also made some website + tweaks to make it faster. + +## 2021 +### October +* Taking a break for a few months to recharge and work on a different coding + side project that I'm excited about. Be back in a few months with some updates. + +### September +* Clean up continues across the site to remove link rot and replace + out-of-date links with newer ones where necessary. + +### August +* New blog post on + [Application Performance Monitoring AWS Lambda Functions with Sentry](/blog/application-performance-monitoring-aws-lambda-functions-sentry.html). + +### June +* Fix broken links across the site. It's a real shame people and companies don't use + 301 redirects more often rather than just breaking their URL structures. + +### May +* New resources on [GPT-3](/gpt-3.html), [Jupyter Notebook](/jupyter-notebook.html) + and [serverless](/serverless.html) pages. + +### April +* Published new post on [How to Monitor Python Functions on AWS Lambda with Sentry](/blog/monitor-python-functions-aws-lambda-sentry.html). +* New [SQLite](/sqlite.html) resource. + +### March +* New [webhook](/webhooks.html) resource. + +### February +* New [GPT-3](/gpt-3.html) resources. + +### January +* Published a new blog post on + [Using Django & AssemblyAI for More Accurate Twilio Call Transcriptions](/blog/django-accurate-twilio-voice-transcriptions.html). +* Updated + [Flask extension projects and example code](/flask-extensions-plug-ins-related-libraries.html). +* Happy New Year! + + ## 2020 +### December +* New [Bash](/bourne-again-shell-bash.html), [tmux](/tmux.html) and + [Vim](/vim.html) resources and explanations. + +### November +* New resources for [DevOps](/devops.html) and [containers](/containers.html). + +### October +* Added new blog on + [Higher Accuracy Twilio Voice Transcriptions with Python and Flask](/blog/accurate-twilio-voice-call-recording-transcriptions-assemblyai.html). +* New [NumPy](/scipy-numpy.html) resources. + +### September +* Tweaks across [Flask code examples](/flask-code-examples.html). + +### August +* New blog posts on + [How to Transcribe Speech Recordings into Text with Python](/blog/transcribe-recordings-speech-text-assemblyai.html) + and + [Using Sentry to Handle Python Exceptions in Django Projects](/blog/sentry-handle-exceptions-django-projects.html). +* Added new [GPT-3 page](/gpt-3.html). +* Updated [debugging](/debugging.html) page with some additional descriptions. + +### July +* Updated [webhooks](/webhooks.html) page with additional resources. +* New blog posts: + * [Tracking Daily User Data in Django with django-user-visit](/blog/track-daily-user-data-django-user-visit.html) + * [Quickly Use Bootstrap 4 in a Django Template with a CDN](/blog/bootstrap-4-django-template.html) + * [How to report errors in Flask web apps with Sentry](/blog/report-errors-flask-web-apps-sentry.html) + +### June +* Added new example code for [Django](/django.html) modules: + * [django.contrib.admin.helpers](/django-contrib-admin-helpers-examples.html) + [ActionForm](/django-contrib-admin-helpers-actionform-examples.html), + and + [AdminForm](/django-contrib-admin-helpers-adminform-examples.html) + * django.contrib.admin.options + [IS_POPUP_VAR](/django-contrib-admin-options-is-popup-var-examples.html), + [IncorrectLookupParameters](/django-contrib-admin-options-incorrectlookupparameters-examples.html), + [ModelAdmin](/django-contrib-admin-options-modeladmin-examples.html), + and + [csrf_protect_m](/django-contrib-admin-options-csrf-protect-m-examples.html) + * django.contrib.admin.sites + [NotRegistered](/django-contrib-admin-sites-notregistered-examples.html) + and + [site](/django-contrib-admin-sites-site-examples.html) + * django.core + [cache](/django-core-cache-examples.html), + [checks](/django-core-checks-examples.html), + [exceptions](/django-core-exceptions-examples.html), + [mail](/django-core-mail-examples.html), + [management](/django-core-management-examples.html), + [serializers](/django-core-serializers-examples.html), + [signals](/django-core-signals-examples.html), + [signing](/django-core-signing-examples.html), + and + [validators](/django-core-validators-examples.html) + * django.utils.translation + [LANGUAGE_SESSION_KEY](/django-utils-translation-language-session-key-examples.html), + [activate](/django-utils-translation-activate-examples.html), + [deactivate_all](/django-utils-translation-deactivate-all-examples.html), + [get_language](/django-utils-translation-get-language-examples.html), + [get_language_from_request](/django-utils-translation-get-language-from-request-examples.html), + [gettext](/django-utils-translation-gettext-examples.html), + [gettext_lazy](/django-utils-translation-gettext-lazy-examples.html), + [ngettext](/django-utils-translation-ngettext-examples.html), + [override](/django-utils-translation-override-examples.html), + [pgettext](/django-utils-translation-pgettext-examples.html), + [pgettext_lazy](/django-utils-translation-pgettext-lazy-examples.html), + [ugettext](/django-utils-translation-ugettext-examples.html), + [ugettext_lazy](/django-utils-translation-ugettext-lazy-examples.html), + [ungettex](/django-utils-translation-ungettext-examples.html), + and + [ungettext_lazy](/django-utils-translation-ungettext-lazy-examples.html) +* Added new example code pages for Flask modules: + * flask.blueprints [Blueprint](/flask-blueprints-blueprint-examples.html) + * flask.ctx [after_this_request](/flask-ctx-after-this-request-examples.html), + [has_app_context](/flask-ctx-has-app-context-examples.html) and + [has_request_context](/flask-ctx-has-request-context-examples.html) + * flask.globals [current_app](/flask-globals-current-app-examples.html) + * flask.helpers [send_file](flask-helpers-send-file-examples.html) + * flask.json [JSONEncoder](/flask-json-jsonencoder-examples.html) + * flask.sessions [BadSignature](/flask-sessions-badsignature-examples.html) + and + [SessionMixin](/flask-sessions-sessionmixin-examples.html) + +### May +* Added new example code pages for Flask modules: + * flask.cli [FlaskGroup](/flask-cli-flaskgroup-examples.html), + [ScriptInfo](/flask-cli-scriptinfo-examples.html), and + [with_appcontext](/flask-cli-with-appcontext-examples.html) + * flask.globals [request](/flask-globals-request-examples.html) and + [session](/flask-globals-session-examples.html) + * flask.helpers [flask](/flask-helpers-flash-examples.html), + [make_response](/flask-helpers-make-response-examples.html), and + [url_for](/flask-helpers-url-for-examples.html) + * flask.sessions [SessionInterface](/flask-sessions-sessioninterface-examples.html) + * flask.signals [Namespace](/flask-signals-namespace-examples.html) + * flask.templating + [render_template](/flask-templating-render-template-examples.html) + * flask.views + [MethodView](/flask-views-methodview-examples.html), + [View](/flask-views-view-examples.html), and + [http_method_funcs](/flask-views-http-method-funcs-examples.html) +* New blog post on + [Reporting Exceptions in Python Scripts with Sentry](/blog/report-exceptions-python-scripts-sentry.html). +* Tweaked some CSS for the site. +* Added a new page with the start of + [pandas example code and projects](/pandas-code-examples.html). + +### April +* Merge [PR #233](https://github.com/mattmakai/fullstackpython.com/pull/233) and + [PR #235](https://github.com/mattmakai/fullstackpython.com/pull/235) for new + [Celery](/celery.html) and [podcast](/best-python-podcasts.html) resources. +* Updated the [web design](/web-design.html) page with new resources. + +### March +* Added another new blog post on + [Exporting pandas DataFrames into SQLite with SQLAlchemy](/blog/export-pandas-dataframes-sqlite-sqlalchemy.html). +* Added new blog post tutorial on + [Learning pandas by Exploring COVID-19 Data](/blog/learn-pandas-basic-commands-explore-covid-19-data.html). +* New [web design](/web-design.html) and + [web development](/web-development.html) resources. +* Added new blog post on + [The Best Resources for Developers to Learn Finance](/blog/best-resources-developers-learn-finance.html). + +### February +* New [CSS](/cascading-style-sheets.html), [task queue](/task-queues.html) + and [uWSGI](/uwsgi.html) resources. +* Added new Django code example pages: + * [django.forms DateField](/django-db-models-datefield-examples.html) + * [django.forms DateTimeField](/django-db-models-datetimefield-examples.html) + * [django.forms TypedChoiceField](/django-db-models-typedchoicefield-examples.html) + ### January * Added new Django code example pages: * [django.db.models SmallIntegerField](/django-db-models-smallintegerfield-examples.html) diff --git a/content/pages/meta/02-about-author.markdown b/content/pages/meta/02-about-author.markdown index 63c3d2a94..0ab3b577c 100644 --- a/content/pages/meta/02-about-author.markdown +++ b/content/pages/meta/02-about-author.markdown @@ -8,17 +8,17 @@ meta: Learn more about the author of Full Stack Python, Matt Makai. [Full Stack Python](https://www.fullstackpython.com/) is coded and written by -[Matt Makai](http://www.mattmakai.com/). Matt currently +[Matt Makai](https://github.com/mattmakai). Matt currently works in Washington, D.C. for the [Twilio Developer Network](https://www.twilio.com/blog/2014/02/introducing-developer-evangelist-matt-makai.html) -as head of the Developer Voices program. +as the Director of Developer Content. Other projects by Matt include -[The Full Stack Python Guide to Deployments](https://www.deploypython.com/), [Python for Entrepreneurs](https://training.talkpython.fm/courses/explore_entrepreneurs/python-for-entrepreneurs-build-and-launch-your-online-business), -[Introduction to Ansible](https://training.talkpython.fm/courses/explore_ansible/introduction-to-ansible-with-python) -and +[Introduction to Ansible](https://training.talkpython.fm/courses/explore_ansible/introduction-to-ansible-with-python), [Coding Across America](http://www.codingacrossamerica.com/). +and +[The Full Stack Python Guide to Deployments](https://www.deploypython.com/), You can reach him by email at matthew.makai@gmail.com. Matt can't respond to every email, but he will do his best to reply when possible. diff --git a/content/posts/160511-send-sms-text-message-python.markdown b/content/posts/160511-send-sms-text-message-python.markdown index 1159e7114..4cbb10078 100644 --- a/content/posts/160511-send-sms-text-message-python.markdown +++ b/content/posts/160511-send-sms-text-message-python.markdown @@ -3,7 +3,7 @@ slug: send-sms-text-messages-python meta: A how-to guide for sending SMS (text messages) using the Python programming language. category: post date: 2016-05-11 -modified: 2017-04-28 +modified: 2020-08-05 newsletter: False headerimage: /img/160511-send-sms-python/header.jpg headeralt: Twilio and Python logos. Copyright their respective owners. @@ -25,7 +25,7 @@ those two versions installed. * [pip](https://pip.pypa.io/en/stable/) and [virtualenv](https://virtualenv.pypa.io/en/latest/) to handle [application dependencies](/application-dependencies.html) -* A free [Twilio account](https://www.twilio.com/try-twilio) to use their +* A free [Twilio account](www.twilio.com/referral/w9pugq) to use their [SMS web API](https://www.twilio.com/docs/api/rest/sending-messages) * Open source [Twilio Python helper library](https://pypi.org/project/twilio), @@ -41,7 +41,7 @@ guide that'll show how to install system packages for those tools. ## Using a Web API We're going to use a web API to make sending SMS easier and more reliable. Head to the -[Twilio website and sign up for a free trial account](https://www.twilio.com/try-twilio). If you already have a Twilio account (and you should - it's +[Twilio website and sign up for a free trial account](www.twilio.com/referral/w9pugq) awesome for more than just sending text messages!) then sign into your existing account. diff --git a/content/posts/160518-install-postgresql-python-3-ubuntu-1604.markdown b/content/posts/160518-install-postgresql-python-3-ubuntu-1604.markdown index e5d4338cc..baf38465d 100644 --- a/content/posts/160518-install-postgresql-python-3-ubuntu-1604.markdown +++ b/content/posts/160518-install-postgresql-python-3-ubuntu-1604.markdown @@ -12,7 +12,7 @@ headeralt: PostgreSQL and Ubuntu logos. Copyright their respective owners. [PostgreSQL](/postgresql.html) is a powerful open source [relational database](/databases.html) frequently used to create, read, update and delete [Python web application](/web-frameworks.html) data. -[Psycopg2](http://initd.org/psycopg/) is a PostgreSQL database +[Psycopg2](https://www.psycopg.org/) is a PostgreSQL database driver that serves as a Python client for access to the PostgreSQL server. This post explains how to install PostgreSQL on [Ubuntu 16.04](/ubuntu.html) and run a few basic SQL queries within a Python program. @@ -110,7 +110,7 @@ found in the ## Installing psycopg2 Now that PostgreSQL is installed and we have a non-superuser account, we -can install the [psycopg2](http://initd.org/psycopg/) package. Let's +can install the [psycopg2](https://www.psycopg.org/) package. Let's figure out where our `python3` executable is located, create a virtualenv with `python3`, activate the virtualenv and then install the psycopg2 package with `pip`. Find your `python3` executable using the `which` command. diff --git a/content/posts/160530-respond-sms-text-messages-python-flask.markdown b/content/posts/160530-respond-sms-text-messages-python-flask.markdown index 2da56f22a..0d0f0e10e 100644 --- a/content/posts/160530-respond-sms-text-messages-python-flask.markdown +++ b/content/posts/160530-respond-sms-text-messages-python-flask.markdown @@ -3,7 +3,7 @@ slug: respond-sms-text-messages-python-flask meta: A quick tutorial on receiving and responding to SMS text messages in a Flask application built with Python. category: post date: 2016-05-30 -modified: 2017-05-11 +modified: 2020-08-05 newsletter: False headerimage: /img/160530-respond-sms-python-flask/header.jpg headeralt: Twilio, Python and Flask logos. Copyright their respective owners. @@ -26,7 +26,7 @@ those two versions installed on your system. [virtualenv](https://virtualenv.pypa.io/en/latest/) to handle [application dependencies](/application-dependencies.html) * The [Flask](/flask.html) micro web framework -* A free [Twilio account](https://www.twilio.com/try-twilio) to use their +* A free [Twilio account](www.twilio.com/referral/w9pugq) to use their [SMS web API](https://www.twilio.com/docs/api/rest/sending-messages) * Open source [Twilio Python helper library](https://pypi.org/project/twilio) @@ -158,7 +158,7 @@ to respond to text messages. ## Obtaining Our Phone Number We can use our Flask application's route to respond to incoming web API requests based on incoming SMS messages to a Twilio phone number. Go to the -[Twilio website and sign up for a free trial account](https://www.twilio.com/try-twilio) +[Twilio website and sign up for a free trial account](www.twilio.com/referral/w9pugq) to use their API. If you already have a Twilio account then sign into your existing account. diff --git a/content/posts/160626-django-gunicorn-mint-linux-17.markdown b/content/posts/160626-django-gunicorn-mint-linux-17.markdown index 688adaaf8..8ab8836ff 100644 --- a/content/posts/160626-django-gunicorn-mint-linux-17.markdown +++ b/content/posts/160626-django-gunicorn-mint-linux-17.markdown @@ -3,7 +3,7 @@ slug: python-3-django-gunicorn-linux-mint-17 meta: A step-by-step walkthrough on configuring Linux Mint 17.3 with Python 3, Django and Green Unicorn (Gunicorn). category: post date: 2016-06-26 -modified: 2016-07-22 +modified: 2021-06-17 newsletter: False headerimage: /img/160626-mint-django-gunicorn/header.jpg headeralt: Django, Green Unicorn and Linux Mint logos. Copyright their respective owners. @@ -32,7 +32,7 @@ their current versions as of June 2016 are: * [Python](/why-use-python.html) version [3.5.1](https://www.python.org/downloads/release/python-351/) * [Django](/django.html) web framework version - [1.9.7](https://docs.djangoproject.com/en/1.9/releases/1.9/) + [1.9.x](https://pypi.org/project/Django/1.9.13/) * [Green Unicorn (Gunicorn)](/green-unicorn-gunicorn.html) version [19.6](http://docs.gunicorn.org/en/stable/news.html) diff --git a/content/posts/170428-python-2-7-aws-lambda.markdown b/content/posts/170428-python-2-7-aws-lambda.markdown index 77a3e8ec9..c702fc194 100644 --- a/content/posts/170428-python-2-7-aws-lambda.markdown +++ b/content/posts/170428-python-2-7-aws-lambda.markdown @@ -3,7 +3,7 @@ slug: aws-lambda-python-2-7 meta: Learn how to create and deploy your first Amazon Web Services (AWS) Lambda function with Python 2.7. category: post date: 2017-04-28 -modified: 2017-04-29 +modified: 2021-03-30 newsletter: False headerimage: /img/170428-aws-lambda-python-2-7/header.jpg headeralt: AWS, AWS Lambda and Python logos, copyright their respective owners. @@ -22,6 +22,11 @@ function that executes some simple Python 2.7 code and handles environment variables. The code can then be modified to build far more complicated Python applications. +*Note*: AWS +[ended support for Python 2.7 Lambda functions in 2021](https://aws.amazon.com/blogs/compute/announcing-end-of-support-for-python-2-7-in-aws-lambda/) +and Python 2.7 no longer receives support so you should really be using +[Python 3.8 or above](https://aws.amazon.com/about-aws/whats-new/2019/11/aws-lambda-now-supports-python-3-8/). + ## Tools We Need We do not need any local development environment tools to get through diff --git a/content/posts/170723-monitor-flask-apps.markdown b/content/posts/170723-monitor-flask-apps.markdown index b3cd8b760..4ef02bfc6 100644 --- a/content/posts/170723-monitor-flask-apps.markdown +++ b/content/posts/170723-monitor-flask-apps.markdown @@ -165,7 +165,7 @@ The above [Jinja2](/jinja2.html) template is basic HTML without any [embedded template tags](http://jinja.pocoo.org/docs/latest/templates/). The template creates a very plain page with a header description of "PUBG so good" and a GIF from this -[excellent computer game](http://store.steampowered.com/app/578080/PLAYERUNKNOWNS_BATTLEGROUNDS/). +[excellent computer game](https://store.steampowered.com/app/578080/PUBG_BATTLEGROUNDS/). Time to run and test our code. Change into the base directory of your project where `app.py` file is located. Execute `app.py` using the `python` diff --git a/content/posts/190626-dev-led-sales-startups.markdown b/content/posts/190626-dev-led-sales-startups.markdown index 55e4ec431..ba8066e9e 100644 --- a/content/posts/190626-dev-led-sales-startups.markdown +++ b/content/posts/190626-dev-led-sales-startups.markdown @@ -456,9 +456,9 @@ tactics.

    Conferences split into a couple of categories: community-run and vendor-run. For example, -WWDC is Apple's vendor-run +WWDC is Apple's vendor-run developer conference. They run the show and control the messaging. -PyCon US is the community-run +PyCon US is the community-run Python developer conference. There are a ton of vendors there as sponsors but no one company controls what happens at the conference.

    diff --git a/content/posts/200308-financial-resources-developers.markdown b/content/posts/200308-financial-resources-developers.markdown new file mode 100644 index 000000000..80f2560d0 --- /dev/null +++ b/content/posts/200308-financial-resources-developers.markdown @@ -0,0 +1,112 @@ +title: The Best Resources for Developers to Learn Finance +slug: best-resources-developers-learn-finance +meta: Find out the best free and low cost finance newsletters, websites and books for developers to learn financial literacy. +category: post +date: 2020-03-08 +modified: 2020-03-08 +newsletter: True +headerimage: /img/visuals/email-post-header.jpg +headeralt: Python programming language and Full Stack Python logos. + + +Software developers should understand the basics of finance not only +to manage their own money but also to understand how businesses' software +projects are funded. + +Understanding how other people who work in accounting, finance and project +management think about business and finance in particular can help you make +better architectural decisions when trying to build maintainable systems. +Code is only one aspect of a large software project so working with others +and viewing the world through their discipline will help you immensely as +you advance your career. + + +## Newsletters & Podcasts on Finance +The fastest way to take a first step in improving your financial literacy +is to subscribe to a few free newsletters that regularly hit your inbox, +or a podcast if listening better fits your daily routine. I read and listen +to each of the following newsletters and podcasts to pick up on unfamiliar +topics then do more of my own research if I do not understand what they +are talking or writing about. + +* [Money Stuff by Matt Levine of Bloomberg](https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine) + ([newsletter sign up form](https://link.mail.bloombergbusiness.com/join/4wm/moneystuff-signup)) + is a hilarious must-read daily newsletter that covers the world of + finance and breaks down many absurd situations such as financial + fraud, insider trading, or competing interests in credit default swaps. + Amazingly, the author stays out of political topics, which I find very + refreshing because many other journalists seem to force their own biases + about finance down your throat even if you do not want their opinions. + +* [Endless Metrics](https://endlessmetrics.substack.com) explains financial + topics in a way that's easy for anyone without a finance background to + understand. For example, + [what the heck is GDP and how do you read a GDP chart?](https://endlessmetrics.substack.com/p/reading-a-gdp-chart). + What I love most about this newsletter is that the author will often + venture into finance-related topics he's interested in and then explain + those subjects while grounding them with useful charts and data. + This analytic approach closely matches how my developer brain processes + information! + +* [Points of Return by John Auther](https://www.bloomberg.com/authors/AT2bBytfUHQ/john-authers) + ([newsletter sign up form](http://link.mail.bloombergbusiness.com/join/4wm/opinion-authers-signup)). + This author is incredibly knowledgeable about finance and typically + provides a solid grounding in long-term fundamentals rather than the + short-term hyperbole that is pervasive in cable television financial + journalism. + +* [Odd Lots](https://www.bloomberg.com/podcasts/odd_lots) covers kind + of whatever topics the hosts find interesting such as pandemic bonds, + repo market disruption, sovereign debt restructuring and emerging + markets. That's why it's so good - the hosts bring on an expert in that + topic and ask a ton of great questions because they want to learn + what's going on for themselves. You follow along with them as they + try to understand some of the oft-esoteric subject areas of finance. + + +## Books, Websites and Magazines for Finance +Newsletters and podcasts are great for prodding you into discovering +topics you did not know you needed to learn. When you discover something +that you want to go deeper on in finance, here are a few of my favorite +books and websites that range from the very basics of finance to broader +macroeconomic data trends. + +* I learned most of my basic finance knowledge when I read + [Financial Intelligence for IT Professionals](https://www.amazon.com/Financial-Intelligence-Professionals-Really-Numbers/dp/1422119149) + in graduate school ([go Hoos](https://www.virginia.edu/)!). The book + is well-written, straightforward and accessible, particularly because + it clearly targets its software developer audience. + +* [Don't Quit Your Day Job](https://dqydj.com) uses a ton of metrics + and statistics to ground their articles on financial topics that + are often relevant specifically to software developers. For example, + the article on + [How Many Developers are There in America, and Where Do They Live?](https://dqydj.com/number-of-developers-in-america-and-per-state/) + is fascinating and especially useful because they explain their + data sources and analysis methodology. + +* [Money Magazine](https://money.com/) can be useful to pick up in paper + edition for a few months to understand personal finance basics. After a + few months you'll discover the articles and topics tend to recycle so + there are diminishing returns to reading it after you have familiarized + yourself with most of the topics. + +* [Longtermtrends](https://www.longtermtrends.net/) aggregates long term + high-level financial data and displays it. I find looking at these + charts gets me away from the day-to-day "oh the stock market is down" + and towards thinking about what happens when you invest money over many + years or decades. + + +## Specific Articles on Financial Topics +The following individual articles I have found to be both well-written and +extremely useful for specific scenarios such as evaluating stock-based +equity compensation, or negotiating your salary. + +* [Salary negotiation](https://www.kalzumeus.com/2012/01/23/salary-negotiation/) + +* [Stock Options](https://blog.alexmaccaw.com/an-engineers-guide-to-stock-options) + +* [Open Guide to Equity Compensation](https://github.com/jlevy/og-equity-compensation) + + diff --git a/content/posts/200328-explore-covid-pandas.markdown b/content/posts/200328-explore-covid-pandas.markdown new file mode 100644 index 000000000..1ffb8c6e4 --- /dev/null +++ b/content/posts/200328-explore-covid-pandas.markdown @@ -0,0 +1,315 @@ +title: Learning pandas by Exploring COVID-19 Data +slug: learn-pandas-basic-commands-explore-covid-19-data +meta: Use the pandas data analysis tool to explore the free COVID-19 data set provided by the European Centre for Disease Prevention and Control. +category: post +date: 2020-03-28 +modified: 2020-03-28 +newsletter: False +headerimage: /img/200328-covid-19-pandas/header.jpg +headeralt: pandas logo. Copyright the PyData Foundation. + + +The +[European Centre for Disease Prevention and Control](https://www.ecdc.europa.eu/en) +provides +[daily-updated worldwide COVID-19 data](https://www.ecdc.europa.eu/en/publications-data/download-todays-data-geographic-distribution-covid-19-cases-worldwide) +that is easy to download in JSON, CSV or XML formats. In this tutorial, +we will use the [pandas](/pandas.html) data analysis tool on the +comma-separated values (CSV) data to learn some of the basic pandas +commands and explore what is contained within the data set. + + +## Configuring our development environment +Make sure you have Python 3 installed. As of right now, +[Python 3.8.2](https://www.python.org/downloads/) is the latest. + +During this tutorial we're also going to use +[pandas](https://pandas.pydata.org/). + +Install it now into a new virtual environment with the following +commands: + +```bash +python -m venv covidpandas +source covidpandas/bin/activate + +pip install pandas +``` + +We are now ready to get the COVID-19 data and start analyzing it with +pandas. + + +## Obtaining the COVID-19 data +Go to the +[download today’s data on the geographic distribution of COVID-19 cases worldwide](https://www.ecdc.europa.eu/en/publications-data/download-todays-data-geographic-distribution-covid-19-cases-worldwide) +page in your web browser. It should look something like the following +screenshot. + +Download the CSV version of the COVID-19 data. + +There should be a link to download the +data in CSV format, but the organization has changed the page layout +several times in the past few weeks, which makes it difficult to find +formats other than Excel (XLSX). If you have trouble obtaining the +CSV version, just download +[this one from GitHub](https://raw.githubusercontent.com/fullstackpython/blog-code-examples/master/pandas-covid-19/covid-19-cases-march-28-2020.csv) +which is pegged to a copy downloaded on March 28th, 2020. + + + +## Importing the CSV into pandas +We have the data in a CSV now we need to import it into a pandas +DataFrame. + +Start by running the Python REPL: + +```bash +python + +>>> +``` + +The REPL is ready to go, now we need to import pandas so we can read +the data we downloaded. + +```python +from pandas import read_csv + +df = read_csv("covid-19-cases-march-28-2020.csv") +``` + +Don't worry if you get an error like +`UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe7...`. +Run this command instead which explicitly sets the file encoding +so pandas can properly read the CSV. + +```python +# make sure the file name of the csv matches your file's name! +df = read_csv("covid-19-cases-march-28-2020.csv", encoding="ISO-8859-1") +``` + +We now have our data loaded into a +[pandas DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) +and can start running code to poke and prod and what's inside the +data set. + + +## Running pandas commands +Let's first take a peek at what a sample of the data looks like. I +typically run the `head` and `tail` functions when I open something +up to find out what are contained in the first five and last five rows. + +```python +df.head() +``` + +You should see six lines of output: one as the columns header and the +first five rows of data from the CSV: + +``` + dateRep day month year cases deaths countriesAndTerritories geoId countryterritoryCode popData2018 +0 28/03/2020 28 3 2020 16 1 Afghanistan AF AFG 37172386.0 +1 27/03/2020 27 3 2020 0 0 Afghanistan AF AFG 37172386.0 +2 26/03/2020 26 3 2020 33 0 Afghanistan AF AFG 37172386.0 +3 25/03/2020 25 3 2020 2 0 Afghanistan AF AFG 37172386.0 +4 24/03/2020 24 3 2020 6 1 Afghanistan AF AFG 37172386.0 +``` + +The `tail` function looks at the last five rows in a DataFrame. + +``` +df.tail() +``` + +`tail` output will look something like this: + +``` + dateRep day month year cases deaths countriesAndTerritories geoId countryterritoryCode popData2018 +7315 25/03/2020 25 3 2020 0 0 Zimbabwe ZW ZWE 14439018.0 +7316 24/03/2020 24 3 2020 0 1 Zimbabwe ZW ZWE 14439018.0 +7317 23/03/2020 23 3 2020 0 0 Zimbabwe ZW ZWE 14439018.0 +7318 22/03/2020 22 3 2020 1 0 Zimbabwe ZW ZWE 14439018.0 +7319 21/03/2020 21 3 2020 1 0 Zimbabwe ZW ZWE 14439018.0 +``` + +Note that you can also pass an integer into `head` or `tail` like +`df.head(10)` to get the first or last **n** number of rows. + +It looks like based on the `tail` function we have around 7320 rows of +data (since the first row is 0 indexed). We can confirm how much +data is in each column with the `count` function. + +``` +df.count() +``` + +`count`'s output will look like: + +``` +dateRep 7320 +day 7320 +month 7320 +year 7320 +cases 7320 +deaths 7320 +countriesAndTerritories 7320 +geoId 7306 +countryterritoryCode 7254 +popData2018 7311 +dtype: int64 +``` + +What if we want to look at one of those columns and find, for example, +the highest value of cases? + +``` +df.cases.max() +``` + +In this data set we get 18695 as the output. What about looking at +standard statistical measures across all columns? That's where the +`describe` function comes in handy. + +``` +df.describe() +``` + +`describe` presents standard statistical measures such as min, max, +median and mean for everything in your data set. In this case we +receive as output: + +``` + day month year cases deaths popData2018 +count 7320.000000 7320.000000 7320.000000 7320.000000 7320.000000 7.311000e+03 +mean 16.828142 2.249454 2019.990847 80.870355 3.687158 7.130483e+07 +std 8.322981 1.256463 0.095239 608.270244 35.327689 2.140624e+08 +min 1.000000 1.000000 2019.000000 -9.000000 0.000000 1.000000e+03 +25% 10.000000 1.000000 2020.000000 0.000000 0.000000 4.137309e+06 +50% 18.000000 2.000000 2020.000000 0.000000 0.000000 1.072767e+07 +75% 24.000000 3.000000 2020.000000 5.000000 0.000000 5.139301e+07 +max 31.000000 12.000000 2020.000000 18695.000000 971.000000 1.392730e+09 +``` + +How about a quick view into whether or not columns' data are correlated +with each other? The `corr` function is what we need. + +``` +df.corr() +``` + +For our data set, `corr` outputs: + +``` + day month year cases deaths popData2018 +day 1.000000 0.203006 -0.163665 0.063629 0.060075 -0.040677 +month 0.203006 1.000000 -0.745912 0.062494 0.052707 -0.039131 +year -0.163665 -0.745912 1.000000 0.012715 0.010032 -0.006294 +cases 0.063629 0.062494 0.012715 1.000000 0.716968 0.136580 +deaths 0.060075 0.052707 0.010032 0.716968 1.000000 0.082229 +popData2018 -0.040677 -0.039131 -0.006294 0.136580 0.082229 1.000000 +``` + +Not surprisingly, we see 1.000000 correlation between a column and itself. +We'd have to worry if we didn't see that result! For other columns it may +not make sense to look at their correlation. This is where you need to +think about the data. There is often correlation between completely unrelated +columns just because the data is structured a certain way. + +If you are a developer like me without a rigorous background in statistics +(Stats 200 in college was a **long** time ago), you may need to brush up +on your stats knowledge before you are able to say whether something in the +data matters or not. + +Let's keep going exploring the data. We can select columns and determine how +many unique items are held within it. For example, how many unique countries +and territories are listed? + +``` +df.countriesAndTerritories.nunique() +``` + +In this case the result should be 196. + + +## Asking questions of the data +Those functions are fine for basic querying to learn what's in the +data set, but how do we ask real questions by stringing together some +commands? + +We now know there are 7320 rows in this set since we used the `count` +function above. Each row represents a single day within a country. Now +to ask a question. How many days across these countries were there 10 +or more cases reported? + +Let's create a new dataframe named df2 with the rows that only have +10 or more cases reported on that day, then count the number of rows +within it. + +``` +df2 = df[df['cases']>=10] +df2.count() +``` + +That should give us the value 1531. There have been 1531 instances +of 10 or more COVID-19 cases reported on a single day, across the +196 countries or terrorities listed. But the 1531 is hard to explain +to people. We should pick out a single country and show how many times +10 or more cases were reported on one day. How about a smaller +country like Vietnam that is not being reported on as much as China, +the United States or Italy? + +``` +df2[df2['countriesAndTerritories']=='Vietnam'] +``` + +This will give us the full output of data by column: + +``` + dateRep day month year cases deaths countriesAndTerritories geoId countryterritoryCode popData2018 +7217 28/03/2020 28 3 2020 16 0 Vietnam VN VNM 95540395.0 +7219 26/03/2020 26 3 2020 14 0 Vietnam VN VNM 95540395.0 +7220 25/03/2020 25 3 2020 11 0 Vietnam VN VNM 95540395.0 +7222 23/03/2020 23 3 2020 24 0 Vietnam VN VNM 95540395.0 +7226 19/03/2020 19 3 2020 15 0 Vietnam VN VNM 95540395.0 +``` + +We can also use the `count` function here to confirm there have been +five days in which 10 or more new cases have been reported in Vietnam +so far: + +``` +df2[df2['countriesAndTerritories']=='Vietnam'].count() +``` + +We get the output of 5 for the columns. Unfortunately, when you look at +the full data it appears these rows are all very recent and the virus +is just beginning to spread more widely there. Let's hope they along +with every other country is able to turn the tide, flatten the curve +and keep more people from getting sick as we continue onwards. + +That's a good spot to leave off, but we covered a lot of pandas ground +in this tutorial! + + +## What's next? +We just imported and took a look at what's in the European Centre +for Disease Prevention and Control's COVID-19 data set using +[pandas](/pandas.html). That was a quick tour of some basic pandas +commands and I strongly recommend you peruse the +[DataFrame documentation list](https://pandas.pydata.org/pandas-docs/stable/reference/frame.html) +to learn about all of the other handy functions that this tool +provides to developers. + +You can also get an idea of what to code next in your Python project by +reading the +[Full Stack Python table of contents page](/table-of-contents.html). + +Questions? Contact me via Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). I'm also on GitHub with +the username [mattmakai](https://github.com/mattmakai). + +Something wrong with this post? Fork +[this page's source on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/200328-explore-covid-pandas.markdown) +and submit a pull request. diff --git a/content/posts/200330-pandas-dataframes-sqlalchemy.markdown b/content/posts/200330-pandas-dataframes-sqlalchemy.markdown new file mode 100644 index 000000000..cfef8af42 --- /dev/null +++ b/content/posts/200330-pandas-dataframes-sqlalchemy.markdown @@ -0,0 +1,401 @@ +title: Exporting pandas DataFrames into SQLite with SQLAlchemy +slug: export-pandas-dataframes-sqlite-sqlalchemy +meta: Learn how to export data from pandas DataFrames into SQLite databases using SQLAlchemy. +category: post +date: 2020-03-30 +modified: 2020-03-30 +newsletter: False +headerimage: /img/200330-pandas-sqlite/header.jpg +headeralt: pandas and SQLite logos. Copyright their respective owners. + + +It is common when performing exploratory [data analysis](/data-analysis.html), +[for example when examining COVID-19 data with pandas](/blog/learn-pandas-basic-commands-explore-covid-19-data.html), +to load from files like a CSV, XML, or JSON into a +[pandas](/pandas.html) DataFrame. You may then do some work with the +data in the DataFrame and want to store it in a more durable location +like a [relational database](/databases.html). + +This tutorial walks through how to load a pandas DataFrame from a CSV +file, pull out some data from the full data set, then save the +subset of data to a [SQLite](/sqlite.html) database using +[SQLAlchemy](/sqlalchemy.html). + + +## Configuring our development environment +Make sure you have Python 3 installed. As of right now, +[Python 3.8.2](https://www.python.org/downloads/) is the latest +version of Python. + +During this tutorial we're also going to use: + +* [pandas](/pandas.html) ([project homepage](https://pandas.pydata.org/) + and [source code](https://github.com/pandas-dev/pandas)), version 1.0.3 + in this tutorial +* [SQLAlchemy](/sqlalchemy.html) + ([project homepage](https://www.sqlalchemy.org/) and + [source code](https://github.com/sqlalchemy/sqlalchemy)), version 1.3.15 + for this tutorial +* [SQLite](/sqlite.html) ([project homepage](https://sqlite.org/index.html) + and [source code](https://www.sqlite.org/src/doc/trunk/README.md)), + which Python + [includes a connector for as part of the Python standard library](https://docs.python.org/3/library/sqlite3.html) + + +Install the above code libraries into a new +[Python virtual environment](/virtual-environments-virtualenvs-venvs.html) +using the following commands: + +```bash +python -m venv pandasexport +source pandasexport/bin/activate + +pip install pandas==1.0.3 sqlalchemy==1.3.15 +``` + +Our [development environment](/development-environments.html) is now +ready to download an example COVID-19 data set, load it into a pandas +DataFrame, perform some analysis on it then save into a SQLite database. + + +## Obtaining COVID-19 data +Go to the +[download today’s data on the geographic distribution of COVID-19 cases worldwide](https://www.ecdc.europa.eu/en/publications-data/download-todays-data-geographic-distribution-covid-19-cases-worldwide) +page in your web browser. It should look something like the following +screenshot. + +Download the CSV version of the COVID-19 March 29, 2020 data. + +There should be a link to download the +data in CSV format, but the organization has changed the page layout +several times in the past few weeks, which makes it difficult to find +formats other than Excel (XLSX). If you have trouble obtaining the +CSV version, just download +[this one from GitHub](https://raw.githubusercontent.com/fullstackpython/blog-code-examples/master/pandas-covid-19/covid-19-cases-march-28-2020.csv) +which is pegged to a copy downloaded on March 28th, 2020. + + +## Importing the CSV into pandas +The raw data is in a CSV file and we need to load it into memory via a +pandas DataFrame. + +Start by running the Python Read-Evaluate-Print Loop (REPL) on the +command line: + +```bash +python + +>>> +``` + +The REPL is ready to execute code, but we first need to import the pandas +library so we can use it. + +```python +from pandas import read_csv + +df = read_csv("covid-19-cases-march-28-2020.csv", encoding="ISO-8859-1") +``` + +The data is now loaded into the `df` variable which is an instance of the +[pandas DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) +class. + +When we run the `count` function on this DataFrame, we get back that it +has 7320 rows. + +```python +df.count() +``` + +Next, we'll take this set of 7320 rows of data and slice out only +the rows that pertain to the United States. + + +## Creating a new DataFrame from the original DataFrame +We can pick out all of the rows of data for a single country using +a pandas function to match the `countriesAndTerritories` column +to the country of our choice. + + +```python +save_df = df[df['countriesAndTerritories']=="United_States_of_America"] +``` + +The `save_df` variable contains the smaller subset of data. You can +find out what's in it by having it print itself: + +```python +save_df +``` + +You should see something like the following output: + +``` + dateRep day month year cases deaths countriesAndTerritories geoId countryterritoryCode popData2018 +7082 28/03/2020 28 3 2020 18695 411 United_States_of_America US USA 327167434.0 +7083 27/03/2020 27 3 2020 16797 246 United_States_of_America US USA 327167434.0 +7084 26/03/2020 26 3 2020 13963 249 United_States_of_America US USA 327167434.0 +7085 25/03/2020 25 3 2020 8789 211 United_States_of_America US USA 327167434.0 +7086 24/03/2020 24 3 2020 11236 119 United_States_of_America US USA 327167434.0 +... ... ... ... ... ... ... ... ... ... ... +7166 04/01/2020 4 1 2020 0 0 United_States_of_America US USA 327167434.0 +7167 03/01/2020 3 1 2020 0 0 United_States_of_America US USA 327167434.0 +7168 02/01/2020 2 1 2020 0 0 United_States_of_America US USA 327167434.0 +7169 01/01/2020 1 1 2020 0 0 United_States_of_America US USA 327167434.0 +7170 31/12/2019 31 12 2019 0 0 United_States_of_America US USA 327167434.0 + +[89 rows x 10 columns] +``` + +89 rows of data out of the original 7320 rows. Let's proceed with +saving this subset to a SQLite relational database. + + +## Saving the DataFrame to SQLite +We are going to use [SQLAlchemy](/sqlalchemy.html) to create a connection +to a new SQLite database, which in this example will be stored in file +named `save_pandas.db`. You can of course save the file with whatever name +you want and in any location, not just the directory where you are +executing the Python REPL. + +Start by importing the `create_engine` function from the `sqlalchemy` +library. + +```python +from sqlalchemy import create_engine +``` + +Create the connection using the imported `create_engine` function +and then invoking the `connect` method on it. + +```python +engine = create_engine('sqlite:///save_pandas.db', echo=True) +sqlite_connection = engine.connect() +``` + +We set `echo=True` to see all of the output that comes from our +database connection. When the connection is successful you will +see output similar to the following: + +``` +2020-03-29 20:44:08,198 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1 +2020-03-29 20:44:08,198 INFO sqlalchemy.engine.base.Engine () +2020-03-29 20:44:08,199 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1 +2020-03-29 20:44:08,199 INFO sqlalchemy.engine.base.Engine () + +``` + +Set a variable name with the string of a table name you would like +to create. Then use that variable when invoking the `to_sql` +method on the `save_df` object, which is our pandas DataFrame that +is a subset of the original data set with 89 rows filtered from +the original 7320. + +Note that in this case we are going to fail if the table already +exists in the database. You can change `if_exists` to to `replace` +or `append` and add your own exception handling in a more robust +version of this program. Check the +[pandas.DataFrame.to_sql](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html) +documentation for the extensive details on your options. + +```python +sqlite_table = "Covid19" +save_df.to_sql(sqlite_table, sqlite_connection, if_exists='fail') +``` + +The echo output should spin up with a bunch of output. + +``` +2020-03-29 20:45:09,066 INFO sqlalchemy.engine.base.Engine PRAGMA main.table_info("Covid19") +2020-03-29 20:45:09,066 INFO sqlalchemy.engine.base.Engine () +2020-03-29 20:45:09,067 INFO sqlalchemy.engine.base.Engine PRAGMA temp.table_info("Covid19") +2020-03-29 20:45:09,067 INFO sqlalchemy.engine.base.Engine () +2020-03-29 20:45:09,069 INFO sqlalchemy.engine.base.Engine +CREATE TABLE "Covid19" ( + "index" BIGINT, + "dateRep" TEXT, + day BIGINT, + month BIGINT, + year BIGINT, + cases BIGINT, + deaths BIGINT, + "countriesAndTerritories" TEXT, + "geoId" TEXT, + "countryterritoryCode" TEXT, + "popData2018" FLOAT +) + + +2020-03-29 20:45:09,069 INFO sqlalchemy.engine.base.Engine () +2020-03-29 20:45:09,070 INFO sqlalchemy.engine.base.Engine COMMIT +2020-03-29 20:45:09,070 INFO sqlalchemy.engine.base.Engine CREATE INDEX "ix_Covid19_index" ON "Covid19" ("index") +2020-03-29 20:45:09,070 INFO sqlalchemy.engine.base.Engine () +2020-03-29 20:45:09,071 INFO sqlalchemy.engine.base.Engine COMMIT +2020-03-29 20:45:09,072 INFO sqlalchemy.engine.base.Engine BEGIN (implicit) +2020-03-29 20:45:09,074 INFO sqlalchemy.engine.base.Engine INSERT INTO "Covid19" ("index", "dateRep", day, month, year, cases, deaths, "countriesAndTerritories", "geoId", "countryterritoryCode", "popData2018") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) +2020-03-29 20:45:09,074 INFO sqlalchemy.engine.base.Engine ((7082, '28/03/2020', 28, 3, 2020, 18695, 411, 'United_States_of_America', 'US', 'USA', 327167434.0), (7083, '27/03/2020', 27, 3, 2020, 16797, 246, 'United_States_of_America', 'US', 'USA', 327167434.0), (7084, '26/03/2020', 26, 3, 2020, 13963, 249, 'United_States_of_America', 'US', 'USA', 327167434.0), (7085, '25/03/2020', 25, 3, 2020, 8789, 211, 'United_States_of_America', 'US', 'USA', 327167434.0), (7086, '24/03/2020', 24, 3, 2020, 11236, 119, 'United_States_of_America', 'US', 'USA', 327167434.0), (7087, '23/03/2020', 23, 3, 2020, 8459, 131, 'United_States_of_America', 'US', 'USA', 327167434.0), (7088, '22/03/2020', 22, 3, 2020, 7123, 80, 'United_States_of_America', 'US', 'USA', 327167434.0), (7089, '21/03/2020', 21, 3, 2020, 5374, 110, 'United_States_of_America', 'US', 'USA', 327167434.0) ... displaying 10 of 89 total bound parameter sets ... (7169, '01/01/2020', 1, 1, 2020, 0, 0, 'United_States_of_America', 'US', 'USA', 327167434.0), (7170, '31/12/2019', 31, 12, 2019, 0, 0, 'United_States_of_America', 'US', 'USA', 327167434.0)) +2020-03-29 20:45:09,074 INFO sqlalchemy.engine.base.Engine COMMIT +2020-03-29 20:45:09,075 INFO sqlalchemy.engine.base.Engine SELECT name FROM sqlite_master WHERE type='table' ORDER BY name +2020-03-29 20:45:09,075 INFO sqlalchemy.engine.base.Engine () +``` + +Our table with all of its data should now be all set. Close the database +connection. + +```python +sqlite_connection.close() +``` + +We can take a look at the data through the `sqlite3` command line viewer +to make sure it was properly saved to the SQLite file. + +On the command line (**not in the Python REPL**), type: + +```bash +sqlite3 +``` + +This will open up the command line prompt to interact with SQLite +databases. However, we are not yet connected to our `save_pandas.db` +file. + +``` +SQLite version 3.28.0 2019-04-15 14:49:49 +Enter ".help" for usage hints. +Connected to a transient in-memory database. +Use ".open FILENAME" to reopen on a persistent database. +sqlite> +``` + +Use the `.open` command with our `save_pandas.db` file name to +access the database. Then use a standard SQL query to obtain all +of the records from the `Covid19` table. + +``` +sqlite> .open save_pandas.db +sqlite> select * from Covid19; +``` + +The SQLite explorer should produce output like you see below: + +``` +7082|28/03/2020|28|3|2020|18695|411|United_States_of_America|US|USA|327167434.0 +7083|27/03/2020|27|3|2020|16797|246|United_States_of_America|US|USA|327167434.0 +7084|26/03/2020|26|3|2020|13963|249|United_States_of_America|US|USA|327167434.0 +7085|25/03/2020|25|3|2020|8789|211|United_States_of_America|US|USA|327167434.0 +7086|24/03/2020|24|3|2020|11236|119|United_States_of_America|US|USA|327167434.0 +7087|23/03/2020|23|3|2020|8459|131|United_States_of_America|US|USA|327167434.0 +7088|22/03/2020|22|3|2020|7123|80|United_States_of_America|US|USA|327167434.0 +7089|21/03/2020|21|3|2020|5374|110|United_States_of_America|US|USA|327167434.0 +7090|20/03/2020|20|3|2020|4835|0|United_States_of_America|US|USA|327167434.0 +7091|19/03/2020|19|3|2020|2988|42|United_States_of_America|US|USA|327167434.0 +7092|18/03/2020|18|3|2020|1766|23|United_States_of_America|US|USA|327167434.0 +7093|17/03/2020|17|3|2020|887|16|United_States_of_America|US|USA|327167434.0 +7094|16/03/2020|16|3|2020|823|12|United_States_of_America|US|USA|327167434.0 +7095|15/03/2020|15|3|2020|777|10|United_States_of_America|US|USA|327167434.0 +7096|14/03/2020|14|3|2020|511|7|United_States_of_America|US|USA|327167434.0 +7097|13/03/2020|13|3|2020|351|10|United_States_of_America|US|USA|327167434.0 +7098|12/03/2020|12|3|2020|287|2|United_States_of_America|US|USA|327167434.0 +7099|11/03/2020|11|3|2020|271|2|United_States_of_America|US|USA|327167434.0 +7100|10/03/2020|10|3|2020|200|5|United_States_of_America|US|USA|327167434.0 +7101|09/03/2020|9|3|2020|121|4|United_States_of_America|US|USA|327167434.0 +7102|08/03/2020|8|3|2020|95|3|United_States_of_America|US|USA|327167434.0 +7103|07/03/2020|7|3|2020|105|2|United_States_of_America|US|USA|327167434.0 +7104|06/03/2020|6|3|2020|74|1|United_States_of_America|US|USA|327167434.0 +7105|05/03/2020|5|3|2020|34|2|United_States_of_America|US|USA|327167434.0 +7106|04/03/2020|4|3|2020|22|3|United_States_of_America|US|USA|327167434.0 +7107|03/03/2020|3|3|2020|14|4|United_States_of_America|US|USA|327167434.0 +7108|02/03/2020|2|3|2020|20|1|United_States_of_America|US|USA|327167434.0 +7109|01/03/2020|1|3|2020|3|1|United_States_of_America|US|USA|327167434.0 +7110|29/02/2020|29|2|2020|6|0|United_States_of_America|US|USA|327167434.0 +7111|28/02/2020|28|2|2020|1|0|United_States_of_America|US|USA|327167434.0 +7112|27/02/2020|27|2|2020|6|0|United_States_of_America|US|USA|327167434.0 +7113|26/02/2020|26|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7114|25/02/2020|25|2|2020|18|0|United_States_of_America|US|USA|327167434.0 +7115|24/02/2020|24|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7116|23/02/2020|23|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7117|22/02/2020|22|2|2020|19|0|United_States_of_America|US|USA|327167434.0 +7118|21/02/2020|21|2|2020|1|0|United_States_of_America|US|USA|327167434.0 +7119|20/02/2020|20|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7120|19/02/2020|19|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7121|18/02/2020|18|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7122|17/02/2020|17|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7123|16/02/2020|16|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7124|15/02/2020|15|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7125|14/02/2020|14|2|2020|1|0|United_States_of_America|US|USA|327167434.0 +7126|13/02/2020|13|2|2020|1|0|United_States_of_America|US|USA|327167434.0 +7127|12/02/2020|12|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7128|11/02/2020|11|2|2020|1|0|United_States_of_America|US|USA|327167434.0 +7129|10/02/2020|10|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7130|09/02/2020|9|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7131|08/02/2020|8|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7132|07/02/2020|7|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7133|06/02/2020|6|2|2020|1|0|United_States_of_America|US|USA|327167434.0 +7134|05/02/2020|5|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7135|04/02/2020|4|2|2020|0|0|United_States_of_America|US|USA|327167434.0 +7136|03/02/2020|3|2|2020|3|0|United_States_of_America|US|USA|327167434.0 +7137|02/02/2020|2|2|2020|1|0|United_States_of_America|US|USA|327167434.0 +7138|01/02/2020|1|2|2020|1|0|United_States_of_America|US|USA|327167434.0 +7139|31/01/2020|31|1|2020|1|0|United_States_of_America|US|USA|327167434.0 +7140|30/01/2020|30|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7141|29/01/2020|29|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7142|28/01/2020|28|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7143|27/01/2020|27|1|2020|3|0|United_States_of_America|US|USA|327167434.0 +7144|26/01/2020|26|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7145|25/01/2020|25|1|2020|1|0|United_States_of_America|US|USA|327167434.0 +7146|24/01/2020|24|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7147|23/01/2020|23|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7148|22/01/2020|22|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7149|21/01/2020|21|1|2020|1|0|United_States_of_America|US|USA|327167434.0 +7150|20/01/2020|20|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7151|19/01/2020|19|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7152|18/01/2020|18|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7153|17/01/2020|17|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7154|16/01/2020|16|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7155|15/01/2020|15|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7156|14/01/2020|14|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7157|13/01/2020|13|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7158|12/01/2020|12|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7159|11/01/2020|11|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7160|10/01/2020|10|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7161|09/01/2020|9|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7162|08/01/2020|8|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7163|07/01/2020|7|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7164|06/01/2020|6|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7165|05/01/2020|5|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7166|04/01/2020|4|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7167|03/01/2020|3|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7168|02/01/2020|2|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7169|01/01/2020|1|1|2020|0|0|United_States_of_America|US|USA|327167434.0 +7170|31/12/2019|31|12|2019|0|0|United_States_of_America|US|USA|327167434.0 +sqlite> +``` + +All of the data with the `countriesAndTerritories` column matching +`United_States_of_America` is there! We successfully exported the +data from the DataFrame into the SQLite database file. + + +## What's Next? +We just imported data from a CSV into a pandas DataFrame, selected a +subset of that data then saved it to a relational database. + +You should take a look at the +[Learning pandas by Exploring COVID-19 Data](/blog/learn-pandas-basic-commands-explore-covid-19-data.html) +tutorial to learn more about how to select subsets of data from a +larger DataFrame, or head to the [pandas](/pandas.html) page for +more tutorials by the rest of the Python community. + +You can also get an idea of what to code next in your Python project by +reading the +[Full Stack Python table of contents page](/table-of-contents.html). + +Questions? Contact me via Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). I'm also on GitHub with +the username [mattmakai](https://github.com/mattmakai). + +Something wrong with this post? Fork +[this page's source on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/200330-pandas-dataframes-sqlalchemy.markdown) +and submit a pull request. diff --git a/content/posts/200525-python-exceptions-sentry.markdown b/content/posts/200525-python-exceptions-sentry.markdown new file mode 100644 index 000000000..2ff43f88e --- /dev/null +++ b/content/posts/200525-python-exceptions-sentry.markdown @@ -0,0 +1,376 @@ +title: Reporting Exceptions in Python Scripts with Sentry +slug: report-exceptions-python-scripts-sentry +meta: Learn how to catch exceptions in Python scripts and then use Sentry to store and analyze the errors. +category: post +date: 2020-05-25 +modified: 2020-05-25 +newsletter: False +headerimage: /img/200525-sentry/header.jpg +headeralt: Python and Sentry logos. Copyright their respective owners. + + +Python scripts are the glue that keep many applications and their +infrastructure running, but when one of your scripts throws an exception +you may not know about it immediately unless you have a central place to +aggregate the errors. That's where adding [Sentry](https://sentry.io/) +can solved this distributed error logging problem. + +In this tutorial, we'll see how to quickly add Sentry to a new or existing +Python script to report errors into a centralized location for further +[debugging](/debugging.html). + + +## Development environment setup +Make sure you have Python 3 installed. As of right now, +[Python 3.8.3](https://www.python.org/downloads/) is the latest +version of Python. + +During this tutorial we're also going to use: + +* a hosted Sentry instance on [sentry.io](https://sentry.io), which we'll + need an account to access +* the [Sentry Python helper library](https://pypi.org/project/sentry-sdk/) to + send exception data to our Sentry instance + + +Install the above code libraries into a new +[Python virtual environment](/virtual-environments-virtualenvs-venvs.html) +using the following commands: + +```bash +python -m venv sentryscript +source sentryscript/bin/activate + +pip install sentry-sdk>=0.14.4 +``` + +Our [development environment](/development-environments.html) is now +ready and we can write some code that will throw exceptions to demonstrate +how to use Sentry. + +Note that all of the code for this tutorial can be found within the +[blog-code-examples](https://github.com/fullstackpython/blog-code-examples) +Git repository on GitHub under the +[python-script-sentry](https://github.com/fullstackpython/blog-code-examples/tree/master/python-script-sentry) +directory. + + +## An Example Script for Loading Python Modules +We'll start by writing a small but useful script that prints out the +names of all modules within a Python package, then add Sentry to it +when it becomes apparent that capturing exceptions would be a +useful addition. + +Create a new file named `module_loader.py` and write the +following lines of code in it to allow us to easily execute it +on the command line. + +```python +import argparse + +def import_submodules(package): + return {} + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("package") + args = parser.parse_args() + + package_to_load = args.package + results = import_submodules(package_to_load) + for r in results: + print(str(r)) +``` + +The above code takes an argument when the script is invoked from the +command line and uses the value as an input into the stub +`import_submodules` function that will contain code to walk the +tree of modules within the package. + +Nextt, add the following highlighted lines of code to use `importlib` and +`pkgutil` to recursively import modules from the package if one is +found that matches the name sent in as the `package` argument. + +```python +import argparse +~~import importlib +~~import pkgutil + + +def import_submodules(package): +~~ """Import all submodules of a module, recursively, including subpackages. + +~~ :param package: package (name or actual module) +~~ :type package: str | module +~~ :rtype: dict[str, types.ModuleType] +~~ """ +~~ if isinstance(package, str): +~~ package = importlib.import_module(package) +~~ results = {} +~~ for loader, name, is_pkg in pkgutil.walk_packages(package.__path__): +~~ full_name = package.__name__ + '.' + name +~~ try: +~~ results[full_name] = importlib.import_module(full_name) +~~ if is_pkg: +~~ results.update(import_submodules(full_name)) +~~ except ModuleNotFoundError as mnfe: +~~ print("module not found: {}".format(full_name)) +~~ except Exception as general_exception: +~~ print(general_exception) +~~ return results + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("package") + args = parser.parse_args() + + package_to_load = args.package + results = import_submodules(package_to_load) + for r in results: + print(str(r)) +``` + +The new code above loops through all packages with the +`walk_package` function in the `pkgutil` standard library +module and tries to import it using the `import_module` on +the package name plus package as a string. If the +result is successful, the function will recursively call +itself to import submodules within the imported package. +If a module is not found, or some other issue occurs, exceptions +are caught so that the script does not fail but instead can +continue processing potential modules. + +Test the full script to see what it prints out with an arbitrary +package on the command line: + +```bash +python module_loader.py importlib +``` + +The above example generates the output: + +```bash +importlib._bootstrap +importlib._bootstrap_external +importlib.abc +importlib.machinery +importlib.resources +importlib.util +``` + +Trying to inspect a package that is not installed will give an error. Use +the script with a package that is not installed in your current environment. + +```bash +python module_loader.py flask +``` + +The above command produces the following traceback due to an expected +`ModuleNotFoundError`. + +``` +Traceback (most recent call last): + File "module_loader.py", line 35, in + results = import_submodules(package_to_load) + File "module_loader.py", line 14, in import_submodules + package = importlib.import_module(package) + File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/__init__.py", line 127, in import_module + return _bootstrap._gcd_import(name[level:], package, level) + File "", line 1006, in _gcd_import + File "", line 983, in _find_and_load + File "", line 965, in _find_and_load_unlocked +ModuleNotFoundError: No module named 'flask' +``` + +If you install Flask into your current environment the module is found and +the application will go through the list of modules and submodules. + +Our example script is usable but what if we run this code or something similar +on one or more servers that we don't check that often? That's where it would +be helpful to have a way to aggregate one or more scripts' exception output +in a single place. Sentry can help us to accomplish that goal. + + +## Adding Exception Reporting with Sentry +Sentry can either be [self-hosted](https://github.com/getsentry/onpremise) or +used as a cloud service through [Sentry.io](https://sentry.io). In this +tutorial we will use the cloud hosted version because it's faster than +setting up your own server as well as free for smaller projects. + +Go to [Sentry.io's homepage](https://sentry.io). + +Sentry.io homepage where you can sign up for a free account. + +Sign into your account or sign up for a new free account. You will be at +the main account dashboard after logging in or completing the Sentry sign +up process. + +There are no errors logged on our account dashboard yet, which is as +expected because we have not yet connected our account to the Python +script. + +Blank Sentry account dashboard. + +You'll want to create a new Sentry Project just for this application so +click "Projects" in the left sidebar to go to the Projects page. + +Button to create a new Sentry project. + +On the Projects page, click the "Create Project" button in the top right +corner of the page. + +Create a new Sentry project. + +Select Python, give your new Project a name and then press the "Create Project" +button. Our new project is ready to integrate with our Python script. + +We need the unique identifier for our account and project to authorize our +Python code to send errors to this Sentry instance. The easiest way to get +what we need is to go to the +[Python getting started documentation page](https://docs.sentry.io/error-reporting/quickstart/?platform=python) +and scroll down to the "Configure the SDK" section. + +The Sentry docs show you exactly what you need to export to connect to your account. + +Copy the string parameter for the `init` method and +[set it as an environment variable](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html) +rather than exposing it directly in your application code. + +```bash +export SENTRY_DSN='https://yourkeygoeshere.ingest.sentry.io/project-number' +``` + +**Make sure to replace "yourkeygoeshere" with your own unique identifier +and "project-number" with the ID that matches the project you just +created.** + +Check that the `SENTRY_DSN` is set properly in your shell using the `echo` +command: + +```bash +echo $SENTRY_DSN +``` + +Modify the application to send exception information to Sentry now +that we have our unique identifier. Open `module_loader.py` again and +update the following highlighted lines of code. + +```python +import argparse +import importlib +~~import os +import pkgutil +~~import sentry_sdk +~~from sentry_sdk import capture_exception + +~~# find on https://docs.sentry.io/error-reporting/quickstart/?platform=python +~~sentry_sdk.init(dsn=os.getenv('SENTRY_DSN')) + + +def import_submodules(package): + """Import all submodules of a module, recursively, including subpackages. + + :param package: package (name or actual module) + :type package: str | module + :rtype: dict[str, types.ModuleType] + """ + if isinstance(package, str): + package = importlib.import_module(package) + results = {} + for loader, name, is_pkg in pkgutil.walk_packages(package.__path__): + full_name = package.__name__ + '.' + name + try: + results[full_name] = importlib.import_module(full_name) + if is_pkg: + results.update(import_submodules(full_name)) + except ModuleNotFoundError as mnfe: + print("module not found: {}".format(full_name)) +~~ capture_exception(mnfe) + except Exception as general_exception: + print(general_exception) +~~ capture_exception(general_exception) + return results + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("package") + args = parser.parse_args() + + package_to_load = args.package + results = import_submodules(package_to_load) + for r in results: + print(str(r)) +``` + +These new lines of code import the +[Sentry Python SDK](https://github.com/getsentry/sentry-python) and `os` +library (to read system environment variables). The application then +initializes the Sentry SDK with the string found in the `SENTRY_DSN` +environment variable. Down in the `import_submodules` function we +then call the `capture_exception` SDK function whenever a +`ModuleNotFoundException` is thrown or another exception which would +be caught within the broader `Exception` bucket. + +Now that our code is in place, let's test out the new Sentry integration. + + +## Testing the Script and Viewing Exceptions +The easiest way to test out whether the Sentry code is working or not is +to try to import a module that does not exist. Let's say you make a +typo in your command and try to run the script on `importliba` instead +of `importlib` (maybe because you are using an awful Macbook Pro "butterfly" +keyboard instead of a durable keyboard). Try it out and see what happens: + +```bash +python module_loader.py importliba +``` + +The script will run and finish but there will be errors because that +module does not exist. Thanks to our new code, we can view the +errors in Sentry. + +Check the Sentry dashboard to see the error. + +Viewing the first exception in the Sentry dashboard. + +We can also click into the error to learn more about what happened. + +The exception details in the Sentry dashboard. + +You can also receive email reports on the errors that occur so that +you do not have to always stay logged into the dashboard. + +The exception via email. + +With that all configured, we've now got a great base to expand the script +and build better error handling with Sentry as our Python application +becomes more complex. + + +## What's Next? +We just created an example script that outputs all of the modules and +submodules in a package, then added Sentry to it so that it would report +any exceptions back to our central hosted instance. + +That's just a simple introduction to Sentry, so next you'll want to +read one of the following articles to do more with it: + +* [Python Sentry docs](https://docs.sentry.io/platforms/python/) +* [How to use Sentry with Flask](https://docs.sentry.io/platforms/python/flask/) +* [Integrating Sentry into Celery task queues](https://docs.sentry.io/platforms/python/celery/) + +You can also get an idea of what to code next in your Python project by +reading the +[Full Stack Python table of contents page](/table-of-contents.html). + +Questions? Contact me via Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). I'm also on GitHub with +the username [mattmakai](https://github.com/mattmakai). + +Something wrong with this post? Fork +[this page's source on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/200525-python-exceptions-sentry.markdown) +and submit a pull request. diff --git a/content/posts/200630-report-errors-flask-web-apps-sentry.markdown b/content/posts/200630-report-errors-flask-web-apps-sentry.markdown new file mode 100644 index 000000000..2e9ec9684 --- /dev/null +++ b/content/posts/200630-report-errors-flask-web-apps-sentry.markdown @@ -0,0 +1,264 @@ +title: How to Report Errors in Flask Web Apps with Sentry +slug: report-errors-flask-web-apps-sentry +meta: Learn how to use Sentry and the Flask integration to easily report errors in your Python-based web applications. +category: post +date: 2020-06-30 +modified: 2020-07-02 +newsletters: False +headerimage: /img/headers/flask-sentry.jpg +headeralt: Logos for the implementations used in this blog post. Copyright their respective owners. + + +[Flask](/flask.html) web applications are highly customizable by developers +thanks to the [framework](/web-frameworks.html)'s extension-based +architecture, but that flexibility can sometimes lead to more errors +when you run the application due to rough edges between the libraries. + +Reporting errors is crucial to running a well-functioning Flask web +application, so this tutorial will guide you through adding a free, basic +[Sentry](https://sentry.io) configuration to a fresh Flask project. + + +## Tutorial Requirements +Ensure you have Python 3 installed, because Python 2 reached its +end-of-life at the beginning of 2020 and is no longer supported. +Preferrably, you should have +[Python 3.7 or greater installed](https://www.python.org/downloads/) +in your [development environment](/development-environments.html). +This tutorial will also use: + +* [Flask](/flask.html) web framework, + [version 1.1.2](https://github.com/pallets/flask/releases/tag/1.1.2) +* a hosted Sentry instance on [sentry.io](https://sentry.io), which we'll + need an account to access +* the [Sentry Python helper library](https://pypi.org/project/sentry-sdk/) to + send exception data to our Sentry instance, with the + [Flask integration](https://docs.sentry.io/platforms/python/flask/) + +All code in this blog post is available open source under the MIT license +on GitHub under the +[report-errors-flask-web-apps-sentry directory of the blog-code-examples](https://github.com/fullstackpython/blog-code-examples/tree/master/report-errors-flask-web-apps-sentry) +repository. Use the source code as you desire for your own projects. + + +## Development environment set up +Change into the directory where you keep your Python +[virtual environments](/virtual-environments-virtualenvs-venvs.html). +Create a new virtualenv for this project using the following +command. + +Install the Flask and Sentry-SDK code libraries into a new Python +virtual environment using the following commands: + +```bash +python -m venv sentryflask +source sentryflask/bin/activate + +pip install flask>=1.1.2 sentry-sdk[flask]==0.15.1 +``` + +Note that we installed the Flask integration as part of the Sentry +SDK, which is why the dependency is `sentry-sdk[flask]` rather than +just `sentry-sdk`. + +Now that we have all of our dependencies installed we can code up a +little application to show how the error reporting works. + + +## Creating the application +We have everything we need to start building our application. Create +a new directory for your project. I've called mine +[report-errors-flask-web-apps-sentry](https://github.com/fullstackpython/blog-code-examples/tree/master/report-errors-flask-web-apps-sentry) +in the examples repository but you can use a shorter name if you +prefer. Open a new file named `app.py` and write the following code in it. + +```python +# app.py +from flask import Flask, escape, request + + +app = Flask(__name__) + + +@app.route('/divide//by//') +def hello(numerator, denominator): + answer = numerator / denominator + return f'{numerator} can be divided by {denominator} {answer} times.' + +``` + +The above code is a short Flask application that allows input via the URL for +two integer values: a numerator and a denominator. + +Save the file and run it using the `flask run` command: + +```bash +env FLASK_APP=app.py flask run +``` + +If you see the following output on the command line that means the development +server is working properly: + +```bash + * Serving Flask app "app.py" + * Environment: production + WARNING: This is a development server. Do not use it in a production deployment. + Use a production WSGI server instead. + * Debug mode: off + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) +``` + +Test it by going to http://localhost:5000/divide/50/by/10/ and you will +get the following output in your web browser: + +Successful division of 50 by 10. + +With our base application working, we can now add error reporting for +the situations that do not work as expected. + + +## Adding Sentry to the Flask app +It's time to add Sentry with the Flask integration into the mix, so that we +can easily see when the route errors out due to bad input. + +Sentry can either be [self-hosted](https://github.com/getsentry/onpremise) or +used as a cloud service through [Sentry.io](https://sentry.io). In this +tutorial we will use the cloud hosted version because it's faster than +setting up your own server as well as free for smaller projects. + +Go to [Sentry.io's homepage](https://sentry.io). + +Sentry.io homepage where you can sign up for a free account. + +Sign into your account or sign up for a new free account. You will be at +the main account dashboard after logging in or completing the Sentry sign +up process. + +There are no errors logged on our account dashboard yet, which is as +expected because we have not yet connected our account to our Python +application. + +Blank Sentry account dashboard. + +You'll want to create a new Sentry Project just for this application so +click "Projects" in the left sidebar to go to the Projects page. + +Button to create a new Sentry project. + +On the Projects page, click the "Create Project" button in the top right +corner of the page. + +Create a new Sentry project. + +You can either choose "Flask" or select "Python". I usually just choose +"Python" if I do not yet know what framework I'll be using to build my +application. Next, give your new Project a name and then press the "Create +Project" button. Our new project is ready to integrate with our Python code. + +We need the unique identifier for our account and project to authorize our +Python code to send errors to this Sentry instance. The easiest way to get +what we need is to go to the +[Python+Flask documentation page](https://docs.sentry.io/platforms/python/flask/) +and read how to configure the SDK. + +The Sentry docs show you exactly what you need to export to connect to your account. + +Copy the string parameter for the `init` method and set it +[as an environment variable](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html) +rather than having it exposed in your project's code. + +```bash +export SENTRY_DSN='https://yourkeygoeshere.ingest.sentry.io/project-number' +``` + +**Make sure to replace "yourkeygoeshere" with your own unique identifier +and "project-number" with the ID that matches the project you just +created.** + +Check that the `SENTRY_DSN` is set properly in your shell using the `echo` +command: + +```bash +echo $SENTRY_DSN +``` + + +Update `app.py` with the following highlighted lines of code. + +```python +# app.py +~~import os +~~import sentry_sdk +from flask import Flask, escape, request +~~from sentry_sdk.integrations.flask import FlaskIntegration + + +~~sentry_sdk.init( +~~ dsn=os.getenv('SENTRY_DSN'), integrations=[FlaskIntegration()] +~~) + + +app = Flask(__name__) + + +@app.route('/divide//by//') +def hello(numerator, denominator): + answer = numerator / denominator + return f'{numerator} can be divided by {denominator} {answer} times.' +``` + +The above new lines of code initialize the Sentry client and allow it to +properly send any errors that occur over to the right Sentry service. + + +## Testing the Sentry Integration +The Sentry dashboard shows that the service is still waiting for events. + +Sentry dashboard, without any error data shown. + +Let's make an error happen to see if we've properly connected the Flask integration +with our application. + +Try to divide by zero, by going to http://localhost:5000/divide/50/by/0/ in +your web browser. You should get an "Internal Server Error". + +Flask HTTP status code 500 for internal server error. + +Back over in the Sentry dashboard, the error appears in the list. + +Sentry dashboard showing the exact ZeroDivisionError. + +We can drill into the error by clicking on it and get a ton more information, +not just about our application but also about the client that visited the +site. This is handy if you have an issue in a specific browser or other +type of client when building an [API](/application-programming-interfaces.html). + +ZeroDivisionError error details in the Sentry user interface. + +With that in place, you can now build out the rest of your Flask application +knowing that all of the exceptions will be tracked in Sentry. + + +## What's next? +We just finished building a Flask app to show how quickly the hosted +version of Sentry can be added to applications so you do not lose +track of your error messages. + +Next, you can try one of these tutorials to add other useful features to your +new application: + +* [Responding to SMS Text Messages with Python & Flask](/blog/respond-sms-text-messages-python-flask.html) +* [Develop and Run Flask Apps within Docker Containers](/blog/develop-flask-web-apps-docker-containers-macos.html) +* [Add Okta Authentication to an Existing Flask App](/blog/okta-user-auth-existing-flask-web-app.html) + +You can also determine what to code next in your Python project by reading +the [Full Stack Python table of contents page](/table-of-contents.html). + +Questions? Contact me via Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). I am also on GitHub with +the username [mattmakai](https://github.com/mattmakai). + +If you see an issue or error in this tutorial, please +[fork the source repository on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/200630-report-errors-flask-web-apps-sentry.markdown) +and submit a pull request with the fix. diff --git a/content/posts/200705-bootstrap-4-django-template.markdown b/content/posts/200705-bootstrap-4-django-template.markdown new file mode 100644 index 000000000..96e105df8 --- /dev/null +++ b/content/posts/200705-bootstrap-4-django-template.markdown @@ -0,0 +1,350 @@ +title: Quickly Use Bootstrap 4 in a Django Template with a CDN +slug: bootstrap-4-django-template +meta: Use the Bootstrap 4 CDN to quickly add Bootstrap styling and functionality to Django web apps. +category: post +date: 2020-07-05 +modified: 2020-07-05 +newsletter: False +headerimage: /img/headers/django-bootstrap.jpg +headeralt: Logos for the implementations used in this blog post. Copyright their respective owners. + + +The [Django](/django.html) [web framework](/web-frameworks.html) +makes it easy to render HTML using the [Django template engine](/django-templates.html). +However, the default styling on HTML pages usually need a +[Cascading Style Sheet (CSS)](/cascading-style-sheets.html) framework such as +Bootstrap to make the design look decent. +In this beginner's tutorial, we'll use the [Bootstrap](/bootstrap-css.html) +[Content Delivery Network (CDN)](/content-delivery-networks-cdns.html) +to quickly add Bootstrap to a rendered HTML page. + +Here is what the `

    ` element styling will look like at the end +of this tutorial: + +Bootstrap-enhanced HTML page saying 'Hello, world!'. + + +## Tutorial Requirements +Throughout this tutorial we are going to use the following dependencies, +which we will install in just a moment. Make sure you also have Python 3, +[preferrably 3.7 or newer installed](https://www.python.org/downloads/), +in your environment: + +We will use the following dependencies to complete this +tutorial: + +* [Django](/django.html) [web framework](/web-frameworks.html), + [version 3.0.8](https://www.djangoproject.com/download/) + +All code in this blog post is available open source under the MIT license +on GitHub under the +[bootstrap-4-django-template directory of the blog-code-examples repository](https://github.com/fullstackpython/blog-code-examples). +Use the source code as you desire for your own projects. + + +## Development environment set up +Change into the directory where you keep your Python +[virtual environments](/virtual-environments-virtualenvs-venvs.html). +Create a new virtualenv for this project using the following +command. + +Start the Django project by creating a new +[virtual environment](/virtual-environments-virtualenvs-venvs.html) +using the following command. I recommend using a separate directory +such as `~/venvs/` (the tilde is a shortcut for your user's `home` +directory) so that you always know where all your virtualenvs are +located. + +```bash +python3 -m venv ~/venvs/djbootstrap4 +``` + +Activate the virtualenv with the `activate` shell script: + +```bash +source ~/venvs/djbootstrap4/bin/activate +``` + +After the above command is executed, the command prompt will +change so that the name of the virtualenv is prepended to the +original command prompt format, so if your prompt is simply +`$`, it will now look like the following: + +```bash +(djbootstrap4) $ +``` + +Remember, you have to activate your virtualenv in every new terminal +window where you want to use dependencies in the virtualenv. + +We can now install the [Django](https://pypi.org/project/Django/) +package into the activated but otherwise empty virtualenv. + +``` +pip install django==3.0.8 +``` + +Look for output similar to the following to confirm the appropriate +packages were installed correctly from PyPI. + +``` +Collecting django + Using cached https://files.pythonhosted.org/packages/ca/ab/5e004afa025a6fb640c6e983d4983e6507421ff01be224da79ab7de7a21f/Django-3.0.8-py3-none-any.whl +Collecting sqlparse>=0.2.2 (from django) + Using cached https://files.pythonhosted.org/packages/85/ee/6e821932f413a5c4b76be9c5936e313e4fc626b33f16e027866e1d60f588/sqlparse-0.3.1-py2.py3-none-any.whl +Collecting asgiref~=3.2 (from django) + Using cached https://files.pythonhosted.org/packages/d5/eb/64725b25f991010307fd18a9e0c1f0e6dff2f03622fc4bcbcdb2244f60d6/asgiref-3.2.10-py3-none-any.whl +Collecting pytz (from django) + Using cached https://files.pythonhosted.org/packages/4f/a4/879454d49688e2fad93e59d7d4efda580b783c745fd2ec2a3adf87b0808d/pytz-2020.1-py2.py3-none-any.whl +Installing collected packages: sqlparse, asgiref, pytz, django +Successfully installed asgiref-3.2.10 django-3.0.8 pytz-2020.1 sqlparse-0.3.1 +``` + +We can get started coding the application now that we have all of our +required dependencies installed. + + +## Building our application +Let's begin coding our application. + +We can use the [Django](/django.html) `django-admin` tool to create +the boilerplate code structure to get our project started. +Change into the directory where you develop your applications. For +example, I typically use `/Users/matt/devel/py/` for all of my +Python projects. Then run the following command to start a Django +project named `djbootstrap4`: + +``` +django-admin.py startproject djbootstrap4 +``` + +Note that in this tutorial we are using the same name for both the +virtualenv and the Django project directory, but they can be +different names if you prefer that for organizing your own projects. + +The `django-admin` command creates a directory named `djbootstrap4` +along with several subdirectories that you should be familiar with +if you have previously worked with Django. + +Change directories into the new project. + +``` +cd djbootstrap4 +``` + +Create a new Django app within `djbootstrap4`. + +``` +python manage.py startapp bootstrap4 +``` + +Django will generate a new folder named `bootstrap4` for the project. +We should update the URLs so the app is accessible before we write +our `views.py` code. + +Open `djbootstrap4/djbootstrap4/urls.py`. Add the highlighted +lines so that URL resolver will check the `bootstrap4` app +for additional routes to match with URLs that are requested of +this Django application. + +```python +# djbootstrap4/djbootstrap4/urls.py +~~from django.conf.urls import include +from django.contrib import admin +from django.urls import path + + +urlpatterns = [ +~~ path('', include('bootstrap4.urls')), + path('admin/', admin.site.urls), +] +``` + +Save `djbootstrap4/djbootstrap4/urls.py` and open +`djbootstrap4/djbootstrap4/settings.py`. +Add the `bootstrap4` app to `settings.py` by inserting +the highlighted line: + +```python +# djbootstrap4/djbootstrap4/settings.py +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +~~ 'bootstrap4', +] +``` + +Make sure you change the default `DEBUG` and `SECRET_KEY` +values in `settings.py` before you deploy any code to production. Secure +your app properly with the information from the Django +[production deployment checklist](https://docs.djangoproject.com/en/stable/howto/deployment/checklist/) +so that you do not add your project to the list of hacked applications +on the web. + +Save and close `settings.py`. + +Next change into the `djbootstrap4/bootstrap4` directory. Create +a new file named `urls.py` to contain routes for the `bootstrap4` app. + +Add all of these lines to the empty `djbootstrap4/bootstrap4/urls.py` +file. + +```python +# djbootstrap4/bootstrap4/urls.py +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'', views.bootstrap4_index, name="index"), +] +``` + +Save `djbootstrap4/bootstrap4/urls.py`. Open +`djbootstrap4/bootstrap4/views.py` to add the +following two highlighted lines. You can keep the boilerplate comment +"# Create your views here." or delete like I usually do. + +``` +# djbootstrap4/bootstrap4/views.py +from django.shortcuts import render + + +~~def bootstrap4_index(request): +~~ return render(request, 'index.html', {}) +``` + + +Next, create a directory for your template files named `templates` under +the `djmaps/maps` app directory. + +``` +mkdir templates +``` + +Create a new file named `index.html` within +`djbootstrap4/bootstrap4/templates` that contains the +following [Django template language](/django-templates.html) markup. + +``` + + + + First step for bootstrap4 + + +

    Hello, world!

    + + +``` + +We can test out this static page to make sure all of our code is +correct before we start adding the meat of the functionality to +the project. Change into the base directory of your Django project +where the `manage.py` file is located. Execute the development +server with the following command: + +```bash +python manage.py runserver +``` + +The Django development server should start up with no issues other than +an unapplied migrations warning. + +``` +Watching for file changes with StatReloader +Performing system checks... + +System check identified no issues (0 silenced). + +You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. +Run 'python manage.py migrate' to apply them. + +July 05, 2020 - 10:59:58 +Django version 3.0.8, using settings 'djbootstrap4.settings' +Starting development server at http://127.0.0.1:8000/ +Quit the server with CONTROL-C. +``` + +Open a web browser and go to "http://localhost:8000". + +Plain old HTML page saying 'Hello, world!'. + +With our base application working, we can now add Bootstrap. + + +## Integrating Bootstrap +Time to add Bootstrap into the template so we can use its styling. + +Open `djbootstrap4/bootstrap4/templates/index.html` back up and +add or modify the following highlighted lines, which are very +similar to what you will find in the +[Bootstrap introduction guide](https://getbootstrap.com/docs/4.5/getting-started/introduction/): + +``` + + + +~~ +~~ +~~ +~~ bootstrap4 + + +

    Hello, world!

    + +~~ +~~ +~~ +~~ +~~ + + +``` + +The above new lines in the `` section add a couple of meta elements +that are important to Bootstrap's styling, and add the mandatory Bootstrap +stylesheet. + +We keep the same `

    ` header, which will automatically get the CSS +styling. Then there are 3 *optional* script elements that pull in +Bootstrap [JavaScript](/javascript.html) for more advanced features. +We are not using them in this tutorial because we just wanted to +quickly show how to use the CDN and with this in place you can see +in the +[Bootstrap content docs](https://getbootstrap.com/docs/4.5/content/reboot/) +what you want to add to the template next. + +Refresh the page at "http://localhost:8000" and you should see "Hello, world!" +change fonts. + + +Bootstrap-enhanced HTML page saying 'Hello, world!'. + +If you see that, it means everything works as expected. + + +## What now? +We just added Bootstrap via the CDN so we can use it in our Django template. +This was the absolute simplest way to add Bootstrap to a single Django +page and now there's a ton more you can do with it. + +Next, try out some of these other related [Django](/django.html) tutorials: + +* [More Bootstrap resources](/bootstrap-css.html) +* [How to Add Maps to Django Web App Projects with Mapbox](/blog/maps-django-web-applications-projects-mapbox.html) +* [Monitoring Django Projects with Rollbar](/blog/monitor-django-projects-web-apps-rollbar.html) + +Questions? Contact me via Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). I am also on GitHub with +the username [mattmakai](https://github.com/mattmakai). +If you see an issue or error in this tutorial, please +[fork the source repository on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/200705-bootstrap-4-django-template.markdown) +and submit a pull request with the fix. + diff --git a/content/posts/200719-track-daily-user-data-django-user-visit.markdown b/content/posts/200719-track-daily-user-data-django-user-visit.markdown new file mode 100644 index 000000000..c08b23529 --- /dev/null +++ b/content/posts/200719-track-daily-user-data-django-user-visit.markdown @@ -0,0 +1,389 @@ +title: Tracking Daily User Data in Django with django-user-visit +slug: track-daily-user-data-django-user-visit +meta: Learn how to easily track daily user visits and related data in Django projects with django-user-visit. +category: post +date: 2020-07-19 +modified: 2020-07-19 +newsletter: False +headerimage: /img/headers/django.jpg +headeralt: Logos for the implementations used in this blog post. Copyright their respective owners. + + +It can be tedious to figure out what data to track, create data models +and build [middleware](https://docs.djangoproject.com/en/stable/topics/http/middleware/) for your [Django](/django.html) project if you just want to +collect some basic information about clients that connect to your web application +. Fortunately, the library [django-user-visit](https://github.com/yunojuno/django-user-visit) +is a handy Django project that quickly handles all +of this complexity for you. In this tutorial, we'll learn +how to use django-user-visit in a new Django project +to add daily visit data tracking to Django projects. + +When we're done, we can view information like the following in the Django Admin: + +Django Admin with django-user-visit information + + + +## Project Requirements +Ensure you have Python 3 installed, because Python 2 reached its +end-of-life at the beginning of 2020 and is no longer supported. +Preferrably, you should have +[Python 3.7 or greater installed](https://www.python.org/downloads/) +in your [development environment](/development-environments.html). +This tutorial will also use: + +We will use the following dependencies to complete this +tutorial: + +* [Django](/django.html) [web framework](/web-frameworks.html), + [version 3.0.8](https://www.djangoproject.com/download/) +* [django-user-visit](https://github.com/yunojuno/django-user-visit), + [version 0.4](https://pypi.org/project/django-user-visit/) + +All code in this blog post is available open source under the MIT license +on GitHub under the +[track-daily-user-data-django-user-visit directory of the blog-code-examples repository](https://github.com/fullstackpython/blog-code-examples). +Use the source code as you desire for your own projects. + + +## Development environment set up +Change into the directory where you keep your Python +[virtual environments](/virtual-environments-virtualenvs-venvs.html). +Create a new virtualenv for this project using the following +command. + +Start the Django project by creating a new +[virtual environment](/virtual-environments-virtualenvs-venvs.html) +using the following command. I recommend using a separate directory +such as `~/venvs/` (the tilde is a shortcut for your user's `home` +directory) so that you always know where all your virtualenvs are +located. + +```bash +python3 -m venv ~/venvs/djuservisit +``` + +Activate the virtualenv with the `activate` shell script: + +```bash +source ~/venvs/djuservisit/bin/activate +``` + +After the above command is executed, the command prompt will +change so that the name of the virtualenv is prepended to the +original command prompt format, so if your prompt is simply +`$`, it will now look like the following: + +```bash +(djuservisit) $ +``` + +Remember, you have to activate your virtualenv in every new terminal +window where you want to use dependencies in the virtualenv. + +We can now install the [Django](https://pypi.org/project/Django/) +package into the activated but otherwise empty virtualenv. + +``` +pip install django==3.0.8 django-user-visit==0.4 +``` + +Look for output similar to the following to confirm the appropriate +packages were installed correctly from PyPI. + +``` +(djuservisit) $ pip install django==3.0.8 django-user-visit==0.4 +Collecting django==3.0.8 + Using cached https://files.pythonhosted.org/packages/ca/ab/5e004afa025a6fb640c6e983d4983e6507421ff01be224da79ab7de7a21f/Django-3.0.8-py3-none-any.whl +Collecting django-user-visit==0.4 + Downloading https://files.pythonhosted.org/packages/23/ef/d3ec22c3a897192e267389d6ee59ce1858f5ede262b078f93211aff110e7/django_user_visit-0.4-py3-none-any.whl +Collecting sqlparse>=0.2.2 (from django==3.0.8) + Using cached https://files.pythonhosted.org/packages/85/ee/6e821932f413a5c4b76be9c5936e313e4fc626b33f16e027866e1d60f588/sqlparse-0.3.1-py2.py3-none-any.whl +Collecting asgiref~=3.2 (from django==3.0.8) + Using cached https://files.pythonhosted.org/packages/d5/eb/64725b25f991010307fd18a9e0c1f0e6dff2f03622fc4bcbcdb2244f60d6/asgiref-3.2.10-py3-none-any.whl +Collecting pytz (from django==3.0.8) + Using cached https://files.pythonhosted.org/packages/4f/a4/879454d49688e2fad93e59d7d4efda580b783c745fd2ec2a3adf87b0808d/pytz-2020.1-py2.py3-none-any.whl +Collecting user-agents<3.0,>=2.1 (from django-user-visit==0.4) + Using cached https://files.pythonhosted.org/packages/1b/be/82e4d20a7716d8e5de98b948edcecff9bb237e6718c3831bd92794fe9821/user-agents-2.1.tar.gz +Collecting ua-parser>=0.9.0 (from user-agents<3.0,>=2.1->django-user-visit==0.4) + Using cached https://files.pythonhosted.org/packages/9d/22/4d16b08db329fd440eed366d35e4dd7195c9babb4ecac5218f28081522a2/ua_parser-0.10.0-py2.py3-none-any.whl +Installing collected packages: sqlparse, asgiref, pytz, django, ua-parser, user-agents, django-user-visit + Running setup.py install for user-agents ... done +Successfully installed asgiref-3.2.10 django-3.0.8 django-user-visit-0.4 pytz-2020.1 sqlparse-0.3.1 ua-parser-0.10.0 user-agents-2.1 + +``` + +Our dependencies are installed so we can now create our +project and start coding. + + +## Creating the application +We have everything we need to start building our application. + +We can use the [Django](/django.html) `django-admin` tool to create +the boilerplate code structure to get our project started. +Change into the directory where you develop your applications. For +example, I typically use `/Users/matt/devel/py/` for all of my +Python projects. Then run the following command to start a Django +project named `djuservisit`: + +``` +django-admin.py startproject djuservisit +``` + +Note that in this tutorial we are using the same name for both the +virtualenv and the Django project directory, but they can be +different names if you prefer that for organizing your own projects. + +The `django-admin` command creates a directory named `djuservisit` +along with several subdirectories that you should be familiar with +if you have previously worked with Django. + +Change directories into the new project. + +``` +cd djuservisit +``` + +Open `djuservisit/djuservisit/settings.py`. Add the `user_visits` +app and its middleware to `settings.py` by inserting the two +highlighted lines: + +```python +# djuservisit/djuservisit/settings.py +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +~~ 'user_visit', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +~~ 'user_visit.middleware.UserVisitMiddleware', +] +``` + +Make sure you change the default `DEBUG` and `SECRET_KEY` +values in `settings.py` before you deploy any code to production. Secure +your app properly with the information from the Django +[production deployment checklist](https://docs.djangoproject.com/en/stable/howto/deployment/checklist/) +so that you do not add your project to the list of hacked applications +on the web. + +Save and close `settings.py`. + +Create a [Django superuser](https://docs.djangoproject.com/en/stable/ref/django-admin/) +so you can access the Django Admin. Go to the base directory of this project +and use the `manage.py` file with the following command: + +``` +python manage.py createsuperuser +``` + +Follow the prompts and enter values for the username, email address and +password that you want your local Django superuser to have. Next, we'll +test out how this library works when a user visits a page created by +our Django web app. + + +## Testing django-user-visit +Let's test out our bare-bones application. Execute the development server +with the following command: + +```bash +python manage.py runserver +``` + +The Django development server should start up with no issues. + +``` +Watching for file changes with StatReloader +Performing system checks... + +System check identified no issues (0 silenced). +July 19, 2020 - 13:01:41 +Django version 3.0.8, using settings 'djuservisit.settings' +Starting development server at http://127.0.0.1:8000/ +Quit the server with CONTROL-C. +``` + +Open a web browser and go to "http://localhost:8000". + +Default Django page. + +That's the default page provided by Django in the absence of any other URLs +to serve at the root URL, but it works for our purposes. + +Go to the Django Admin by changing the URL in your browser to +"http://localhost:8000/admin". The Django Admin login page will appear. + +Django admin default login screen. + +Enter the username and password of the superuser you just created with +the `manage.py` command to log in. Next, you will see the Django admin +dashboard. + +Django admin dashboard. + +The "User visit log" has already been added to the Admin. Click on +the "User visits" link. + +django-user-visit list in the Django admin dashboard. + +The list of all users that have visited by day will show up. + +django-user-visit details page in the Django admin. + +Click on any of the visits to see more detailed data about the record, +just like you would with any Django Admin extension. + +That library was pretty easy to install for the information that it +aggregates for you. Next, let's take a closer look at the +[Django ORM](/django-orm.html) model that powers this library. + + +## Inspecting the django-user-visit model +We confirmed that django-user-visit is properly installed. Let's take a closer +look at the model the library provides to store the user data. + +Take a look at the source code for +[django-user-visit/user_visit/models.py](https://github.com/yunojuno/django-user-visit/blob/master/user_visit/models.py) +on GitHub. Below is an excerpt with the relevant lines of that source file. +I've highlighted a few lines that will be discussed below the code excerpt. + +```python +## ... source code abbreviated ... + +class UserVisit(models.Model): + """ + Record of a user visiting the site on a given day. + This is used for tracking and reporting - knowing the volume of visitors + to the site, and being able to report on someone's interaction with the site. + We record minimal info required to identify user sessions, plus changes in + IP and device. This is useful in identifying suspicious activity (multiple + logins from different locations). + Also helpful in identifying support issues (as getting useful browser data + out of users can be very difficult over live chat). + """ + +~~ user = models.ForeignKey( +~~ settings.AUTH_USER_MODEL, related_name="user_visits", on_delete=models.CASCADE +~~ ) + timestamp = models.DateTimeField( + help_text="The time at which the first visit of the day was recorded", + default=timezone.now, + ) + session_key = models.CharField(help_text="Django session identifier", max_length=40) + remote_addr = models.CharField( + help_text=( + "Client IP address (from X-Forwarded-For HTTP header, " + "or REMOTE_ADDR request property)" + ), + max_length=100, + blank=True, + ) +~~ ua_string = models.TextField( +~~ "User agent (raw)", help_text="Client User-Agent HTTP header", blank=True, +~~ ) + uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) + hash = models.CharField( + max_length=32, + help_text="MD5 hash generated from request properties", + unique=True, + ) + created_at = models.DateTimeField( + help_text="The time at which the database record was created (!=timestamp)", + auto_now_add=True, + ) + + objects = UserVisitManager() + + class Meta: + get_latest_by = "timestamp" + + def __str__(self) -> str: + return f"{self.user} visited the site on {self.timestamp}" + + def __repr__(self) -> str: + return f"" + + def save(self, *args: Any, **kwargs: Any) -> None: + """Set hash property and save object.""" +~~ self.hash = self.md5().hexdigest() + super().save(*args, **kwargs) + + @property + def user_agent(self) -> user_agents.parsers.UserAgent: + """Return UserAgent object from the raw user_agent string.""" + return user_agents.parsers.parse(self.ua_string) + + @property + def date(self) -> datetime.date: + """Extract the date of the visit from the timestamp.""" + return self.timestamp.date() + + # see https://github.com/python/typeshed/issues/2928 re. return type + def md5(self) -> hashlib._Hash: + """Generate MD5 hash used to identify duplicate visits.""" +~~ h = hashlib.md5(str(self.user.id).encode()) # noqa: S303 + h.update(self.date.isoformat().encode()) + h.update(self.session_key.encode()) + h.update(self.remote_addr.encode()) + h.update(self.ua_string.encode()) + return h + +``` + +A few things to note based on the highlighted above: + +* The `UserVisit` model matches up with the + [Django user model](https://docs.djangoproject.com/en/stable/ref/contrib/auth/) + using the `user = models.ForeignKey...` line +* The code uses the `save` function to ensure the some of the fields + are automatically populated, such as the `hash` property using the + `hashlib` module +* This library has a dependency on the + [user_agents library](https://pypi.org/project/user-agents/) to parse the + [User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) + of the browser the client is using + +Reading the source code for libraries like django-user-visit is helpful +not only to know what it is doing under the covers, but also to learn new +ways to code your own applications. + +Take a look at the [Django code examples](/django-code-examples.html) and +[Django extensions](/django-extensions-plug-ins-related-libraries.html) pages +to see more projects with good Python example code that you can learn from. + + +## Additional resources +We just finished building an app that tracks daily user visits with the +django-user-visit library. + +Next, try out some of these other related [Django](/django.html) tutorials: + +* [Quickly Use Bootstrap 4 in a Django Template with a CDN](/blog/bootstrap-4-django-template.html) +* [How to Add Maps to Django Web App Projects with Mapbox](/blog/maps-django-web-applications-projects-mapbox.html) +* [Monitoring Django Projects with Rollbar](/blog/monitor-django-projects-web-apps-rollbar.html) + +Questions? Let me know via +[a GitHub issue ticket on the Full Stack Python repository](https://github.com/mattmakai/fullstackpython.com/issues), +on Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). +If you see an issue or error in this tutorial, please +[fork the source repository on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/200719-track-daily-user-data-django-user-visit.markdown) +and submit a pull request with the fix. + diff --git a/content/posts/200809-transcribe-recordings-speech-text-assemblyai.markdown b/content/posts/200809-transcribe-recordings-speech-text-assemblyai.markdown new file mode 100644 index 000000000..4a5027fbe --- /dev/null +++ b/content/posts/200809-transcribe-recordings-speech-text-assemblyai.markdown @@ -0,0 +1,483 @@ +title: How to Transcribe Speech Recordings into Text with Python +slug: transcribe-recordings-speech-text-assemblyai +meta: Learn to transcribe speech in recordings like MP3s into text with Python and AssemblyAI's API. +category: post +date: 2020-08-09 +modified: 2021-09-13 +newsletter: False +headerimage: /img/headers/python-assemblyai.jpg +headeralt: Logos for the implementations used in this blog post. Copyright their respective owners. + + +When you have a recording where one or more people are talking, it's useful +to have a highly accurate and automated way to extract the spoken words into +text. Once you have the text, you can use it for further analysis or +as an accessibility feature. + +In this tutorial, we'll use a high accuracy speech-to-text web application +programming interface called [AssemblyAI](https://www.assemblyai.com/) to +extract text from an MP3 recording (many other formats are supported as well). + +With the code from this tutorial, you will be able to take an audio file +that contains speech +[such as this example one I recorded](https://www.fullstackpython.com/audio/fsp-object-relational-mappers.mp3) +and output a highly accurate text transcription like this: + +``` +An object relational mapper is a code library that automates the transfer of +data stored in relational, databases into objects that are more commonly used +in application code or EMS are useful because they provide a high level +abstraction upon a relational database that allows developers to write Python +code instead of sequel to create read update and delete, data and schemas in +their database. Developers can use the programming language. They are +comfortable with to work with a database instead of writing SQL... + +(the text goes on from here but I abbreviated it at this point) +``` + +## Tutorial requirements +Throughout this tutorial we are going to use the following dependencies, +which we will install in just a moment. Make sure you also have Python 3, +[preferably 3.6 or newer installed](https://www.python.org/downloads/), +in your environment: + +We will use the following dependencies to complete this +tutorial: + +* [requests](https://requests.readthedocs.io/) + [version 2.24.0](https://pypi.org/project/requests/) to make HTTP requests to + the [AssemblyAI](https://www.assemblyai.com/) speech-to-text + [API](/application-programming-interfaces.html) +* An [AssemblyAI](https://www.assemblyai.com/) account, + which you can sign up for a + [free API access key here](https://app.assemblyai.com/login/) + +All code in this blog post is available open source under the MIT license +on GitHub under the +[transcribe-speech-text-script directory of the blog-code-examples repository](https://github.com/fullstackpython/blog-code-examples). +Use the source code as you desire for your own projects. + + +## Setting up the development environment +Change into the directory where you keep your Python +[virtual environments](/virtual-environments-virtualenvs-venvs.html). +I keep mine in a subdirectory named `venvs` within my user's home +directory. Create a new virtualenv for this project using the following +command. + +```bash +python3 -m venv ~/venvs/pytranscribe +``` + +Activate the virtualenv with the `activate` shell script: + +```bash +source ~/venvs/pytranscribe/bin/activate +``` + +After the above command is executed, the command prompt will +change so that the name of the virtualenv is prepended to the +original command prompt format, so if your prompt is simply +`$`, it will now look like the following: + +```bash +(pytranscribe) $ +``` + +Remember, you have to activate your virtualenv in every new terminal +window where you want to use dependencies in the virtualenv. + +We can now install the `requests` package into the activated +but otherwise empty virtualenv. + +``` +pip install requests==2.24.0 +``` + +Look for output similar to the following to confirm the appropriate +packages were installed correctly from PyPI. + +``` +(pytranscribe) $ pip install requests==2.24.0 +Collecting requests==2.24.0 + Using cached https://files.pythonhosted.org/packages/45/1e/0c169c6a5381e241ba7404532c16a21d86ab872c9bed8bdcd4c423954103/requests-2.24.0-py2.py3-none-any.whl +Collecting certifi>=2017.4.17 (from requests==2.24.0) + Using cached https://files.pythonhosted.org/packages/5e/c4/6c4fe722df5343c33226f0b4e0bb042e4dc13483228b4718baf286f86d87/certifi-2020.6.20-py2.py3-none-any.whl +Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests==2.24.0) + Using cached https://files.pythonhosted.org/packages/9f/f0/a391d1463ebb1b233795cabfc0ef38d3db4442339de68f847026199e69d7/urllib3-1.25.10-py2.py3-none-any.whl +Collecting chardet<4,>=3.0.2 (from requests==2.24.0) + Using cached https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl +Collecting idna<3,>=2.5 (from requests==2.24.0) + Using cached https://files.pythonhosted.org/packages/a2/38/928ddce2273eaa564f6f50de919327bf3a00f091b5baba8dfa9460f3a8a8/idna-2.10-py2.py3-none-any.whl +Installing collected packages: certifi, urllib3, chardet, idna, requests +Successfully installed certifi-2020.6.20 chardet-3.0.4 idna-2.10 requests-2.24.0 urllib3-1.25.10 +``` + +We have all of our required dependencies installed so we can get started +coding the application. + + +## Uploading, initiating and transcribing audio +We have everything we need to start building our application that +will transcribe audio into text. We're going to build this +application in three files: + +1. [upload_audio_file.py](https://github.com/fullstackpython/blog-code-examples/blob/master/transcribe-speech-text-script/upload_audio_file.py): + uploads your audio file to a secure place on AssemblyAI's service so + it can be access for processing. If your audio file is already accessible + with a public URL, you don't need to do this step, you can just follow + [this quickstart](https://docs.assemblyai.com/overview/getting-started) +1. [initiate_transcription.py](https://github.com/fullstackpython/blog-code-examples/blob/master/transcribe-speech-text-script/initiate_transcription.py): + tells the API which file to transcribe and to start immediately +1. [get_transcription.py](https://github.com/fullstackpython/blog-code-examples/blob/master/transcribe-speech-text-script/get_transcription.py): + prints the status of the transcription if it is still processing, or + displays the results of the transcription when the process is complete + +Create a new directory named `pytranscribe` to store these files as +we write them. Then change into the new project directory. + +``` +mkdir pytranscribe +cd pytranscribe +``` + +We also need to export our AssemblyAI API key as an environment variable. +[Sign up for an AssemblyAI account](https://app.assemblyai.com/login/) +and log in to the +[AssemblyAI dashboard](https://app.assemblyai.com/dashboard/), then +copy "Your API token" as shown in this screenshot: + +AssemblyAI dashboard. + + +```bash +export ASSEMBLYAI_KEY=your-api-key-here +``` + +Note that you must use the `export` command in every command line window +that you want this key to be accessible. The scripts we are writing will +not be able to access the API if you do not have the token exported as +`ASSEMBLYAI_KEY` in the environment you are running the script. + +Now that we have our project directory created and the API key set as an +environment variable, let's move on to writing the code for the first file +that will upload audio files to the AssemblyAI service. + + +## Uploading the audio file for transcription +Create a new file named `upload_audio_file.py` and place the following +code in it: + +```python +import argparse +import os +import requests + + +API_URL = "https://api.assemblyai.com/v2/" + + +def upload_file_to_api(filename): + """Checks for a valid file and then uploads it to AssemblyAI + so it can be saved to a secure URL that only that service can access. + When the upload is complete we can then initiate the transcription + API call. + Returns the API JSON if successful, or None if file does not exist. + """ + if not os.path.exists(filename): + return None + + def read_file(filename, chunk_size=5242880): + with open(filename, 'rb') as _file: + while True: + data = _file.read(chunk_size) + if not data: + break + yield data + + headers = {'authorization': os.getenv("ASSEMBLYAI_KEY")} + response = requests.post("".join([API_URL, "upload"]), headers=headers, + data=read_file(filename)) + return response.json() + +``` + +The above code imports the `argparse`, `os` and `requests` packages +so that we can use them in this script. The `API_URL` is a constant +that has the base URL of the AssemblyAI service. We define the +`upload_file_to_api` function with a single argument, `filename` +that should be a string with the absolute path to a file and its +filename. + +Within the function, we check that the file exists, then use Request's +[chunked transfer encoding](https://requests.readthedocs.io/en/master/user/advanced/#chunk-encoded-requests) +to stream large files to the AssemblyAI API. + +The `os` module's `getenv` function reads the API that was set on the +command line using the `export` command with the `getenv`. Make sure +that you use that `export` command in the terminal where you are +running this script otherwise that `ASSEMBLYAI_KEY` value will be +blank. When in doubt, use `echo $ASSEMBLY_AI` to see if the value +matches your API key. + +To use the `upload_file_to_api` function, append the following lines of +code in the `upload_audio_file.py` file so that we can properly +execute this code as a script called with the `python` command: + +```python + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("filename") + args = parser.parse_args() + upload_filename = args.filename + response_json = upload_file_to_api(upload_filename) + if not response_json: + print("file does not exist") + else: + print("File uploaded to URL: {}".format(response_json['upload_url'])) +``` + +The code above creates an `ArgumentParser` object that allows the +application to obtain a single argument from the command line +to specify the file we want to access, read and upload to the +AssmeblyAI service. + +If the file does not exist, the script will print a message that +the file couldn't be found. In the happy path where we do find the +correct file at that path, then the file is uploaded using +the code in `upload_file_to_api` function. + +Execute the completed `upload_audio_file.py` script by running it on +the command line with the `python` command. Replace `FULL_PATH_TO_FILE` +with an absolute path to the file you want to upload, such as +`/Users/matt/devel/audio.mp3`. + +```bash +python upload_audio_file.py FULL_PATH_TO_FILE +``` + +Assuming the file is found at the location that you specified, when the +script finishes uploading the file, it will print a message like this one +with a unique URL: + +``` +File uploaded to URL: https://cdn.assemblyai.com/upload/463ce27f-0922-4ea9-9ce4-3353d84b5638 +``` + +This URL is not public, it can only be used by the AssemblyAI service, so no +one else will be able to access your file and its contents except for you +and their transcription API. + +The part that is important is the last section of the URL, in this example +it is `463ce27f-0922-4ea9-9ce4-3353d84b5638`. Save that unique identifier +because we need to pass it into the next script that initiates the +transcription service. + + +## Initiate transcription +Next, we'll write some code to kick off the transcription. Create a +new file named `initiate_transcription.py`. Add the following +code to the new file. + +```python +import argparse +import os +import requests + + +API_URL = "https://api.assemblyai.com/v2/" +CDN_URL = "https://cdn.assemblyai.com/" + + +def initiate_transcription(file_id): + """Sends a request to the API to transcribe a specific + file that was previously uploaded to the API. This will + not immediately return the transcription because it takes + a moment for the service to analyze and perform the + transcription, so there is a different function to retrieve + the results. + """ + endpoint = "".join([API_URL, "transcript"]) + json = {"audio_url": "".join([CDN_URL, "upload/{}".format(file_id)])} + headers = { + "authorization": os.getenv("ASSEMBLYAI_KEY"), + "content-type": "application/json" + } + response = requests.post(endpoint, json=json, headers=headers) + return response.json() +``` + +We have the same imports as the previous script and we've added a +new constant, `CDN_URL` that matches the separate URL where AssemblyAI +stores the uploaded audio files. + +The `initiate_transcription` function essentially just sets up +a single HTTP request to the AssemblyAI API to start the transcription +process on the audio file at the specific URL passed in. This is why +passing in the `file_id` is important: that completes the URL of the +audio file that we are telling AssemblyAI to retrieve. + +Finish the file by appending this code so that it can be easily +invoked from the command line with arguments. + +```python + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("file_id") + args = parser.parse_args() + file_id = args.file_id + response_json = initiate_transcription(file_id) + print(response_json) +``` + +Start the script by running the `python` command on the +`initiate_transcription` file and pass in the unique file identifier +you saved from the previous step. + +```bash +# the FILE_IDENTIFIER is returned in the previous step and will +# look something like this: 463ce27f-0922-4ea9-9ce4-3353d84b5638 +python initiate_transcription.py FILE_IDENTIFIER +``` + +The API will send back a JSON response that this script prints to +the command line. + +```bash +{'audio_end_at': None, 'acoustic_model': 'assemblyai_default', 'text': None, + 'audio_url': 'https://cdn.assemblyai.com/upload/463ce27f-0922-4ea9-9ce4-3353d84b5638', + 'speed_boost': False, 'language_model': 'assemblyai_default', 'redact_pii': False, + 'confidence': None, 'webhook_status_code': None, + 'id': 'gkuu2krb1-8c7f-4fe3-bb69-6b14a2cac067', 'status': 'queued', 'boost_param': None, + 'words': None, 'format_text': True, 'webhook_url': None, 'punctuate': True, + 'utterances': None, 'audio_duration': None, 'auto_highlights': False, + 'word_boost': [], 'dual_channel': None, 'audio_start_from': None} +``` + +Take note of the value of the `id` key in the JSON response. This is the +transcription identifier we need to use to retrieve the transcription result. +In this example, it is `gkuu2krb1-8c7f-4fe3-bb69-6b14a2cac067`. Copy the +transcription identifier in your own response because we will need it to +check when the transcription process has completed in the next step. + + +## Retrieving the transcription result +We have uploaded and begun the transcription process, so let's get the +result as soon as it is ready. + +How long it takes to get the results back can depend on the size of the file, +so this next script will send an HTTP request to the API and report back +the status of the transcription, or print the output if it's complete. + +Create a third Python file named `get_transcription.py` and put the following +code into it. + +```python +import argparse +import os +import requests + + +API_URL = "https://api.assemblyai.com/v2/" + + +def get_transcription(transcription_id): + """Requests the transcription from the API and returns the JSON + response.""" + endpoint = "".join([API_URL, "transcript/{}".format(transcription_id)]) + headers = {"authorization": os.getenv('ASSEMBLYAI_KEY')} + response = requests.get(endpoint, headers=headers) + return response.json() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("transcription_id") + args = parser.parse_args() + transcription_id = args.transcription_id + response_json = get_transcription(transcription_id) + if response_json['status'] == "completed": + for word in response_json['words']: + print(word['text'], end=" ") + else: + print("current status of transcription request: {}".format( + response_json['status'])) +``` + +The code above has the same imports as the other scripts. In this +new `get_transcription` function, we simply call the AssemblyAI API +with our API key and the *transcription identifier* from the previous +step (not the file identifier). We retrieve the JSON response and +return it. + +In the main function we handle the transcription identifier that +is passed in as a command line argument and pass it into the +`get_transcription` function. If the response JSON from the +`get_transcription` function contains a `completed` status then we +print the results of the transcription. Otherwise, print the +current status which is either `queued` or `processing` before +it is `completed`. + +Call the script using the command line and the transcription identifier +from the previous section: + +```bash +python get_transcription.py TRANSCRIPTION_ID +``` + +If the service has not yet started working on the transcript then it +will return `queued` like this: + +```bash +current status of transcription request: queued +``` + +When the service is currently working on the audio file it will +return `processing`: + +```bash +current status of transcription request: processing +``` + +When the process is completed, our script will return the text of +the transcription, like you see here: + +```bash +An object relational mapper is a code library that automates the transfer of +data stored in relational, databases into objects that are more commonly used +in application code or EMS are useful because they provide a high level + +...(output abbreviated) +``` + +That's it, we've got our transcription! + +You may be wondering what to do if the accuracy isn't where you need +it to be for your situation. That is where +[boosting accuracy for keywords or phrases](https://docs.assemblyai.com/guides/boosting-accuracy-for-keywords-or-phrases) +comes in. You can use either of those two methods to boost the accuracy +of your recordings to an acceptable level for your situation. + + +## What's next? +We just finished writing some scripts that call the AssemblyAI API to +transcribe recordings with speech into text output. + +Next, take a look at some of their more advanced documentation that goes +beyond the basics in this tutorial: + +* [Supported file formats](https://docs.assemblyai.com/faqs/supported-file-formats) +* [Transcribing dual channel/stereo recordings](https://docs.assemblyai.com/guides/transcribing-dual-channel-stereo-recordings) +* [Getting speaker labels (speaker diarization)](https://docs.assemblyai.com/guides/getting-speaker-labels-speaker-diarization) + +Questions? Let me know via an issue ticket on +[the Full Stack Python repository](https://github.com/mattmakai/fullstackpython.com/issues), +on Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). +See something wrong with this post? Fork +[this page's source on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/200809-transcribe-recordings-speech-text-assemblyai.markdown) +and submit a pull request. + diff --git a/content/posts/200823-sentry-handle-exceptions-django-projects.markdown b/content/posts/200823-sentry-handle-exceptions-django-projects.markdown new file mode 100644 index 000000000..d3ef987b8 --- /dev/null +++ b/content/posts/200823-sentry-handle-exceptions-django-projects.markdown @@ -0,0 +1,454 @@ +title: Using Sentry to Handle Python Exceptions in Django Projects +slug: sentry-handle-exceptions-django-projects +meta: Learn to handle Python exceptions in your Django projects with the hosted Sentry service. +category: post +date: 2020-08-23 +modified: 2020-08-23 +newsletter: False +headerimage: /img/headers/django-sentry.jpg +headeralt: Logos for the implementations used in this blog post. Copyright their respective owners. + + +Web applications built in [Django](/django.html) can become sprawlingly complex over time, which is one reason why centralized error handling is important. This tutorial will guide you through adding a free, basic Sentry configuration to a new Django project. + +When we're done, you will be able to view centralized error reports in the Sentry dashboard like you see in this screenshot: + +Sentry dashboard with caught Django exceptions. + + + +## Tutorial Requirements +Throughout this tutorial we are going to use the following dependencies, +which we will install in just a moment. Make sure you also have Python 3, +[preferrably 3.7 or newer installed](https://www.python.org/downloads/), +in your environment: + +We will use the following dependencies to complete this +tutorial: + +* [Django](/django.html) [web framework](/web-frameworks.html), + [version 3.1](https://www.djangoproject.com/download/) +* [sentry-sdk](https://sentry.io/for/python/), + [version 0.16.5](https://pypi.org/project/sentry-sdk/) + +All code in this blog post is available open source under the MIT license +on GitHub under the +[sentry-handle-exceptions-django-projects directory of the blog-code-examples repository](https://github.com/fullstackpython/blog-code-examples). +Use the source code as you desire for your own projects. + + +## Development environment configuration +Change into the directory where you keep your Python +[virtual environments](/virtual-environments-virtualenvs-venvs.html). +Create a new virtualenv for this project using the following +command. + +Start the Django project by creating a new +[virtual environment](/virtual-environments-virtualenvs-venvs.html) +using the following command. I recommend using a separate directory +such as `~/venvs/` (the tilde is a shortcut for your user's `home` +directory) so that you always know where all your virtualenvs are +located. + +```bash +python3 -m venv ~/venvs/djsentry +``` + +Activate the virtualenv with the `activate` shell script: + +```bash +source ~/venvs/djsentry/bin/activate +``` + +After the above command is executed, the command prompt will +change so that the name of the virtualenv is prepended to the +original command prompt format, so if your prompt is simply +`$`, it will now look like the following: + +```bash +(djsentry) $ +``` + +Remember, you have to activate your virtualenv in every new terminal +window where you want to use dependencies in the virtualenv. + +We can now install the [Django](https://pypi.org/project/Django/) +package into the activated but otherwise empty virtualenv. + +``` +pip install django==3.1 sentry-sdk==0.16.5 +``` + +Look for output similar to the following to confirm the appropriate +packages were installed correctly from PyPI. + +``` +(djsentry) $ pip install django==3.1 sentry-sdk==0.16.5 +Collecting django + Downloading https://files.pythonhosted.org/packages/2b/5a/4bd5624546912082a1bd2709d0edc0685f5c7827a278d806a20cf6adea28/Django-3.1-py3-none-any.whl (7.8MB) + 100% |████████████████████████████████| 7.8MB 6.3MB/s +Collecting sentry-sdk + Downloading https://files.pythonhosted.org/packages/f4/4c/49f899856e3a83e02bc88f2c4945aa0bda4f56b804baa9f71e6664a574a2/sentry_sdk-0.16.5-py2.py3-none-any.whl (113kB) + 100% |████████████████████████████████| 122kB 33.7MB/s +Collecting asgiref~=3.2.10 (from django) + Using cached https://files.pythonhosted.org/packages/d5/eb/64725b25f991010307fd18a9e0c1f0e6dff2f03622fc4bcbcdb2244f60d6/asgiref-3.2.10-py3-none-any.whl +Collecting sqlparse>=0.2.2 (from django) + Using cached https://files.pythonhosted.org/packages/85/ee/6e821932f413a5c4b76be9c5936e313e4fc626b33f16e027866e1d60f588/sqlparse-0.3.1-py2.py3-none-any.whl +Collecting pytz (from django) + Using cached https://files.pythonhosted.org/packages/4f/a4/879454d49688e2fad93e59d7d4efda580b783c745fd2ec2a3adf87b0808d/pytz-2020.1-py2.py3-none-any.whl +Collecting urllib3>=1.10.0 (from sentry-sdk) + Using cached https://files.pythonhosted.org/packages/9f/f0/a391d1463ebb1b233795cabfc0ef38d3db4442339de68f847026199e69d7/urllib3-1.25.10-py2.py3-none-any.whl +Collecting certifi (from sentry-sdk) + Using cached https://files.pythonhosted.org/packages/5e/c4/6c4fe722df5343c33226f0b4e0bb042e4dc13483228b4718baf286f86d87/certifi-2020.6.20-py2.py3-none-any.whl +Installing collected packages: asgiref, sqlparse, pytz, django, urllib3, certifi, sentry-sdk +Successfully installed asgiref-3.2.10 certifi-2020.6.20 django-3.1 pytz-2020.1 sentry-sdk-0.16.5 sqlparse-0.3.1 urllib3-1.25.10 + +``` + +We can get started coding the application now that we have all of our +required dependencies installed. + + +## Coding the initial application +We have everything we need to start building our application. + +We can use the [Django](/django.html) `django-admin` tool to create +the boilerplate code structure to get our project started. +Change into the directory where you develop your applications. For +example, I typically use `/Users/matt/devel/py/` for all of my +Python projects. Then run the following command to start a Django +project named `djsentry`: + +``` +django-admin.py startproject djsentry +``` + +Note that in this tutorial we are using the same name for both the +virtualenv and the Django project directory, but they can be +different names if you prefer that for organizing your own projects. + +The `django-admin` command creates a directory named `djsentry` +along with several subdirectories that you should be familiar with +if you have previously worked with Django. + +Change directories into the new project. + +``` +cd djsentry +``` + +Create a new Django app within `djsentry`. + +``` +python manage.py startapp errors +``` + +Django will generate a new folder named `errors` for the project. +We should update the URLs so the app is accessible before we write +our `views.py` code. + +Open `djsentry/djsentry/urls.py`. Add the highlighted +lines so that URL resolver will check the `errors` app +for additional routes to match with URLs that are requested of +this Django application. + +```python +# djsentry/djsentry/urls.py +~~from django.conf.urls import include +from django.contrib import admin +from django.urls import path + + +urlpatterns = [ +~~ path('', include('errors.urls')), + path('admin/', admin.site.urls), +] +``` + +Save `djsentry/djsentry/urls.py` and open +`djsentry/djsentry/settings.py`. +Add the `errors` app to `settings.py` by inserting +the highlighted line: + +```python +# djsentry/djsentry/settings.py +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +~~ 'errors', +] +``` + +Make sure you change the default `DEBUG` and `SECRET_KEY` +values in `settings.py` before you deploy any code to production. Secure +your app properly with the information from the Django +[production deployment checklist](https://docs.djangoproject.com/en/stable/howto/deployment/checklist/) +so that you do not add your project to the list of hacked applications +on the web. + +Save and close `settings.py`. + +Next change into the `djsentry/errors` directory. Create +a new file named `urls.py` to contain routes for the `errors` app. + +Add all of these lines to the empty `djsentry/errors/urls.py` +file. + +```python +# djsentry/errors/urls.py +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.errors_index, name="index"), +] +``` + +Save `djsentry/errors/urls.py`. Open +`djsentry/errors/views.py` to add the +following two highlighted lines. You can keep the boilerplate comment +"# Create your views here." or delete like I usually do. + +``` +# djsentry/errors/views.py +from django.shortcuts import render + + +~~def errors_index(request): +~~ return render(request, 'index.html', {}) +``` + + +Next, create a directory for your template files named `templates` under +the `djmaps/maps` app directory. + +``` +mkdir templates +``` + +Create a new file named `index.html` within +`djsentry/errors/templates` that contains the +following [Django template language](/django-templates.html) markup. + +``` + + + + First step for errors + + +

    Hello, world!

    + + +``` + +We can test out this static page to make sure all of our code is +correct before we start adding the meat of the functionality to +the project. Change into the base directory of your Django project +where the `manage.py` file is located. Execute the development +server with the following command: + +```bash +python manage.py runserver +``` + +The Django development server should start up with no issues other than +an unapplied migrations warning. + +``` +Watching for file changes with StatReloader +Performing system checks... + +System check identified no issues (0 silenced). + +You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. +Run 'python manage.py migrate' to apply them. +August 15, 2020 - 17:26:57 +Django version 3.1, using settings 'djsentry.settings' +Starting development server at http://127.0.0.1:8000/ +Quit the server with CONTROL-C. + +``` + +Open a web browser and go to `localhost:8000`. + +Plain old HTML page saying 'Hello, world!'. + +Our code works, but it sure does not do much yet. Let's add +sentry-sdk so we can understand how it works. + + +## Adding Sentry and the sentry-sdk library +We can now add Sentry and test it with a bunch of errors to make sure it +is working properly. + +Sentry can either be [self-hosted](https://github.com/getsentry/onpremise) or +used as a cloud service through [Sentry.io](https://sentry.io). In this +tutorial we will use the cloud hosted version because it's faster than +setting up your own server as well as free for smaller projects. + +Go to [Sentry.io's homepage](https://sentry.io). + +Sentry.io homepage where you can sign up for a free account. + +Sign into your account or sign up for a new free account. You will be at +the main account dashboard after logging in or completing the Sentry sign +up process. + +There are no errors logged on our account dashboard yet, which is as +expected because we have not yet connected our account to our Django +project. + +Blank Sentry account dashboard. + +Create a new Sentry Project just for this application by clicking +"Projects" in the left sidebar to go to the Projects page. + +Button to create a new Sentry project. + +On the Projects page, click the "Create Project" button in the top right +corner of the page. + +Create a new Sentry project. + +You can either choose "Django" or select "Python". I usually just choose +"Python" if I do not yet know what framework I'll be using to build my +application. Next, give your new Project a name and then press the "Create +Project" button. Our new project is ready to integrate with our Python code. + +We need the unique identifier for our account and project to authorize our +Python code to send errors to this Sentry instance. The easiest way to get +what we need is to go to the +[Python+Django documentation page](https://docs.sentry.io/platforms/python/django/) +and read how to configure the SDK. + +The Sentry docs show you exactly what you need to export to connect to your account. + +Copy the string parameter for the `init` method and set it +[as an environment variable](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html) +rather than having it exposed in your project's code. + +```bash +export SENTRY_DSN='https://yourkeygoeshere.ingest.sentry.io/project-number' +``` + +**Make sure to replace "yourkeygoeshere" with your own unique identifier +and "project-number" with the ID that matches the project you just +created.** + +Check that the `SENTRY_DSN` is set properly in your shell using the `echo` +command: + +```bash +echo $SENTRY_DSN +``` + +Next, update `settings.py` with the following highlighted new lines: + +```python +# settings.py +~~import os +~~import sentry_sdk + +from pathlib import Path +~~from sentry_sdk.integrations.django import DjangoIntegration + + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve(strict=True).parent.parent +``` + +At the bottom of the file after the line with `STATIC_URL`, add the +Sentry configuration: + +```python +STATIC_URL = '/static/' + +~~sentry_sdk.init( +~~ dsn=os.getenv('SENTRY_DSN'), +~~ integrations=[DjangoIntegration()], + +~~ # If you wish to associate users to errors (assuming you are using +~~ # django.contrib.auth) you may enable sending PII data. +~~ send_default_pii=True +~~) +``` + +Now that we have the configuration in place we can deliberately make some +errors happen to test the connection to Sentry's service. + + +## Testing Sentry's error catching +We'll change some of the existing code to deliberately throw exceptions +to make sure everything is working properly. + +Start by opening `errors/views.py` and updating it with one new +highlighted line that will automatically throw a generic Exception +when this function is called. + +```python +# djsentry/errors/views.py +from django.shortcuts import render + + +def errors_index(request): +~~ raise Exception('testing exception') + return render(request, 'index.html', {}) +``` + +Go to `localhost:8000` in your browser and you will immediately get this +exception page when running the development server: + +Django development mode debug page when the Exception is raised. + +We can also try out code that does not simply raise an exception but instead +will definitely create one when executed, like this division by zero +operation: + +```python +# djsentry/errors/views.py +from django.shortcuts import render + + +def errors_index(request): +~~ division_by_zero = 1 / 0 + return render(request, 'index.html', {}) +``` + +Django development mode debug page when the Exception occurs. + +If those exceptions both appear in the Sentry dashboard like this, you're all +set: + +Sentry dashboard with the exceptions that just occurred.. + +The above exceptions were just a couple of generic ways to test that everything +is working to send error information to Sentry. This configuration will +also handle the +[many other Django exceptions](https://docs.djangoproject.com/en/stable/ref/exceptions/) +you are likely to see when building the rest of your Django project. + + +## Additional resources +We just finished building a Django project that uses Sentry for +centralized error handling. + +Next, try out some of these other related [Django](/django.html) tutorials: + +* [Tracking Daily User Data in Django with django-user-visit](/blog/track-daily-user-data-django-user-visit.html) +* [Quickly Use Bootstrap 4 in a Django Template with a CDN](/blog/bootstrap-4-django-template.html) +* [How to Add Maps to Django Web App Projects with Mapbox](/blog/maps-django-web-applications-projects-mapbox.html) + +If you have questions or comments about this tutorial, please contact me +via Twitter [@fullstackpython](https://twitter.com/fullstackpython), or +on GitHub [@mattmakai](https://github.com/mattmakai). +See something wrong with this post? Fork +[this page's source on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/200823-sentry-handle-exceptions-django-projects.markdown) +and submit a pull request. + diff --git a/content/posts/201009-accurate-twilio-voice-call-recording-transcriptions-assemblyai.markdown b/content/posts/201009-accurate-twilio-voice-call-recording-transcriptions-assemblyai.markdown new file mode 100644 index 000000000..a041498f9 --- /dev/null +++ b/content/posts/201009-accurate-twilio-voice-call-recording-transcriptions-assemblyai.markdown @@ -0,0 +1,569 @@ +title: Higher Accuracy Twilio Voice Transcriptions with Python and Flask +slug: accurate-twilio-voice-call-recording-transcriptions-assemblyai +meta: Use AssemblyAI's speech-to-text service to improve recording transcription accuracy for Twilio Programmable Voice phone calls. +category: post +date: 2020-10-10 +modified: 2020-10-10 +newsletter: False +headerimage: /img/headers/python-assemblyai.jpg +headeralt: Logos for the implementations used in this blog post. Copyright their respective owners. + + +[Twilio's Programmable Voice API](https://www.twilio.com/docs/voice) +is commonly used to initiate and receive phone calls, but the transcription +accuracy for [recordings](https://www.twilio.com/docs/voice/api/recording) +often leaves a lot to be desired. In this tutorial, we'll see how to connect an +outbound phone call powered by the Twilio Voice API with +[AssemblyAI's deep learning transcription API](https://docs.assemblyai.com/overview/getting-started) +to get significantly more accurate speech-to-text output. + + +## Required Tools for this Application +Ensure you have Python 3 installed, because Python 2 reached its +end-of-life at the beginning of 2020 and is no longer supported. +Preferrably, you should have +[Python 3.6 or newer installed](https://www.python.org/downloads/) +in your [development environment](/development-environments.html). +This tutorial will also use: + +We will use the following dependencies to complete this +tutorial: + +* [requests](https://requests.readthedocs.io/), version + [2.24.0](https://pypi.org/project/requests/), for accessing the + [AssemblyAI transcription API](https://docs.assemblyai.com/overview/getting-started) +* [Flask](https://flask.palletsprojects.com/en/1.1.x/), version + [1.1.2](https://pypi.org/project/Flask/1.1.2/), to respond to Twilio's + webhooks +* A [Twilio account](https://www.twilio.com/referral/w9pugq), of which a + free trial version is good enough to test this tutorial +* [Twilio Python helper library](https://pypi.org/project/twilio/), + version [6.45.4](https://pypi.org/project/twilio/6.45.4/) or newer, + for interacting with the [REST API](https://www.twilio.com/docs/usage/api) +* An [AssemblyAI](https://www.assemblyai.com/) account, which you can sign + up for a [free key API access key here](https://app.assemblyai.com/login/) +* [Ngrok](https://ngrok.com/) if you need a localhost tunnel to expose + a public URL that webhooks can send a POST request to + +All code in this blog post is available open source under the MIT license +on GitHub under the +[accurate-twilio-voice-call-recording-transcriptions-assemblyai directory of the blog-code-examples repository](https://github.com/fullstackpython/blog-code-examples). +Use the source code as you desire for your own projects. + + +## Configuring our development environment +Change into the directory where you keep your Python +[virtual environments](/virtual-environments-virtualenvs-venvs.html). +Create a new virtualenv for this project using the following +command. + +Start this Python project by creating a new +[virtual environment](/virtual-environments-virtualenvs-venvs.html) +using the following command. I recommend using a separate directory +such as `~/venvs/` (the tilde is a shortcut for your user's `home` +directory) so that you always know where all your virtualenvs are +located. + +```bash +python3 -m venv ~/venvs/record-transcribe +``` + +Activate the virtualenv with the `activate` shell script: + +```bash +source ~/venvs/record-transcribe/bin/activate +``` + +After the above command is executed, the command prompt will +change so that the name of the virtualenv is prepended to the +original command prompt format, so if your prompt is simply +`$`, it will now look like the following: + +```bash +(record-transcribe) $ +``` + +Remember, you have to activate your virtualenv in every new terminal +window where you want to use dependencies in the virtualenv. + +We can now install the required packages +package into the activated but otherwise empty virtualenv. + +``` +pip install Flask==1.1.2 requests==2.24.0 twilio==6.45.4 +``` + +Look for output similar to the following to confirm the appropriate +packages were installed correctly from PyPI. + +``` +(recordtranscribe) $ pip install Flask==1.1.2 requests==2.24.0 twilio=6.45.4 +Collecting Flask + Using cached https://files.pythonhosted.org/packages/f2/28/2a03252dfb9ebf377f40fba6a7841b47083260bf8bd8e737b0c6952df83f/Flask-1.1.2-py2.py3-none-any.whl +Collecting requests + Using cached https://files.pythonhosted.org/packages/45/1e/0c169c6a5381e241ba7404532c16a21d86ab872c9bed8bdcd4c423954103/requests-2.24.0-py2.py3-none-any.whl +Collecting twilio + Using cached https://files.pythonhosted.org/packages/d0/4e/7c377eb1a1d57f011dc1bee2fee77cf1e9a08407b8d44ea25a187a30c78d/twilio-6.45.4.tar.gz +Collecting Werkzeug>=0.15 (from Flask) + Using cached https://files.pythonhosted.org/packages/cc/94/5f7079a0e00bd6863ef8f1da638721e9da21e5bacee597595b318f71d62e/Werkzeug-1.0.1-py2.py3-none-any.whl +Collecting itsdangerous>=0.24 (from Flask) + Using cached https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl +Collecting click>=5.1 (from Flask) + Using cached https://files.pythonhosted.org/packages/d2/3d/fa76db83bf75c4f8d338c2fd15c8d33fdd7ad23a9b5e57eb6c5de26b430e/click-7.1.2-py2.py3-none-any.whl +Collecting Jinja2>=2.10.1 (from Flask) + Using cached https://files.pythonhosted.org/packages/30/9e/f663a2aa66a09d838042ae1a2c5659828bb9b41ea3a6efa20a20fd92b121/Jinja2-2.11.2-py2.py3-none-any.whl +Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests) + Using cached https://files.pythonhosted.org/packages/9f/f0/a391d1463ebb1b233795cabfc0ef38d3db4442339de68f847026199e69d7/urllib3-1.25.10-py2.py3-none-any.whl +Collecting idna<3,>=2.5 (from requests) + Using cached https://files.pythonhosted.org/packages/a2/38/928ddce2273eaa564f6f50de919327bf3a00f091b5baba8dfa9460f3a8a8/idna-2.10-py2.py3-none-any.whl +Collecting certifi>=2017.4.17 (from requests) + Using cached https://files.pythonhosted.org/packages/5e/c4/6c4fe722df5343c33226f0b4e0bb042e4dc13483228b4718baf286f86d87/certifi-2020.6.20-py2.py3-none-any.whl +Collecting chardet<4,>=3.0.2 (from requests) + Using cached https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl +Collecting six (from twilio) + Using cached https://files.pythonhosted.org/packages/ee/ff/48bde5c0f013094d729fe4b0316ba2a24774b3ff1c52d924a8a4cb04078a/six-1.15.0-py2.py3-none-any.whl +Collecting pytz (from twilio) + Using cached https://files.pythonhosted.org/packages/4f/a4/879454d49688e2fad93e59d7d4efda580b783c745fd2ec2a3adf87b0808d/pytz-2020.1-py2.py3-none-any.whl +Collecting PyJWT>=1.4.2 (from twilio) + Using cached https://files.pythonhosted.org/packages/87/8b/6a9f14b5f781697e51259d81657e6048fd31a113229cf346880bb7545565/PyJWT-1.7.1-py2.py3-none-any.whl +Collecting MarkupSafe>=0.23 (from Jinja2>=2.10.1->Flask) + Using cached https://files.pythonhosted.org/packages/0c/12/37f68957526d1ec0883b521934b4e1b8ff3dd8e4fab858a5bf3e487bcee9/MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl +Installing collected packages: Werkzeug, itsdangerous, click, MarkupSafe, Jinja2, Flask, urllib3, idna, certifi, chardet, requests, six, pytz, PyJWT, twilio + Running setup.py install for twilio ... done +Successfully installed Flask-1.1.2 Jinja2-2.11.2 MarkupSafe-1.1.1 PyJWT-1.7.1 Werkzeug-1.0.1 certifi-2020.6.20 chardet-3.0.4 click-7.1.2 idna-2.10 itsdangerous-1.1.0 pytz-2020.1 requests-2.24.0 six-1.15.0 twilio-6.45.4 urllib3-1.25.10 + +``` + +We can get started coding the application now that we have all of our +required dependencies installed. + + +## Building our application +Time to dig into the code! We're going to write three source files in +this application: + +* `app.py`: a Flask app that will handle the phone call and recording +* `transcribe.py`: a short Python script to invoke AssemblyAI with the + recording and start the transcription process +* `print_transcription.py`: a script to print the output of the + transcription to the terminal + +Remember that you can get access to all three of the completed files in the +`accurate-twilio-voice-call-recording-transcriptions-assemblyai` directory +of the +[blog-code-examples](https://github.com/fullstackpython/blog-code-examples) +Git repository if you do not want to type or copy from the blog post +itself. + +Create a new directory named `record-transcribe` to store your source files +and change into the new directory. + +``` +mkdir record-transcribe +cd record-transcribe +``` + +Create a new file named `app.py` with the following code: + + +```python +import os +from flask import Flask, request +from twilio.twiml.voice_response import VoiceResponse +from twilio.rest import Client + + +app = Flask(__name__) + +# pulls credentials from environment variables +client = Client() + +BASE_URL = os.getenv("BASE_URL") +twiml_instructions_url = "{}/record".format(BASE_URL) +recording_callback_url = "{}/callback".format(BASE_URL) +twilio_phone_number = os.getenv("TWILIO_PHONE_NUMBER") + + +@app.route("/record", methods=["GET", "POST"]) +def record(): + """Returns TwiML which prompts the caller to record a message""" + # Start our TwiML response + response = VoiceResponse() + + # Use to give the caller some instructions + response.say('Ahoy! Call recording starts now.') + + # Use to record the caller's message + response.record() + + # End the call with + response.hangup() + + return str(response) + + +``` + +There are a couple more functions we'll need to add to `app.py` but first +let's take a look at what the above code does. + +We imported parts of both the Flask and Twilio helper libraries, which will +enable us to programmatically create and control phone calls that Twilio +records. Note that when we instantiate the Twilio helper library with the +empty `Client()` constructor, it automatically looks to read two environment +variables, `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` to gain appropriate +permissions to your Twilio account. If those two environment variables +are not set with those exact names then you will need to explicitly pass +the Account SID and Auth Token for your account into the constructor. + +After the import are the Flask and Twilio library instantiations. +Then we configure the `BASE_URL` by reading from an environment variable. +In this tutorial the `BASE_URL` will be from Ngrok, but it can also +be your domain where your application is deployed, such as +"https://www.twilio.com". We have not yet set these environment variables, +but we will shortly after we finish writing `app.py`. + +After setting `BASE_URL`, and the three other variables set by environment +variables, we have the `record` function. This function is a +[Flask route](https://hackersandslackers.com/flask-routes/) that +generates the [TwiML](https://www.twilio.com/docs/voice/twiml) +that tells Twilio how to handle a phone call. First, an automated voice +alerts the person who picks up that the phone call is being recorded. Then +the recording starts. Whatever the person on the call says will be recorded +and stored by Twilio. + +Finish `app.py` by adding these two following functions after the +`record` function: + +```python +@app.route("/dial/") +def dial(phone_number): + """Dials an outbound phone call to the number in the URL. Just + as a heads up you will never want to leave a URL like this exposed + without authentication and further phone number format verification. + phone_number should be just the digits with the country code first, + for example 14155559812.""" + call = client.calls.create( + to='+{}'.format(phone_number), + from_=twilio_phone_number, + url=twiml_instructions_url, + ) + print(call.sid) + return "dialing +{}. call SID is: {}".format(phone_number, call.sid) + + +@app.route("/get-recording-url/") +def get_recording_url(call_sid): + recording_urls = "" + call = client.calls.get(call_sid) + for r in call.recordings.list(): + recording_urls="\n".join([recording_urls, r.uri]) + return str(recording_urls) +``` + +The `dial` function creates a Flask route that takes a phone number +input as part of the second level path. Note that in a production +application you *must* have better phone number validation or you +will have a security issue with unsanitized inputs. We are doing +this here to easily grab a phone number as input rather than having +to build a whole user interface with an HTML form just to grab a +phone number. `dial` calls the +[Twilio Voice API](https://www.twilio.com/docs/voice) using our +Twilio account credentials so that we can dial an outbound phone +call to the number sent in through the URL. The `twiml_instructions_url` +should be set to the `record` function URL so that it can give the +proper dialing and recording TwiML instructions for how Twilio's +service should handle dialing the phone call. + +Once we dial the outbound phone call, the +[call SID](https://support.twilio.com/hc/en-us/articles/223180488-What-is-a-Call-SID-) +is printed to the terminal. We'll need that call SID to get the +recording after the call is finished. + +Our `app.py` file is all done. We just need to export our environment +variables for our Twilio credentials. + +[Sign up for Twilio](https://www.twilio.com/referral/w9pugq) or +[log into your existing account](https://www.twilio.com/console). +Once you get to the [Twilio Console](https://www.twilio.com/console), +you can obtain your `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` on the +right side of the page: + +Twilio Console. + +When you sign up you should have a phone number assigned to your account. +You can use that or +[purchase a new phone number](https://www.twilio.com/console/phone-numbers/search) +to use. + +Set three environment variables with the names `TWILIO_ACCOUNT_SID`, +`TWILIO_AUTH_TOKEN`, and `TWILIO_PHONE_NUMBER` using the `export` command +in your terminal. Make sure to replace the values with your own Account SID, +Auth Token and Twilio phone number. + +```bash +export TWILIO_ACCOUNT_SID=xxxxxxxxxxxxx # found in twilio.com/console +export TWILIO_AUTH_TOKEN=yyyyyyyyyyyyyy # found in twilio.com/console +export TWILIO_PHONE_NUMBER=+17166382453 # replace with your Twilio number +``` + +Note that you must use the `export` command in every command line window +that you want this key to be accessible. The scripts we are writing will +not be able to access the Twilio APIs if you do not have the tokens exported +in the environment where you are running the script. + +There is one more environment variable to set before we can run `app.py`. +We need to use Ngrok as a localhost tunnel so that Twilio's webhook can +send an HTTP POST request to our `app.py` Flask application running on +our local development environment. + +Run Ngrok in a new terminal window, because you will need to keep it +running while we run our other Python code: + +```bash +./ngrok http 5000 +``` + +Ngrok running with a localhost tunnel. + +Copy the HTTPS version of the "Forwarding" URL and set the `BASE_URL` +environment variable value to it. For example, in this screenshot you +would set `BASE_URL` to `https://7f9139eaf445.ngrok.io` using the +following command: + +```bash +export BASE_URL=https://7f9139eaf445.ngrok.io # use your ngrok URL, or domain. no trailing slash +``` + +Okay, we can finally run `app.py`. Make sure you are still running Ngrok +in a different window, your virtualenv is active and that in this terminal +you have your four environment variables set, then run the `flask run` +command: + +```bash +flask run +``` + +You should see Flask output something like the following text: + +```bash + * Environment: production + WARNING: This is a development server. Do not use it in a production deployment. + Use a production WSGI server instead. + * Debug mode: off + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) +``` + +That is a legitimate warning: only use this command for +development purposes and when you want to [deploy](/deployment.html) +to production you need to use a real [WSGI server](/wsgi-servers.html) +like [Gunicorn](/green-unicorn-gunicorn.html). + +Time to test out our application. + + +## Testing Twilio Programmable Voice Recording +We can test our application by going to localhost on port 5000. +Go to this URL in your web browser, replacing the "14155551234" +with the phone number you want to call, where the person on the +line will be recorded: http://localhost:5000/dial/14155551234. + +That number should now receive a phone call from your Twilio +number. Pick up, record a message that you want to use to test +the transcription, and then hang up. + +If you get an error, make sure all of your environment variables +are set. You can check the values by using the echo command like +this: + +```bash +echo $BASE_URL +``` + +When the call is over, copy the call SID show on the web page +so that we can use it to look up where the recording audio +file is stored. + +Twilio call SID. + +Go to "localhost:5000/get-recording-url/" with the call SID +at the end. For example, +"localhost:5000/get-recording-url/CAda3f2f49ff4e8ef2be6b726edb998c92". + +Twilio call recording URL. + +Copy the entire output except for the ".json" at the end, then paste +it into the web browser's URL bar, prepended with "api.twilio.com". +For example, +"https://api.twilio.com/2010-04-01/Accounts/ACe3737affa0d2e17561ad44c9d190e70c/Recordings/RE3b42cf470bef829c3680ded961a09300". +This will bring up the recording. Copy the entire URL and we will use it +as input into the AssemblyAI service. + + +## Transcribing with the AssemblyAI API +We can now use the AssemblyAI API for speech-to-text transcription on +the call recording that was just made. + +[Sign up for an AssemblyAI account](https://app.assemblyai.com/login/) +and log in to the +[AssemblyAI dashboard](https://app.assemblyai.com/dashboard/), then +copy "Your API token" as shown in this screenshot: + +AssemblyAI dashboard. + +We need to export our AssemblyAI API key as an environment variable +so that our Python application can use it to authenticate with their +API. We also need to pass the publicly-accessible URL for the recording, +so we'll set that as an environment variable as well. + +```bash +# make sure to replace this URL with the one for your recording +export ASSEMBLYAI_KEY=your-api-key-here +export RECORDING_URL=https://api.twilio.com/2010-04-01/Accounts/ACe3737affa0d2e17561ad44c9d190e70c/Recordings/RE3b42cf470bef829c3680ded961a09300 +``` + +Create a new file named `transcribe.py` and write the following code in it: + +```python +import os +import requests + +endpoint = "https://api.assemblyai.com/v2/transcript" + +json = { + "audio_url": os.getenv("RECORDING_URL") +} + +headers = { + "authorization": os.getenv("ASSEMBLYAI_KEY"), + "content-type": "application/json" +} + +response = requests.post(endpoint, json=json, headers=headers) + +print(response.json()) +``` + +The above code calls the AssemblyAI transcription service using +the secret key and passes it the URL with the file recording. +The script prints out the JSON response from the service, +which will contain a transcription ID that we'll use to access +the results after they finish processing. + +Run the script using the `python` command: + +```bash +python transcribe.py +``` + +You will get back some JSON as output, similar what you see here: + +```bash +{'audio_end_at': None, 'acoustic_model': 'assemblyai_default', 'text': None, 'audio_url': 'https://api.twilio.com/2010-04-01/Accounts/ACe3737affa0d2e17561ad44c9d190e70c/Recordings/RE3b42cf470bef829c3680ded961a09300', 'speed_boost': False, 'language_model': 'assemblyai_default', 'redact_pii': False, 'confidence': None, 'webhook_status_code': None, 'id': 'zibe9vwmx-82ce-476c-85a7-e82c09c67daf', 'status': 'queued', +'boost_param': None, 'words': None, 'format_text': True, 'webhook_url': None, 'punctuate': True, 'utterances': None, 'audio_duration': None, 'auto_highlights': False, 'word_boost': [], 'dual_channel': None, 'audio_start_from': None} +``` + +Find the value contained with the `id` field of the JSON response. We need +that value to look up the final result of our transcription. Copy the +transcription ID and set it as an environment variable to use as input by +the final script: + +``` +# replace with what's found within `id` from the JSON response +export TRANSCRIPTION_ID=aksd19vwmx-82ce-476c-85a7-e82c09c67daf +``` + +We just need a little more Python that looks up the result and we'll be all +done. + + +## Retrieve the AssemblyAI Transcription +AssemblyAI will be busy transcribing the recording. Depending on the size of +the file it can take anywhere from a few seconds to a few minutes for the +job to complete. We can use the following code to see if the job is still +in progress or it has completed. If the transcription is done it will print +the results to the terminal. + +Create a new file named `print_transcription.py` with the following code: + +```python +import os +import requests + +endpoint = "https://api.assemblyai.com/v2/transcript/{}".format(os.getenv("TRANSCRIPTION_ID")) + +headers = { + "authorization": os.getenv("ASSEMBLYAI_KEY"), +} + +response = requests.get(endpoint, headers=headers) + +print(response.json()) +print("\n\n") +print(response.json()['text']) +``` + +The code above in `print_transcription.py` is very similar to the code +in the previous `transcribe.py` source file. imports `os` (operating system) +from the Python standard library, as we did in the previous two files, +to obtain the `TRANSCRIPTION_ID` and `ASSEMBLYAI_KEY` environment variable +values. + +The `endpoint` is simply the AssemblyAI API endpoint for retrieving +transcriptions. We set the appropriate `authorization` header and +make the API call using the `requests.get` function. We then print +out the JSON response as well as just the text that was transcribed. + +Time to test out this third file. Execute the following command in +the terminal: + +```bash +python print_transcription.py +``` + +Your output will be different based on your recording but you should see a +result in the terminal similar to the following: + +```bash +{'audio_end_at': None, 'acoustic_model': 'assemblyai_default', 'auto_highlights_result': None, 'text': 'An object relational mapper is a code library that automates the transfer of data stored in a relational database tables into objects that are more commonly used in application. Code or MS provide a high level abstraction upon a relational database that allows the developer to write Python code. Instead of sequel to create read update and delete data and schemas in their database developers can use the programming language that they are comfortable with comfortable to work with the database instead of writing sequel statements or short procedures.', 'audio_url': 'https://api.twilio.com/2010-04-01/Accounts/ACe3737affa0d2e17561ad44c9d190e70c/Recordings/RE3b42cf470bef829c3680ded961a09300', 'speed_boost': False, 'language_model': 'assemblyai_default', 'id': 'zibe9vwmx-82ce-476c-85a7-e82c09c67daf', 'confidence': 0.931797752808989, 'webhook_status_code': None, 'status': 'completed', 'boost_param': None, 'redact_pii': False, 'words': [{'text': 'An', 'confidence': 1.0, 'end': 90, 'start': 0}, {'text': 'object', 'confidence': 0.94, 'end': 570, 'start': 210}, {'text': 'relational', 'confidence': 0.89, 'end': 1080, 'start': 510}, {'text': 'mapper', 'confidence': 0.97, 'end': 1380, 'start': 1020}, {'text': 'is', 'confidence': 0.88, 'end': 1560, 'start': 1350}, {'text': 'a', 'confidence': 0.99, 'end': 1620, 'start': 1500}, {'text': 'code', 'confidence': 0.93, 'end': 1920, 'start': 1620}, {'text': 'library', 'confidence': 0.94, 'end': 2250, 'start': 1860}, {'text': 'that', 'confidence': 0.99, 'end': 2490, 'start': 2220}, {'text': 'automates', 'confidence': 0.93, 'end': 2940, 'start': 2430}, {'text': 'the', 'confidence': 0.95, 'end': 3150, 'start': 2910}, {'text': 'transfer', 'confidence': 0.98, 'end': 3510, 'start': 3090}, {'text': 'of', 'confidence': +0.99, 'end': 3660, 'start': 3480}, {'text': 'data', 'confidence': 0.84, 'end': 3960, 'start': 3630}, {'text': 'stored', 'confidence': 0.89, 'end': 4350, 'start': 3900}, {'text': 'in', 'confidence': 0.98, 'end': 4500, 'start': 4290}, {'text': 'a', 'confidence': 0.85, 'end': 4560, 'start': 4440}, {'text': 'relational', 'confidence': 0.87, 'end': 5580, 'start': 4500}, {'text': 'database', 'confidence': 0.92, 'end': +6030, 'start': 5520}, {'text': 'tables', 'confidence': 0.93, 'end': 6330, 'start': 5970}, {'text': 'into', 'confidence': 0.92, 'end': 7130, 'start': 6560}, {'text': 'objects', 'confidence': 0.96, 'end': 7490, 'start': 7100}, {'text': 'that', 'confidence': 0.97, 'end': 7700, 'start': 7430}, {'text': 'are', 'confidence': 0.9, 'end': 7850, 'start': 7640}, {'text': 'more', 'confidence': 0.97, 'end': 8030, 'start': 7790}, {'text': 'commonly', 'confidence': 0.92, 'end': 8480, 'start': 7970}, {'text': 'used', 'confidence': 0.86, 'end': 8750, 'start': 8420}, {'text': 'in', 'confidence': 0.94, 'end': 9050, 'start': 8840}, {'text': 'application.', 'confidence': 0.98, 'end': 9860, 'start': 9110}, {'text': 'Code', 'confidence': 0.93, 'end': 10040, 'start': 9830}, {'text': 'or', 'confidence': 1.0, 'end': 11210, 'start': 10220}, {'text': 'MS', 'confidence': 0.83, 'end': 11480, 'start': 11180}, {'text': 'provide', 'confidence': 0.94, 'end': 11870, 'start': 11510}, {'text': 'a', 'confidence': 1.0, 'end': 11960, 'start': 11840}, {'text': 'high', 'confidence': 1.0, 'end': 12200, 'start': 11930}, {'text': 'level', 'confidence': 0.94, 'end': 12440, 'start': 12170}, {'text': 'abstraction', 'confidence': 0.95, 'end': 12980, 'start': 12410}, {'text': +'upon', 'confidence': 0.94, 'end': 13220, 'start': 12950}, {'text': 'a', 'confidence': 1.0, 'end': 13280, 'start': 13160}, {'text': 'relational', 'confidence': 0.94, 'end': 13820, 'start': 13280}, {'text': 'database', 'confidence': 0.95, 'end': 14210, 'start': 13790}, {'text': 'that', 'confidence': 0.96, 'end': 14420, 'start': 14150}, {'text': 'allows', 'confidence': 0.99, 'end': 14720, 'start': 14360}, {'text': +'the', 'confidence': 0.56, 'end': 14870, 'start': 14690}, {'text': 'developer', 'confidence': 0.98, 'end': 15290, 'start': 14810}, {'text': 'to', 'confidence': 0.94, 'end': 15410, 'start': 15230}, {'text': 'write', 'confidence': 0.96, 'end': 15680, 'start': 15380}, {'text': 'Python', 'confidence': 0.94, 'end': 16070, 'start': 15620}, {'text': 'code.', 'confidence': 0.98, 'end': 16310, 'start': 16070}, {'text': 'Instead', 'confidence': 0.97, 'end': 17160, 'start': 16500}, {'text': 'of', 'confidence': 0.93, 'end': 17340, 'start': 17130}, {'text': 'sequel', 'confidence': 0.86, 'end': 17820, 'start': 17280}, {'text': 'to', 'confidence': 0.91, 'end': 18090, 'start': 17880}, {'text': 'create', 'confidence': 0.89, 'end': 18450, 'start': 18090}, {'text': 'read', 'confidence': 0.88, 'end': 18840, 'start': 18480}, {'text': 'update', 'confidence': 0.92, 'end': 19290, 'start': 18870}, {'text': 'and', 'confidence': 0.94, 'end': 19590, 'start': 19230}, {'text': 'delete', 'confidence': 0.89, 'end': 19920, 'start': 19530}, {'text': 'data', +'confidence': 0.95, 'end': 20190, 'start': 19890}, {'text': 'and', 'confidence': 0.92, 'end': 20490, 'start': 20250}, {'text': 'schemas', 'confidence': 0.86, 'end': 21000, 'start': 20430}, {'text': 'in', 'confidence': 0.94, 'end': 21210, 'start': 21000}, {'text': 'their', 'confidence': 0.98, 'end': 21510, 'start': 21150}, {'text': 'database', 'confidence': 0.97, 'end': 21900, 'start': 21450}, {'text': 'developers', 'confidence': 0.83, 'end': 23200, 'start': 22420}, {'text': 'can', 'confidence': 0.95, 'end': 23440, 'start': 23200}, {'text': 'use', 'confidence': 0.97, 'end': 23650, 'start': 23410}, {'text': 'the', 'confidence': 0.99, 'end': 23890, 'start': 23590}, {'text': 'programming', 'confidence': 0.97, 'end': 24370, 'start': 23830}, {'text': 'language', 'confidence': 1.0, 'end': 24700, 'start': 24310}, {'text': 'that', 'confidence': 1.0, 'end': 24880, 'start': 24640}, {'text': 'they', 'confidence': 0.99, 'end': 25060, 'start': 24820}, {'text': 'are', 'confidence': 0.85, 'end': 25210, 'start': 25000}, {'text': 'comfortable', 'confidence': 0.92, 'end': 25780, 'start': 25180}, {'text': 'with', 'confidence': 1.0, 'end': 25960, 'start': 25720}, {'text': 'comfortable', 'confidence': 0.94, 'end': 29090, 'start': 28090}, {'text': 'to', 'confidence': 0.84, 'end': 29840, 'start': 29180}, {'text': 'work', 'confidence': 0.95, 'end': 30050, 'start': 29780}, {'text': 'with', 'confidence': 0.98, 'end': 30290, 'start': 30020}, {'text': 'the', 'confidence': 0.69, 'end': 30440, 'start': 30230}, {'text': 'database', 'confidence': 0.98, 'end': 30860, 'start': 30380}, {'text': 'instead', 'confidence': 1.0, 'end': 32780, 'start': 31780}, {'text': 'of', 'confidence': 0.98, 'end': 32900, 'start': 32720}, {'text': 'writing', 'confidence': 0.87, 'end': 33320, 'start': 32870}, {'text': 'sequel', 'confidence': 0.88, 'end': 33860, 'start': 33290}, {'text': 'statements', 'confidence': 0.95, 'end': 34310, 'start': 33800}, {'text': 'or', 'confidence': 0.9, 'end': 34460, 'start': 34250}, {'text': 'short', 'confidence': 0.9, 'end': 34790, 'start': 34430}, {'text': 'procedures.', 'confidence': 0.98, 'end': 35270, 'start': 34760}], 'format_text': True, 'webhook_url': None, 'punctuate': True, 'utterances': None, 'audio_duration': 36.288, 'auto_highlights': False, 'word_boost': [], +'dual_channel': None, 'audio_start_from': None} + + +An object relational mapper is a code library that automates the transfer of data stored in a relational database tables into objects that are more commonly used in application. Code or MS provide a high level abstraction upon a relational database that allows the developer to write Python code. Instead of sequel to create read update and delete data and schemas in their database developers can use the programming language that they are comfortable with comfortable to work with the database instead of writing sequel statements or short procedures. +``` + +That's a lot of output. The first part contains the results of the +transcription and the confidence in the accuracy of each word transcribed. +The second part is just the plain text output from the transcription. + +You can take this now take this base code and add it to any application +that needs high quality text-to-speech transcription. If the results +aren't quite good enough for you, check out this tutorial on +[boosting accuracy for keywords or phrases](https://docs.assemblyai.com/guides/boosting-accuracy-for-keywords-or-phrases) +as well as +[better matching your data with topic detection](https://docs.assemblyai.com/guides/iab-categorization). + + +## What now? +We just finished building a highly accurate transcription application for recordings. + +Next, try out some of these other related Python tutorials: + +* [How to Transcribe Speech Recordings into Text with Python](/blog/transcribe-recordings-speech-text-assemblyai.html) +* [Reporting Exceptions in Python Scripts with Sentry](/blog/report-exceptions-python-scripts-sentry.html) +* [Basic Data Types in Python: Strings](/blog/python-basic-data-types-strings.html) + +Questions? Let me know via +[a GitHub issue ticket on the Full Stack Python repository](https://github.com/mattmakai/fullstackpython.com/issues), +on Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). +If you see an issue or error in this tutorial, please +[fork the source repository on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/201009-accurate-twilio-voice-call-recording-transcriptions-assemblyai.markdown) +and submit a pull request with the fix. + diff --git a/content/posts/210105-django-accurate-twilio-voice-transcriptions.markdown b/content/posts/210105-django-accurate-twilio-voice-transcriptions.markdown new file mode 100644 index 000000000..c4b7d0018 --- /dev/null +++ b/content/posts/210105-django-accurate-twilio-voice-transcriptions.markdown @@ -0,0 +1,716 @@ +title: Using Django & AssemblyAI for More Accurate Twilio Call Transcriptions +slug: django-accurate-twilio-voice-transcriptions +meta: Use Python, Django and AssemblyAI's transcription API to improve recording accuracy for Twilio Programmable Voice phone calls. +category: post +date: 2021-01-05 +modified: 2021-09-13 +newsletter: False +headerimage: /img/headers/django-assemblyai.jpg +headeralt: Logos for the implementations used in this blog post. Copyright their respective owners. + + +[Recording phone calls](https://www.twilio.com/docs/voice/tutorials/how-to-record-phone-calls-python) +with one or more participants is easy with +[Twilio's Programmable Voice API](https://www.twilio.com/docs/voice/quickstart/python), +but the speech-to-text accuracy can be poor, especially for transcription +of words from niche domains such as healthcare and engineering. +[AssemblyAI's API for transcription](https://www.assemblyai.com/) +provides much higher accuracy by default and through optional keyword lists. +accuracy for [recordings](https://www.twilio.com/docs/voice/api/recording). + +In this tutorial, we'll record an outbound Twilio call recording to AssemblyAI's +API to get significantly more accurate speech-to-text output. + + +## Tutorial Prerequisites +Ensure you have Python 3 installed, because Python 2 reached its +end-of-life at the beginning of 2020 and is no longer supported. +Preferrably, you should have +[Python 3.7 or greater installed](https://www.python.org/downloads/) +in your [development environment](/development-environments.html). +This tutorial will also use: + +We will use the following dependencies to complete this +tutorial: + +* [Django](/django.html) version 3.1.x, where *x* is the latest security + release +* A [Twilio account](https://www.twilio.com/referral/w9pugq) and the + [Python Twilio helper library](https://pypi.org/project/twilio/) + version 6.45.2 or newer +* [requests](https://requests.readthedocs.io/) + [version 2.24.0](https://pypi.org/project/requests/) +* An [AssemblyAI](https://www.assemblyai.com/) account, which you can sign up for a [free key API access key here](https://app.assemblyai.com/login/) + +All code in this blog post is available open source under the MIT license +on GitHub under the +[django-accurate-twilio-voice-transcriptions directory of the blog-code-examples repository](https://github.com/fullstackpython/blog-code-examples). +Use the source code as you desire for your own projects. + + +## Configuring our development environment +Change into the directory where you keep your Python +[virtual environments](/virtual-environments-virtualenvs-venvs.html). +Create a new virtualenv for this project using the following +command. + +Start the Django project by creating a new +[virtual environment](/virtual-environments-virtualenvs-venvs.html) +using the following command. I recommend using a separate directory +such as `~/venvs/` (the tilde is a shortcut for your user's `home` +directory) so that you always know where all your virtualenvs are +located. + +```bash +python3 -m venv ~/venvs/djtranscribe +``` + +Activate the virtualenv with the `activate` shell script: + +```bash +source ~/venvs/djtranscribe/bin/activate +``` + +After the above command is executed, the command prompt will +change so that the name of the virtualenv is prepended to the +original command prompt format, so if your prompt is just +`$`, it will now look like the following: + +```bash +(djtranscribe) $ +``` + +Remember, you have to activate your virtualenv in every new terminal +window where you want to use dependencies in the virtualenv. + +We can now install the [Django](https://pypi.org/project/Django/) +package into the activated but otherwise empty virtualenv. + +``` +pip install django==3.1.3 requests==2.24.0 twilio==6.45.2 +``` + +Look for output similar to the following to confirm the appropriate +packages were installed correctly from PyPI. + +``` +(djtranscribe) $ pip install django==3.1.3 requests==2.24.0 twilio=6.45.2 +pip install django requests twilio +Collecting django + Downloading Django-3.1.3-py3-none-any.whl (7.8 MB) + |████████████████████████████████| 7.8 MB 2.6 MB/s +Collecting requests + Using cached requests-2.24.0-py2.py3-none-any.whl (61 kB) +Collecting twilio + Downloading twilio-6.47.0.tar.gz (460 kB) + |████████████████████████████████| 460 kB 19.6 MB/s +Collecting sqlparse>=0.2.2 + Downloading sqlparse-0.4.1-py3-none-any.whl (42 kB) + |████████████████████████████████| 42 kB 4.8 MB/s +Collecting pytz + Downloading pytz-2020.4-py2.py3-none-any.whl (509 kB) + |████████████████████████████████| 509 kB 31.0 MB/s +Collecting asgiref<4,>=3.2.10 + Downloading asgiref-3.3.0-py3-none-any.whl (19 kB) +Collecting chardet<4,>=3.0.2 + Using cached chardet-3.0.4-py2.py3-none-any.whl (133 kB) +Collecting idna<3,>=2.5 + Using cached idna-2.10-py2.py3-none-any.whl (58 kB) +Collecting certifi>=2017.4.17 + Using cached certifi-2020.6.20-py2.py3-none-any.whl (156 kB) +Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 + Downloading urllib3-1.25.11-py2.py3-none-any.whl (127 kB) + |████████████████████████████████| 127 kB 24.5 MB/s +Collecting six + Using cached six-1.15.0-py2.py3-none-any.whl (10 kB) +Collecting PyJWT>=1.4.2 + Using cached PyJWT-1.7.1-py2.py3-none-any.whl (18 kB) +Using legacy 'setup.py install' for twilio, since package 'wheel' is not installed. +Installing collected packages: sqlparse, pytz, asgiref, django, chardet, idna, certifi, urllib3, requests, six, PyJWT, twilio + Running setup.py install for twilio ... done +Successfully installed PyJWT-1.7.1 asgiref-3.3.0 certifi-2020.6.20 chardet-3.0.4 django-3.1.3 idna-2.10 pytz-2020.4 requests-2.24.0 six-1.15.0 sqlparse-0.4.1 twilio-6.47.0 urllib3-1.25.11 + +``` + +We can get started coding the application now that we have all of our +required dependencies installed. + + +## Starting our Django project +Let's begin coding our application. + +We can use the [Django](/django.html) `django-admin` tool to create +the boilerplate code structure to get our project started. +Change into the directory where you develop your applications. For +example, I typically use `/Users/matt/devel/py/` for all of my +Python projects. Then run the following command to start a Django +project named `djtranscribe`: + +``` +django-admin.py startproject djtranscribe +``` + +Note that in this tutorial we are using the same name for both the +virtualenv and the Django project directory, but they can be +different names if you prefer that for organizing your own projects. + +The `django-admin` command creates a directory named `djtranscribe` +along with several subdirectories that you should be familiar with +if you have previously worked with Django. + +Change directories into the new project. + +``` +cd djtranscribe +``` + +Create a new Django app within `djtranscribe` named `caller`. + +``` +python manage.py startapp caller +``` + +Django will generate a new folder named `caller` in the project. +We should update the URLs so the app is accessible before we write +our `views.py` code. + +Open `djtranscribe/djtranscribe/urls.py`. Add the highlighted +lines so that URL resolver will check the `caller` app +for additional routes to match with URLs that are requested of +this Django application. + +```python +# djtranscribe/djtranscribe/urls.py +~~from django.conf.urls import include +from django.contrib import admin +from django.urls import path + + +urlpatterns = [ +~~ path('', include('caller.urls')), + path('admin/', admin.site.urls), +] +``` + +Save `djtranscribe/djtranscribe/urls.py` and open +`djtranscribe/djtranscribe/settings.py`. +Add the `caller` app to `settings.py` by inserting +the highlighted line: + +```python +# djtranscribe/djtranscribe/settings.py +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +~~ 'caller', +] +``` + +Make sure you change the default `DEBUG` and `SECRET_KEY` +values in `settings.py` before you deploy any code to production. Secure +your app properly with the information from the Django +[production deployment checklist](https://docs.djangoproject.com/en/stable/howto/deployment/checklist/) +so that you do not add your project to the list of hacked applications +on the web. + +Save and close `settings.py`. + +Next change into the `djtranscribe/caller` directory. Create +a new file named `urls.py` to contain routes for the `caller` app. + +Add all of these lines to the empty `djtranscribe/caller/urls.py` +file. + +```python +# djtranscribe/caller/urls.py +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'', views.index, name="index"), +] +``` + +Save `djtranscribe/caller/urls.py`. Open +`djtranscribe/caller/views.py` to add the +following two highlighted lines. + +``` +# djtranscribe/caller/views.py +from django.http import HttpResponse + + +~~def index(request): +~~ return HttpResponse('Hello, world!', 200) +``` + +We can test out that this simple boilerplate response is +correct before we start adding the meat of the functionality to +the project. Change into the base directory of your Django project +where the `manage.py` file is located. Execute the development +server with the following command: + +```bash +python manage.py runserver +``` + +The Django development server should start up with no issues other than +an unapplied migrations warning. + +``` +Watching for file changes with StatReloader +Performing system checks... + +System check identified no issues (0 silenced). + +November 15, 2020 - 14:07:03 +Django version 3.1.3, using settings 'djtranscribe.settings' +Starting development server at http://127.0.0.1:8000/ +Quit the server with CONTROL-C. +``` + +Open a web browser and go to `localhost:8000`. + +Web browser rendering simple text 'Hello, world!'. + +You should see 'Hello, world!' rendered in the browser. +That means everything is working properly so far and we can +now add the dialing, recording and transcribing capabilities to +our Django project. + + +## Adding Twilio to the Django project +Time to add Twilio's Voice API into the mix so we can dial +a phone call from our Django project and make a recording +out of it. + + +Start by opening up `djtranscribe/djtranscribe/settings.py` +and modifying it with the following highlighted `import os` +line: + +```python +# djtranscribe/djtranscribe/settings.py +~~import os +from pathlib import Path + + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent +``` + +Then at the bottom of the `settings.py` file, add the +following highlighted lines, which will be settings that are pulled from +environment variables we will configure later. + +```python +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.1/howto/static-files/ + +STATIC_URL = '/static/' + + +~~BASE_URL = os.getenv("BASE_URL") +~~TWIML_INSTRUCTIONS_URL = "{}/record/".format(BASE_URL) +~~TWILIO_PHONE_NUMBER = os.getenv("TWILIO_PHONE_NUMBER") +``` + +Save `settings.py` and change into the `caller` Django app directory. + +Update `djtranscribe/caller/urls.py` with the the following new +code: + +```python +# djtranscribe/caller/urls.py +from django.conf.urls import url +from . import views + +urlpatterns = [ +~~ url(r'dial/(\d+)/$', views.dial, name="dial"), +~~ url(r'record/$', views.record_twiml, name="record-twiml"), +~~ url(r'get-recording-url/([A-Za-z0-9]+)/$', views.get_recording_url, +~~ name='recording-url'), +] +``` + +Next, open `djtranscribe/views.py` and update it with the following +code, replacing what already exists within the file: + +```python +# djtranscribe/caller/views.py +from django.conf import settings +from django.http import HttpResponse +from django.views.decorators.csrf import csrf_exempt + +from twilio.rest import Client +from twilio.twiml.voice_response import VoiceResponse + + +def dial(request, phone_number): + """Dials an outbound phone call to the number in the URL. Just + as a heads up you will never want to leave a URL like this exposed + without authentication and further phone number format verification. + phone_number should be just the digits with the country code first, + for example 14155559812.""" + # pulls credentials from environment variables + twilio_client = Client() + call = twilio_client.calls.create( + to='+{}'.format(phone_number), + from_=settings.TWILIO_PHONE_NUMBER, + url=settings.TWIML_INSTRUCTIONS_URL, + ) + print(call.sid) + return HttpResponse("dialing +{}. call SID is: {}".format( + phone_number, call.sid)) + + +@csrf_exempt +def record_twiml(request): + """Returns TwiML which prompts the caller to record a message""" + # Start our TwiML response + response = VoiceResponse() + + # Use to give the caller some instructions + response.say('Ahoy! Call recording starts now.') + + # Use to record the caller's message + response.record() + + # End the call with + response.hangup() + + return HttpResponse(str(response), content_type='application/xml') + + +def get_recording_url(request, call_sid): + """Returns an HttpResponse with plain text of the link to one or more + recordings from the specified Call SID.""" + # pulls credentials from environment variables + twilio_client = Client() + recording_urls = "" + call = twilio_client.calls.get(call_sid) + for r in call.recordings.list(): + recording_urls="\n".join([recording_urls, "".join(['https://api.twilio.com', r.uri])]) + return HttpResponse(str(recording_urls), 200) +``` + +Each of the above view functions performs one of the steps needed to +create a call recording of a phone call dialed by Twilio, and then +retrieve it as a file. `dial` programmatically initiates the outbound +call, `record_twiml` returns instructions to play a message that the +call is being recorded, records it, and then hangs up when the call +is done. `get_recording_url` only returns the URL location of the +recorded phone call so that in the next step we can send the file over +to AssemblyAI. + +Our Django project modifications are done. Next, we need to use +two services, Twilio and Ngrok, to enable some of the machine +to happen of phone calling and running the application from our +local machine. + + +## Twilio credentials and environment variables +[Sign up for Twilio](https://www.twilio.com/referral/w9pugq) or +[log into your existing account](https://www.twilio.com/console). +Once you get to the [Twilio Console](https://www.twilio.com/console), +you can obtain your `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` on the +right side of the page: + +Twilio Console. + +When you sign up you should have a phone number assigned to your account. +You can use that or +[purchase a new phone number](https://www.twilio.com/console/phone-numbers/search) +to use. + +Set three environment variables with the names `TWILIO_ACCOUNT_SID`, +`TWILIO_AUTH_TOKEN`, and `TWILIO_PHONE_NUMBER` using the `export` command +in your terminal. Make sure to replace the values with your own Account SID, +Auth Token and Twilio phone number. + +```bash +export TWILIO_ACCOUNT_SID=xxxxxxxxxxxxx # found in twilio.com/console +export TWILIO_AUTH_TOKEN=yyyyyyyyyyyyyy # found in twilio.com/console +export TWILIO_PHONE_NUMBER=+17166382453 # replace with your Twilio number +``` + +Note that you must use the `export` command in every command line window +that you want this key to be accessible. The scripts we are writing will +not be able to access the Twilio APIs if you do not have the tokens exported +in the environment where you are running the script. + +There is one more environment variable to set before we can run `app.py`. +We need to use Ngrok as a localhost tunnel so that Twilio's webhook can +send an HTTP POST request to our Django application running on +our local development environment. + +Run Ngrok in a new terminal window, because you will need to keep it +running while we run our other Python code: + +```bash +./ngrok http 8000 +``` + +Ngrok creating a localhost tunnel. + +Copy the HTTPS version of the "Forwarding" URL and set the `BASE_URL` +environment variable value to it. For example, in this screenshot you +would set `BASE_URL` to `https://7764c1810ad3.ngrok.io` using the +following command: + +```bash +export BASE_URL=https://7764c1810ad3.ngrok.io # use your ngrok URL, or domain. no trailing slash +``` + +We also need to update `djtranscribe/djtranscribe/settings.py`'s +`ALLOWED_HOSTS` list to include the Ngrok Forwarding URL otherwise +the [webhook](/webhooks.html) from Twilio asking for instructions +on how to handle the phone call will fail. Open the `settings.py` +file and update the `ALLOWED_HOSTS` with your Ngrok Forwarding +hostname list the following: + +``` +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.getenv('SECRET_KEY', 'development key') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +~~ALLOWED_HOSTS = ['7764c1810ad3.ngrok.io','127.0.0.1','localhost'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'caller', +] +``` + +Okay, we can finally re-run our Django web app. Ensure Ngrok is still +running in a different window, your virtualenv is active and that in this +terminal you have your four environment variables set, then run the +`runserver` command in the root project directory where `manage.py` +is located: + +```bash +python manage.py runserver +``` + +Let's make our phone ring by testing the application. + + +## Testing Twilio Programmable Voice Recording +We can test our application by going to localhost on port 8000. +Go to this URL in your web browser, replacing the "14155551234" +with the phone number you want to call, where the person on the +line will be recorded: http://localhost:8000/dial/14155551234. + +That number should now receive a phone call from your Twilio +number. Pick up, record a message that you want to use to test +the transcription, and then hang up. + +If you get an error, make sure all of your environment variables +are set. You can check the values by using the echo command like +this: + +```bash +echo $BASE_URL +``` + +When the call is over, copy the call SID show on the web page +so that we can use it to look up where the recording audio +file is stored. + +Twilio call SID served through the Django web app. + +Go to "localhost:8000/get-recording-url/" with the call SID +at the end. For example, +"localhost:8000/get-recording-url/CAda3f2f49ff4e8ef2be6b726edb998c92". + +Twilio call recording URL. + +Copy the entire output except for the ".json" at the end, then paste +it into the web browser's URL bar, prepended with "api.twilio.com". +For example, +"https://api.twilio.com/2010-04-01/Accounts/ACe3737affa0d2e17561ad44c9d190e70c/Recordings/RE3b42cf470bef829c3680ded961a09300". +This will bring up the recording. Copy the entire URL and we will use it +as input into the AssemblyAI service. + + +## Transcribing with the AssemblyAI API +We can now use the AssemblyAI API for speech-to-text transcription on +the call recording that was just made. + +[Sign up for an AssemblyAI account](https://app.assemblyai.com/login/) +and log in to the +[AssemblyAI dashboard](https://app.assemblyai.com/dashboard/), then +copy "Your API token" as shown in this screenshot: + +AssemblyAI dashboard. + +We need to export our AssemblyAI API key as an environment variable +so that our Python application can use it to authenticate with their +API. We also need to pass the publicly-accessible URL for the recording, +so we'll set that as an environment variable as well. + +```bash +# make sure to replace this URL with the one for your recording +export ASSEMBLYAI_KEY=your-api-key-here +export RECORDING_URL=https://api.twilio.com/2010-04-01/Accounts/ACe3737affa0d2e17561ad44c9d190e70c/Recordings/RE3b42cf470bef829c3680ded961a09300 +``` + +Create a new file named `transcribe.py` and write the following code in it: + +```python +import os +import requests + +endpoint = "https://api.assemblyai.com/v2/transcript" + +json = { + "audio_url": os.getenv("RECORDING_URL") +} + +headers = { + "authorization": os.getenv("ASSEMBLYAI_KEY"), + "content-type": "application/json" +} + +response = requests.post(endpoint, json=json, headers=headers) + +print(response.json()) +``` + +The above code calls the AssemblyAI transcription service using +the secret key and passes it the URL with the file recording. +The script prints out the JSON response from the service, +which will contain a transcription ID that we'll use to access +the results after they finish processing. + +Run the script using the `python` command: + +```bash +python transcribe.py +``` + +You will get back some JSON as output, similar what you see here: + +```bash +{'audio_end_at': None, 'acoustic_model': 'assemblyai_default', 'text': None, 'audio_url': 'https://api.twilio.com/2010-04-01/Accounts/ACe3737affa0d2e17561ad44c9d190e70c/Recordings/RE3b42cf470bef829c3680ded961a09300', 'speed_boost': False, 'language_model': 'assemblyai_default', 'redact_pii': False, 'confidence': None, 'webhook_status_code': None, 'id': 'zibe9vwmx-82ce-476c-85a7-e82c09c67daf', 'status': 'queued', +'boost_param': None, 'words': None, 'format_text': True, 'webhook_url': None, 'punctuate': True, 'utterances': None, 'audio_duration': None, 'auto_highlights': False, 'word_boost': [], 'dual_channel': None, 'audio_start_from': None} +``` + +Find the value contained with the `id` field of the JSON response. We need +that value to look up the final result of our transcription. Copy the +transcription ID and set it as an environment variable to use as input by +the final script: + +``` +# replace with what's found within `id` from the JSON response +export TRANSCRIPTION_ID=aksd19vwmx-82ce-476c-85a7-e82c09c67daf +``` + +We just need a little more Python that looks up the result and we'll be all +done. + + +## Retrieve the AssemblyAI Transcription +AssemblyAI will be busy transcribing the recording. Depending on the size of +the file it can take anywhere from a few seconds to a few minutes for the +job to complete. We can use the following code to see if the job is still +in progress or it has completed. If the transcription is done it will print +the results to the terminal. + +Create a new file named `print_transcription.py` with the following code: + +```python +import os +import requests + +endpoint = "https://api.assemblyai.com/v2/transcript/{}".format(os.getenv("TRANSCRIPTION_ID")) + +headers = { + "authorization": os.getenv("ASSEMBLYAI_KEY"), +} + +response = requests.get(endpoint, headers=headers) + +print(response.json()) +print("\n\n") +print(response.json()['text']) +``` + +The code above in `print_transcription.py` is very similar to the code +in the previous `transcribe.py` source file. imports `os` (operating system) +from the Python standard library, as we did in the previous two files, +to obtain the `TRANSCRIPTION_ID` and `ASSEMBLYAI_KEY` environment variable +values. + +The `endpoint` is the AssemblyAI API endpoint for retrieving +transcriptions. We set the appropriate `authorization` header and +make the API call using the `requests.get` function. We then print +out the JSON response as well as just the text that was transcribed. + +Time to test out this third file. Execute the following command in +the terminal: + +```bash +python print_transcription.py +``` + +Your output will be different based on your recording but you should see a +result in the terminal similar to the following: + +```bash +{'audio_end_at': None, 'acoustic_model': 'assemblyai_default', 'auto_highlights_result': None, 'text': 'An object relational mapper is a code library that automates the transfer of data stored in a relational database tables into objects that are more commonly used in application. Code or MS provide a high level abstraction upon a relational database that allows the developer to write Python code. Instead of sequel to create read update and delete data and schemas in their database developers can use the programming language that they are comfortable with comfortable to work with the database instead of writing sequel statements or short procedures.', 'audio_url': 'https://api.twilio.com/2010-04-01/Accounts/ACe3737affa0d2e17561ad44c9d190e70c/Recordings/RE3b42cf470bef829c3680ded961a09300', 'speed_boost': False, 'language_model': 'assemblyai_default', 'id': 'zibe9vwmx-82ce-476c-85a7-e82c09c67daf', 'confidence': 0.931797752808989, 'webhook_status_code': None, 'status': 'completed', 'boost_param': None, 'redact_pii': False, 'words': [{'text': 'An', 'confidence': 1.0, 'end': 90, 'start': 0}, {'text': 'object', 'confidence': 0.94, 'end': 570, 'start': 210}, {'text': 'relational', 'confidence': 0.89, 'end': 1080, 'start': 510}, {'text': 'mapper', 'confidence': 0.97, 'end': 1380, 'start': 1020}, {'text': 'is', 'confidence': 0.88, 'end': 1560, 'start': 1350}, {'text': 'a', 'confidence': 0.99, 'end': 1620, 'start': 1500}, {'text': 'code', 'confidence': 0.93, 'end': 1920, 'start': 1620}, {'text': 'library', 'confidence': 0.94, 'end': 2250, 'start': 1860}, {'text': 'that', 'confidence': 0.99, 'end': 2490, 'start': 2220}, {'text': 'automates', 'confidence': 0.93, 'end': 2940, 'start': 2430}, {'text': 'the', 'confidence': 0.95, 'end': 3150, 'start': 2910}, {'text': 'transfer', 'confidence': 0.98, 'end': 3510, 'start': 3090}, {'text': 'of', 'confidence': +0.99, 'end': 3660, 'start': 3480}, {'text': 'data', 'confidence': 0.84, 'end': 3960, 'start': 3630}, {'text': 'stored', 'confidence': 0.89, 'end': 4350, 'start': 3900}, {'text': 'in', 'confidence': 0.98, 'end': 4500, 'start': 4290}, {'text': 'a', 'confidence': 0.85, 'end': 4560, 'start': 4440}, {'text': 'relational', 'confidence': 0.87, 'end': 5580, 'start': 4500}, {'text': 'database', 'confidence': 0.92, 'end': +6030, 'start': 5520}, {'text': 'tables', 'confidence': 0.93, 'end': 6330, 'start': 5970}, {'text': 'into', 'confidence': 0.92, 'end': 7130, 'start': 6560}, {'text': 'objects', 'confidence': 0.96, 'end': 7490, 'start': 7100}, {'text': 'that', 'confidence': 0.97, 'end': 7700, 'start': 7430}, {'text': 'are', 'confidence': 0.9, 'end': 7850, 'start': 7640}, {'text': 'more', 'confidence': 0.97, 'end': 8030, 'start': 7790}, {'text': 'commonly', 'confidence': 0.92, 'end': 8480, 'start': 7970}, {'text': 'used', 'confidence': 0.86, 'end': 8750, 'start': 8420}, {'text': 'in', 'confidence': 0.94, 'end': 9050, 'start': 8840}, {'text': 'application.', 'confidence': 0.98, 'end': 9860, 'start': 9110}, {'text': 'Code', 'confidence': 0.93, 'end': 10040, 'start': 9830}, {'text': 'or', 'confidence': 1.0, 'end': 11210, 'start': 10220}, {'text': 'MS', 'confidence': 0.83, 'end': 11480, 'start': 11180}, {'text': 'provide', 'confidence': 0.94, 'end': 11870, 'start': 11510}, {'text': 'a', 'confidence': 1.0, 'end': 11960, 'start': 11840}, {'text': 'high', 'confidence': 1.0, 'end': 12200, 'start': 11930}, {'text': 'level', 'confidence': 0.94, 'end': 12440, 'start': 12170}, {'text': 'abstraction', 'confidence': 0.95, 'end': 12980, 'start': 12410}, {'text': +'upon', 'confidence': 0.94, 'end': 13220, 'start': 12950}, {'text': 'a', 'confidence': 1.0, 'end': 13280, 'start': 13160}, {'text': 'relational', 'confidence': 0.94, 'end': 13820, 'start': 13280}, {'text': 'database', 'confidence': 0.95, 'end': 14210, 'start': 13790}, {'text': 'that', 'confidence': 0.96, 'end': 14420, 'start': 14150}, {'text': 'allows', 'confidence': 0.99, 'end': 14720, 'start': 14360}, {'text': +'the', 'confidence': 0.56, 'end': 14870, 'start': 14690}, {'text': 'developer', 'confidence': 0.98, 'end': 15290, 'start': 14810}, {'text': 'to', 'confidence': 0.94, 'end': 15410, 'start': 15230}, {'text': 'write', 'confidence': 0.96, 'end': 15680, 'start': 15380}, {'text': 'Python', 'confidence': 0.94, 'end': 16070, 'start': 15620}, {'text': 'code.', 'confidence': 0.98, 'end': 16310, 'start': 16070}, {'text': 'Instead', 'confidence': 0.97, 'end': 17160, 'start': 16500}, {'text': 'of', 'confidence': 0.93, 'end': 17340, 'start': 17130}, {'text': 'sequel', 'confidence': 0.86, 'end': 17820, 'start': 17280}, {'text': 'to', 'confidence': 0.91, 'end': 18090, 'start': 17880}, {'text': 'create', 'confidence': 0.89, 'end': 18450, 'start': 18090}, {'text': 'read', 'confidence': 0.88, 'end': 18840, 'start': 18480}, {'text': 'update', 'confidence': 0.92, 'end': 19290, 'start': 18870}, {'text': 'and', 'confidence': 0.94, 'end': 19590, 'start': 19230}, {'text': 'delete', 'confidence': 0.89, 'end': 19920, 'start': 19530}, {'text': 'data', +'confidence': 0.95, 'end': 20190, 'start': 19890}, {'text': 'and', 'confidence': 0.92, 'end': 20490, 'start': 20250}, {'text': 'schemas', 'confidence': 0.86, 'end': 21000, 'start': 20430}, {'text': 'in', 'confidence': 0.94, 'end': 21210, 'start': 21000}, {'text': 'their', 'confidence': 0.98, 'end': 21510, 'start': 21150}, {'text': 'database', 'confidence': 0.97, 'end': 21900, 'start': 21450}, {'text': 'developers', 'confidence': 0.83, 'end': 23200, 'start': 22420}, {'text': 'can', 'confidence': 0.95, 'end': 23440, 'start': 23200}, {'text': 'use', 'confidence': 0.97, 'end': 23650, 'start': 23410}, {'text': 'the', 'confidence': 0.99, 'end': 23890, 'start': 23590}, {'text': 'programming', 'confidence': 0.97, 'end': 24370, 'start': 23830}, {'text': 'language', 'confidence': 1.0, 'end': 24700, 'start': 24310}, {'text': 'that', 'confidence': 1.0, 'end': 24880, 'start': 24640}, {'text': 'they', 'confidence': 0.99, 'end': 25060, 'start': 24820}, {'text': 'are', 'confidence': 0.85, 'end': 25210, 'start': 25000}, {'text': 'comfortable', 'confidence': 0.92, 'end': 25780, 'start': 25180}, {'text': 'with', 'confidence': 1.0, 'end': 25960, 'start': 25720}, {'text': 'comfortable', 'confidence': 0.94, 'end': 29090, 'start': 28090}, {'text': 'to', 'confidence': 0.84, 'end': 29840, 'start': 29180}, {'text': 'work', 'confidence': 0.95, 'end': 30050, 'start': 29780}, {'text': 'with', 'confidence': 0.98, 'end': 30290, 'start': 30020}, {'text': 'the', 'confidence': 0.69, 'end': 30440, 'start': 30230}, {'text': 'database', 'confidence': 0.98, 'end': 30860, 'start': 30380}, {'text': 'instead', 'confidence': 1.0, 'end': 32780, 'start': 31780}, {'text': 'of', 'confidence': 0.98, 'end': 32900, 'start': 32720}, {'text': 'writing', 'confidence': 0.87, 'end': 33320, 'start': 32870}, {'text': 'sequel', 'confidence': 0.88, 'end': 33860, 'start': 33290}, {'text': 'statements', 'confidence': 0.95, 'end': 34310, 'start': 33800}, {'text': 'or', 'confidence': 0.9, 'end': 34460, 'start': 34250}, {'text': 'short', 'confidence': 0.9, 'end': 34790, 'start': 34430}, {'text': 'procedures.', 'confidence': 0.98, 'end': 35270, 'start': 34760}], 'format_text': True, 'webhook_url': None, 'punctuate': True, 'utterances': None, 'audio_duration': 36.288, 'auto_highlights': False, 'word_boost': [], +'dual_channel': None, 'audio_start_from': None} + + +An object relational mapper is a code library that automates the transfer of data stored in a relational database tables into objects that are more commonly used in application. Code or MS provide a high level abstraction upon a relational database that allows the developer to write Python code. Instead of sequel to create read update and delete data and schemas in their database developers can use the programming language that they are comfortable with comfortable to work with the database instead of writing sequel statements or short procedures. +``` + +That's a lot of output. The first part contains the results of the +transcription and the confidence in the accuracy of each word transcribed. +The second part is just the plain text output from the transcription. + +You can take this now take this base code and add it to any application +that needs high quality text-to-speech transcription. If the results +aren't quite good enough for you yet, check out this tutorial on +[boosting accuracy for keywords or phrases](https://docs.assemblyai.com/guides/boosting-accuracy-for-keywords-or-phrases). + + +## Additional resources +We just finished building a highly accurate transcription application for recordings. + +Next, try out some of these other related [Django](/django.html) tutorials: + +* [Using Sentry to Handle Python Exceptions in Django Projects](/blog/sentry-handle-exceptions-django-projects.html) +* [Tracking Daily User Data in Django with django-user-visit](/blog/track-daily-user-data-django-user-visit.html) +* [How to Quickly Use Bootstrap 4 in a Django Template with a CDN](/blog/bootstrap-4-django-template.html) + +Questions? Let me know via +[a GitHub issue ticket on the Full Stack Python repository](https://github.com/mattmakai/fullstackpython.com/issues), +on Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). +See something wrong with this post? Fork +[this page's source on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/210105-django-accurate-twilio-voice-transcriptions.markdown) +and submit a pull request. + diff --git a/content/posts/210422-monitor-python-aws-lambda-sentry.markdown b/content/posts/210422-monitor-python-aws-lambda-sentry.markdown new file mode 100644 index 000000000..00d3e4cba --- /dev/null +++ b/content/posts/210422-monitor-python-aws-lambda-sentry.markdown @@ -0,0 +1,333 @@ +title: How to Monitor Python Functions on AWS Lambda with Sentry +slug: monitor-python-functions-aws-lambda-sentry +meta: Learn how to monitor your Python 3 functions on AWS Lambda using Sentry. +category: post +date: 2021-04-22 +modified: 2021-04-23 +newsletter: False +headerimage: /img/headers/python-lambda-sentry.jpg +headeralt: The Python, AWS Lambda and Sentry logos are copyright their respective owners. + + +[Amazon Web Services (AWS) Lambda](/aws-lambda.html) is a usage-based +compute service that can run [Python 3](/why-use-python.html) code. Errors +can happen in any environment you are running your application in, so +it is necessary to have reliable [monitoring](/monitoring.html) in place +to have visibility when a problem occurs. + +In this post we will install and configure +[Sentry](https://sentry.io/welcome/)'s application monitoring +service that works specifically for code running on AWS Lambda. + + +## Application Dependencies +A local [development environment](/development-environments.html) is not +required to follow this tutorial because all of the coding and configuration +can happen in a web browser through the +[AWS Console](https://console.aws.amazon.com/console/). + +The example code can be copy and pasted from this blog post or you +can access it on GitHub under the +[Full Stack Python blog-post-examples](https://github.com/fullstackpython/blog-code-examples) +repository within the +[monitor-python-aws-lambda-sentry directory](https://github.com/fullstackpython/blog-code-examples/tree/master/monitor-python-aws-lambda-sentry). + + +## Accessing the AWS Lambda Service +[Sign into your existing AWS account](https://aws.amazon.com/console) +or sign up for a [new account](https://aws.amazon.com/). Lambda +gives you the first 1 million requests for free so that you can execute +basic applications without no or low cost. + +The AWS Lambda landing page. + +When you log into your account, use the search box to enter +"lambda" and select "Lambda" when it appears to get to the right +page. + +Use the search bar to find AWS Lambda. + +If you have already used Lambda before, you will see your existing Lambda +functions in a searchable table. We're going to create a new function so +click the "Create function" button. + +Click the create function button. + +The create function page will give you several options for starting a new +Lambda function. + +The create function details page. + +Click the "Browse Serverless App Repository" selection box, then choose +the "hello-world-python3" starter app from within the +"Public applications" section. + +The create function details page. + +The hello-world-python3 starter app details page should look something +like the following screen: + +Hello world Python3 example app and Lambda function. + +Fill in some example text such as "test" under `IdentityNameParameter` +and click the "Deploy" button: + +Click the deploy button to use the starter app. + +The function will now be deployed. As soon as it is ready we can +customize it and test it out before adding Sentry to capture any errors +that occur during execution. + + +## Testing the starter Python app +Go back to the Lambda functions main page and select your new deployed +starter app from the list. + +List of AWS Lambda functions you have created. + +Find the orange "Test" button with a down arrow next to it like you +see in the image below, and then click the down arrow. Select +"Configure Test Event". + +Configure the test event. + +Fill in the Event name as "FirstTest" or something similar, then +press the "Create" button at the bottom of the modal window. + +Click the "Test" button and it will run the Lambda function with +the parameters from that new test event. You should see something +like the following output: + +```python +Response +"value1" + +Function Logs +START RequestId: 62fa2f25-669c-47b7-b4e7-47353b0bd914 Version: $LATEST +value1 = value1 +value2 = value2 +value3 = value3 +END RequestId: 62fa2f25-669c-47b7-b4e7-47353b0bd914 +REPORT RequestId: 62fa2f25-669c-47b7-b4e7-47353b0bd914 Duration: 0.30 ms Billed Duration: 1 ms Memory Size: 128 MB Max Memory Used: 43 MB Init Duration: 1.34 ms + +Request ID +62fa2f25-669c-47b7-b4e7-47353b0bd914 +``` + +That means the test case was successful, but what happens even if there +is a straightforward mistake in the code, such as trying to access an +undeclared variable? + +Go into the code editor and you should see the starter code like this: + +Code editor within AWS Lambda. + +Update the code with the new highlighted line, which tries to access +a fourth variable, which does not exist in the test configuration +we try to run it with. + +```python +import json + +print('Loading function') + + +def lambda_handler(event, context): + #print("Received event: " + json.dumps(event, indent=2)) + print("value1 = " + event['key1']) + print("value2 = " + event['key2']) + print("value3 = " + event['key3']) +~~ print("value4 = " + event['key4']) + return event['key1'] # Echo back the first key value + #raise Exception('Something went wrong') +``` + +After adding that one new line of code, hit the "Deploy" button, +then the "Test" button. You should see some error output: + +``` +Response +{ + "errorMessage": "'key4'", + "errorType": "KeyError", + "stackTrace": [ + [ + "/var/task/lambda_function.py", + 11, + "lambda_handler", + "print(\"value4 = \" + event['key4'])" + ] + ] +} + +Function Logs +START RequestId: a4e956bd-cce4-403e-b5e7-e95bc3ffa2cb Version: $LATEST +value1 = value1 +value2 = value2 +value3 = value3 +'key4': KeyError +Traceback (most recent call last): + File "/var/task/lambda_function.py", line 11, in lambda_handler + print("value4 = " + event['key4']) +KeyError: 'key4' + +END RequestId: a4e956bd-cce4-403e-b5e7-e95bc3ffa2cb +REPORT RequestId: a4e956bd-cce4-403e-b5e7-e95bc3ffa2cb Duration: 0.81 ms Billed Duration: 1 ms Memory Size: 128 MB Max Memory Used: 43 MB Init Duration: 1.61 ms + +Request ID +a4e956bd-cce4-403e-b5e7-e95bc3ffa2cb +``` + +It is obvious when we are working in the Console that an error just +occurred. However, in most cases an error will happen sporadically +which is why we need a monitoring system in place to catch and report +on those exceptions. + + +## AWS Lambda function monitoring with Sentry +The easiest way to add Sentry to Lambda for this application +is to configure an +[AWS Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) +with the necessary dependency for Sentry. Sentry has concise +[documentation on addin gvia Lambda Layers](https://docs.sentry.io/platforms/python/guides/aws-lambda/layer/) +so we will walk through that way to configure it and test it +out. + +First, scroll down to the "Layers" section while in your Lambda +function configuration. Click the "Add a layer" button": + +Add Lambda layer. + +In the "Add layer" screen, select the "Specify an ARN" option. + +Select Specify ARN in the Add Layer screen. + +Now to specify the Amazon Resource Name (ARN), we need to use +the Sentry documentation to get the right configuration string. + +US-East-1 is the oldest and most commonly-used region so I'll +use that here in this tutorial but you should check which one +you are in if you are not certain. + +Select the AWS for the ARN string. + +Copy that value into the Lambda Layer configuration, like this: + +Select the AWS for the ARN string. + +Then press the "Add" button. Now you have the Sentry dependency +in your environment so code that relies upon that library can be +used in the Lambda function. + +Next we need to go into the Sentry dashboard to create a project, +get our unique identifer, and connect it to our Lambda function. + +Sentry can be [self-hosted](https://github.com/getsentry/onpremise) or +used as a cloud service through [Sentry.io](https://sentry.io). We will +use the cloud hosted version because it is quicker than +setting up your own server as well as free for smaller projects. + +Go to [Sentry.io's homepage](https://sentry.io). + +Sentry.io homepage where you can sign up for a free account. + +Sign into your account or sign up for a new free account. You will be at +the main account dashboard after logging in or completing the Sentry sign +up process. + +There are no errors logged on our account dashboard yet, which is as +expected because we have not yet connected our account to our Lambda +function. + +Click "Projects" on the left navigation bar, then "Create Project" +in the top right corner. + +Under "Choose a Platform", select "Serverless" and then "AWS Lambda (Python)" +as shown below: + +Choose AWS Lambda (Python) under the platform options. + +Decide under what criteria it should send error information out of +Lambda. For this tutorial, we will have it send every exception. +Then click the "Create Project." button. + +You can have Sentry handle the instrumentation automatically but +we will handle it manually for our function. On the next screen, Sentry +will provide you with your unique DSN string, which we will need for +our function. + +Copy the Sentry DSN string so we can export it as an environment variable. + +Typically you will want to +[use environment variables on AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html) +to store and access values like your Sentry key. + +Copy the contents of the Sentry DSN string, and go into the Lambda console +to create a new environment variable. To do that, click the "Configuration" +tab within Lambda like you see here: + +Click the Lambda Configuration tab. + +Then click "Edit" and add a new environment variable with the key of `SENTRY_DSN` +and the value of the DSN string that you copied from the Sentry screen. + +Add the environment variable in AWS Lambda. + +Click the "Save" button and go back to your Lambda function code. + +Update your Lambda function with the following highlighted new lines of code +to send errors to Sentry. + +```python +import json +~~import os +~~import sentry_sdk +~~from sentry_sdk.integrations.aws_lambda import AwsLambdaIntegration + +~~SENTRY_DSN = os.environ.get('SENTRY_DSN') +~~sentry_sdk.init( +~~ dsn=SENTRY_DSN, +~~ integrations=[AwsLambdaIntegration()] +~~) + +print('Loading function') + + +def lambda_handler(event, context): + #print("Received event: " + json.dumps(event, indent=2)) + print("value1 = " + event['key1']) + print("value2 = " + event['key2']) + print("value3 = " + event['key3']) + print("value4 = " + event['key4']) + return event['key1'] # Echo back the first key value + #raise Exception('Something went wrong') +``` + +Click the "Deploy" button and then "Test". The code will throw +an error and when we go back to our Sentry dashboard we will +see it captured and viewable for further inspection. + +AWS Lambda exception in the Sentry dashboard. + +It works! Next you will likely want to tune your exception reporting +criteria to make sure you get alerted to the right number of exceptions +if you do not want to see all of them. + + +## What's Next? +We just wrote and executed a Python 3 function on AWS Lambda then +captured the exception message into the Sentry logs. You can +now continue building out your Python code knowing that when something +goes wrong you will have full visibility on what happened. + +Check out the [AWS Lambda section](/aws-lambda.html) for +more tutorials by other developers. + +Further questions? Contact me on Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). I am also on GitHub with +the username [mattmakai](https://github.com/mattmakai). + +Something wrong with this post? Fork +[this page's source on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/210422-monitor-python-aws-lambda-sentry.markdown) +and submit a pull request. diff --git a/content/posts/210823-performance-monitoring-aws-lambda-sentry.markdown b/content/posts/210823-performance-monitoring-aws-lambda-sentry.markdown new file mode 100644 index 000000000..9ede782ef --- /dev/null +++ b/content/posts/210823-performance-monitoring-aws-lambda-sentry.markdown @@ -0,0 +1,261 @@ +title: Application Performance Monitoring AWS Lambda Functions with Sentry +slug: application-performance-monitoring-aws-lambda-functions-sentry +meta: Learn how to use Sentry Application Performance Monitoring on AWS Lambda. +category: post +date: 2021-08-23 +modified: 2021-08-26 +newsletter: False +headerimage: /img/headers/python-lambda-sentry.jpg +headeralt: The Python, AWS Lambda and Sentry logos are copyright their respective owners. + + +[Amazon Web Services (AWS) Lambda](/aws-lambda.html) is a usage-based +computing infrastructure service that can execute +[Python 3](/why-use-python.html) code. One of the challenges of this +environment is ensuring efficient performance of your Lambda Functions. +Application performance monitoring (APM) is particularly useful in these +situations because you are billed based on how long you use the +resources. + +In this post we will install and configure +[Sentry's APM](https://sentry.io/for/performance/) that works via a +[Lambda layer](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html). +Note that if you are looking for error monitoring rather than performance +monitoring, take a look at +[How to Monitor Python Functions on AWS Lambda with Sentry](/blog/monitor-python-functions-aws-lambda-sentry.html) +rather than following this post. + + +## First steps with AWS Lambda +A local [development environment](/development-environments.html) is not +required to follow this tutorial because all of the coding and configuration +can happen in a web browser through the +[AWS Console](https://console.aws.amazon.com/console/). + +[Sign into your existing AWS account](https://aws.amazon.com/console) +or sign up for a [new account](https://aws.amazon.com/). Lambda +gives you the first 1 million requests for free so that you can execute +basic applications without no or low cost. + +The AWS Lambda landing page. + +When you log into your account, use the search box to enter +"lambda" and select "Lambda" when it appears to get to the right +page. + +Use the search bar to find AWS Lambda. + +If you have already used Lambda before, you will see your existing Lambda +functions in a searchable table. We're going to create a new function so +click the "Create function" button. + +Click the create function button. + +The create function page will give you several options for building a +Lambda function. + +The create function details page. + +Click the "Browse Serverless App Repository" selection box, then choose +the "hello-world-python3" starter app from within the +"Public applications" section. + +The create function details page. + +The hello-world-python3 starter app details page should look something +like the following screen: + +Hello world Python3 example app and Lambda function. + +Fill in some example text such as "test" under `IdentityNameParameter` +and click the "Deploy" button: + +Click the deploy button to use the starter app. + +The function will now be deployed. As soon as it is ready we can +customize it and test it out before adding Sentry to capture any errors +that occur during execution. + +Go back to the Lambda functions main page and select your new deployed +starter app from the list. + +List of AWS Lambda functions you have created. + +Find the orange "Test" button with a down arrow next to it like you +see in the image below, and then click the down arrow. Select +"Configure Test Event". + +Configure the test event. + +Fill in the Event name as "FirstTest" or something similar, then +press the "Create" button at the bottom of the modal window. + +Click the "Test" button and it will run the Lambda function with +the parameters from that new test event. You should see something +like the following output: + +```python +Response +"value1" + +Function Logs +START RequestId: 62fa2f25-669c-47b7-b4e7-47353b0bd914 Version: $LATEST +value1 = value1 +value2 = value2 +value3 = value3 +END RequestId: 62fa2f25-669c-47b7-b4e7-47353b0bd914 +REPORT RequestId: 62fa2f25-669c-47b7-b4e7-47353b0bd914 Duration: 0.30 ms Billed Duration: 1 ms Memory Size: 128 MB Max Memory Used: 43 MB Init Duration: 1.34 ms + +Request ID +62fa2f25-669c-47b7-b4e7-47353b0bd914 +``` + +The code was successfully executed, so let's add Sentry's performance +monitoring and test some code that uses it. + + +## Performance monitoring with Sentry +Go to [Sentry.io's homepage](https://sentry.io). + +Sentry.io homepage where you can sign up for a free account. + +Sign into your account or sign up for a new free account. You will be at +the main account dashboard after logging in or completing the Sentry sign +up process. + +Select "Performance" on the left navigation bar, it will take you to the +performance monitoring page. + +Click the 'performance' button on the left side nav. + +Click "Start Setup" then go back over to AWS Lambda to complete the +steps for adding Sentry's Python layer to your Lambda function. + +The easiest way to add Sentry to Lambda for this application +is to configure an +[AWS Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) +with the necessary dependency for Sentry. Sentry has concise +[documentation on adding via Lambda Layers](https://docs.sentry.io/platforms/python/guides/aws-lambda/layer/) +so we will walk through that way to configure it and test it +out. + +Scroll down to the "Layers" section while in your Lambda +function configuration. Click the "Add a layer" button": + +Add Lambda layer. + +In the "Add layer" screen, select the "Specify an ARN" option. + +Select Specify ARN in the Add Layer screen. + +Now to specify the Amazon Resource Name (ARN), we need to use +the Sentry documentation to get the right configuration string. + +US-East-1 is the oldest and most commonly-used region so I'll +use that here in this tutorial but you should check which one +you are in if you are not certain. + +Select the AWS for the ARN string. + +Copy that value into the Lambda Layer configuration, like this: + +Select the AWS for the ARN string. + +Then press the "Add" button. You now have the Sentry dependency +in your environment so code that relies upon that library can be +used in the Lambda function. + + +## Testing performance monitoring +Let's change our Python code in the Lambda function and test out +the APM agent. + +Make sure you are signed into your Sentry account and go to +[this specific AWS Lambda set up guide](https://docs.sentry.io/platforms/python/guides/aws-lambda/). + +You will see a "DSN string" that we need to set as an environment +variable on AWS Lambda to finish our setup. Copy the string that +matches your project as shown on that page in the highlighted green +section: + +Copy the Sentry DSN string so we can export it as an environment variable. + +We will +[use environment variables on AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html) +to store and access values like this Sentry DSN key. + +Go into the Lambda console to create a new environment variable. To do +that, click the "Configuration" tab within Lambda like you see here: + +Click the Lambda Configuration tab. + +Then click "Edit" and add a new environment variable with the key of `SENTRY_DSN` +and the value of the DSN string that you copied from the Sentry screen. + +Add the environment variable in AWS Lambda. + +Click the "Save" button and go back to your Lambda function's code editor. + +Replace the code in your Lambda function with the following code: + +```python +import json +import os +import sentry_sdk +import time +from sentry_sdk.integrations.aws_lambda import AwsLambdaIntegration +from sentry_sdk import start_transaction + +SENTRY_DSN = os.environ.get('SENTRY_DSN') +sentry_sdk.init( + dsn=SENTRY_DSN, + traces_sample_rate=1.0, + integrations=[AwsLambdaIntegration()] +) + +print('Loading function') + + +def lambda_handler(event, context): + calc = 1000 + + # this is custom instrumentation, see docs: https://bit.ly/2WjT3AY + with start_transaction(op="task", name="big calculation"): + for i in range(1, 1000): + calc = calc * i + + print(calc) + return event['key1'] # Echo back the first key value +``` + +The above code imports the Sentry dependencies, and then runs both +[automatic instrumentation](https://docs.sentry.io/platforms/python/guides/aws-lambda/performance/instrumentation/automatic-instrumentation/) +and [custom instrumentation](https://bit.ly/2WjT3AY) on the +code. Click the "Deploy" button and then "Test". The code will +successfully execute and when we go back to our Sentry performance +monitoring dashboard we will see some initial results, like this +following screenshot. + +APM results shown in the Sentry dashboard. + +Looks good, you have both the default and the specified transaction +performance recordings in the dashboard, and you can toggle between +them (or other transactions you record) through the user interface. + + +## What's Next? +We just wrote and executed a Python 3 function on AWS Lambda that +used the basics of Sentry APM to get some initial performance +monitoring data. + +Check out the [AWS Lambda section](/aws-lambda.html) for +more tutorials by other developers. + +Further questions? Contact me on Twitter +[@fullstackpython](https://twitter.com/fullstackpython) +or [@mattmakai](https://twitter.com/mattmakai). I am also on GitHub with +the username [mattmakai](https://github.com/mattmakai). + +Something wrong with this post? Fork +[this page's source on GitHub](https://github.com/mattmakai/fullstackpython.com/blob/master/content/posts/210823-performance-monitoring-aws-lambda-sentry.markdown) +and submit a pull request. diff --git a/redirects/django-core-exceptions-improperlyconfigured.html b/redirects/django-core-exceptions-improperlyconfigured.html new file mode 100644 index 000000000..2dd308b2d --- /dev/null +++ b/redirects/django-core-exceptions-improperlyconfigured.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/redirects/flask-core-extensions-code-examples.html b/redirects/flask-core-extensions-code-examples.html new file mode 100755 index 000000000..1a439cb87 --- /dev/null +++ b/redirects/flask-core-extensions-code-examples.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/redirects/sqlalchemy-projects-code-examples.html b/redirects/sqlalchemy-projects-code-examples.html new file mode 100755 index 000000000..53b72590e --- /dev/null +++ b/redirects/sqlalchemy-projects-code-examples.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/static/audio/fsp-object-relational-mappers.mp3 b/static/audio/fsp-object-relational-mappers.mp3 new file mode 100644 index 000000000..0259af390 Binary files /dev/null and b/static/audio/fsp-object-relational-mappers.mp3 differ diff --git a/static/img/181008-flask-okta/header.jpg b/static/img/181008-flask-okta/header.jpg index 6da57b010..282152c09 100644 Binary files a/static/img/181008-flask-okta/header.jpg and b/static/img/181008-flask-okta/header.jpg differ diff --git a/static/img/181014-digitalocean-ubuntu/header.jpg b/static/img/181014-digitalocean-ubuntu/header.jpg index 9186be701..b7de487c5 100644 Binary files a/static/img/181014-digitalocean-ubuntu/header.jpg and b/static/img/181014-digitalocean-ubuntu/header.jpg differ diff --git a/static/img/181031-okta-exist-flask/header.jpg b/static/img/181031-okta-exist-flask/header.jpg index 6da57b010..282152c09 100644 Binary files a/static/img/181031-okta-exist-flask/header.jpg and b/static/img/181031-okta-exist-flask/header.jpg differ diff --git a/static/img/191018-python-basic-data-types-strings/header.jpg b/static/img/191018-python-basic-data-types-strings/header.jpg index 7696f44b4..e9874c18f 100644 Binary files a/static/img/191018-python-basic-data-types-strings/header.jpg and b/static/img/191018-python-basic-data-types-strings/header.jpg differ diff --git a/static/img/191115-python-basic-data-types-booleans/header.jpg b/static/img/191115-python-basic-data-types-booleans/header.jpg index f7d4ada94..0a53816e1 100644 Binary files a/static/img/191115-python-basic-data-types-booleans/header.jpg and b/static/img/191115-python-basic-data-types-booleans/header.jpg differ diff --git a/static/img/200328-covid-19-pandas/covid-19-data-download.png b/static/img/200328-covid-19-pandas/covid-19-data-download.png new file mode 100644 index 000000000..1968ae153 Binary files /dev/null and b/static/img/200328-covid-19-pandas/covid-19-data-download.png differ diff --git a/static/img/200328-covid-19-pandas/header.jpg b/static/img/200328-covid-19-pandas/header.jpg new file mode 100644 index 000000000..d5ba041fa Binary files /dev/null and b/static/img/200328-covid-19-pandas/header.jpg differ diff --git a/static/img/200330-pandas-sqlite/covid-19-data-download.jpg b/static/img/200330-pandas-sqlite/covid-19-data-download.jpg new file mode 100644 index 000000000..f187a80b5 Binary files /dev/null and b/static/img/200330-pandas-sqlite/covid-19-data-download.jpg differ diff --git a/static/img/200330-pandas-sqlite/header.jpg b/static/img/200330-pandas-sqlite/header.jpg new file mode 100644 index 000000000..9b6aa9f12 Binary files /dev/null and b/static/img/200330-pandas-sqlite/header.jpg differ diff --git a/static/img/200525-sentry/create-new-project-screen.jpg b/static/img/200525-sentry/create-new-project-screen.jpg new file mode 100644 index 000000000..75310353c Binary files /dev/null and b/static/img/200525-sentry/create-new-project-screen.jpg differ diff --git a/static/img/200525-sentry/create-project.jpg b/static/img/200525-sentry/create-project.jpg new file mode 100644 index 000000000..0e8b3ef17 Binary files /dev/null and b/static/img/200525-sentry/create-project.jpg differ diff --git a/static/img/200525-sentry/detailed-error-report.jpg b/static/img/200525-sentry/detailed-error-report.jpg new file mode 100644 index 000000000..43a7097fe Binary files /dev/null and b/static/img/200525-sentry/detailed-error-report.jpg differ diff --git a/static/img/200525-sentry/exception-in-dashboard.jpg b/static/img/200525-sentry/exception-in-dashboard.jpg new file mode 100644 index 000000000..3a6dd47a3 Binary files /dev/null and b/static/img/200525-sentry/exception-in-dashboard.jpg differ diff --git a/static/img/200525-sentry/header.jpg b/static/img/200525-sentry/header.jpg new file mode 100644 index 000000000..d7e417495 Binary files /dev/null and b/static/img/200525-sentry/header.jpg differ diff --git a/static/img/200525-sentry/python-sentry-quickstart.jpg b/static/img/200525-sentry/python-sentry-quickstart.jpg new file mode 100644 index 000000000..fd1e9cbc0 Binary files /dev/null and b/static/img/200525-sentry/python-sentry-quickstart.jpg differ diff --git a/static/img/200525-sentry/sentry-email.jpg b/static/img/200525-sentry/sentry-email.jpg new file mode 100644 index 000000000..5fd45f8ee Binary files /dev/null and b/static/img/200525-sentry/sentry-email.jpg differ diff --git a/static/img/200525-sentry/sentry-empty-dashboard.jpg b/static/img/200525-sentry/sentry-empty-dashboard.jpg new file mode 100644 index 000000000..347616d94 Binary files /dev/null and b/static/img/200525-sentry/sentry-empty-dashboard.jpg differ diff --git a/static/img/200525-sentry/sentry-homepage.jpg b/static/img/200525-sentry/sentry-homepage.jpg new file mode 100644 index 000000000..0fe92307a Binary files /dev/null and b/static/img/200525-sentry/sentry-homepage.jpg differ diff --git a/static/img/200630-python-flask-sentry/division-success.png b/static/img/200630-python-flask-sentry/division-success.png new file mode 100644 index 000000000..8967c56ee Binary files /dev/null and b/static/img/200630-python-flask-sentry/division-success.png differ diff --git a/static/img/200630-python-flask-sentry/error-details.jpg b/static/img/200630-python-flask-sentry/error-details.jpg new file mode 100644 index 000000000..39e82dcc9 Binary files /dev/null and b/static/img/200630-python-flask-sentry/error-details.jpg differ diff --git a/static/img/200630-python-flask-sentry/internal-server-error.png b/static/img/200630-python-flask-sentry/internal-server-error.png new file mode 100644 index 000000000..5e4edc03f Binary files /dev/null and b/static/img/200630-python-flask-sentry/internal-server-error.png differ diff --git a/static/img/200630-python-flask-sentry/waiting-for-events.jpg b/static/img/200630-python-flask-sentry/waiting-for-events.jpg new file mode 100644 index 000000000..16cd46065 Binary files /dev/null and b/static/img/200630-python-flask-sentry/waiting-for-events.jpg differ diff --git a/static/img/200630-python-flask-sentry/zero-division-error.png b/static/img/200630-python-flask-sentry/zero-division-error.png new file mode 100644 index 000000000..4da400b47 Binary files /dev/null and b/static/img/200630-python-flask-sentry/zero-division-error.png differ diff --git a/static/img/200705-bootstrap-4-django-template/hello-world-bootstrap-style.jpg b/static/img/200705-bootstrap-4-django-template/hello-world-bootstrap-style.jpg new file mode 100644 index 000000000..7a33e97c2 Binary files /dev/null and b/static/img/200705-bootstrap-4-django-template/hello-world-bootstrap-style.jpg differ diff --git a/static/img/200719-django-user-visit/django-admin-dashboard.png b/static/img/200719-django-user-visit/django-admin-dashboard.png new file mode 100644 index 000000000..e958c6ead Binary files /dev/null and b/static/img/200719-django-user-visit/django-admin-dashboard.png differ diff --git a/static/img/200719-django-user-visit/django-admin-django-user-visit.png b/static/img/200719-django-user-visit/django-admin-django-user-visit.png new file mode 100644 index 000000000..3c92961a9 Binary files /dev/null and b/static/img/200719-django-user-visit/django-admin-django-user-visit.png differ diff --git a/static/img/200719-django-user-visit/django-admin-login.png b/static/img/200719-django-user-visit/django-admin-login.png new file mode 100644 index 000000000..b117dcb42 Binary files /dev/null and b/static/img/200719-django-user-visit/django-admin-login.png differ diff --git a/static/img/200719-django-user-visit/django-success.png b/static/img/200719-django-user-visit/django-success.png new file mode 100644 index 000000000..fa2d54c5d Binary files /dev/null and b/static/img/200719-django-user-visit/django-success.png differ diff --git a/static/img/200719-django-user-visit/django-user-visit-details.png b/static/img/200719-django-user-visit/django-user-visit-details.png new file mode 100644 index 000000000..2055153c5 Binary files /dev/null and b/static/img/200719-django-user-visit/django-user-visit-details.png differ diff --git a/static/img/200719-django-user-visit/user-visit-record.png b/static/img/200719-django-user-visit/user-visit-record.png new file mode 100644 index 000000000..21373c410 Binary files /dev/null and b/static/img/200719-django-user-visit/user-visit-record.png differ diff --git a/static/img/200721-django-material-admin/django-admin-login-material.jpg b/static/img/200721-django-material-admin/django-admin-login-material.jpg new file mode 100644 index 000000000..ca68484b4 Binary files /dev/null and b/static/img/200721-django-material-admin/django-admin-login-material.jpg differ diff --git a/static/img/200809-transcription-assemblyai/assemblyai-dashboard.png b/static/img/200809-transcription-assemblyai/assemblyai-dashboard.png new file mode 100644 index 000000000..509b1af75 Binary files /dev/null and b/static/img/200809-transcription-assemblyai/assemblyai-dashboard.png differ diff --git a/static/img/200823-django-sentry/division-by-zero-exception.jpg b/static/img/200823-django-sentry/division-by-zero-exception.jpg new file mode 100644 index 000000000..a3fe1a333 Binary files /dev/null and b/static/img/200823-django-sentry/division-by-zero-exception.jpg differ diff --git a/static/img/200823-django-sentry/exception-thrown-debug-page.jpg b/static/img/200823-django-sentry/exception-thrown-debug-page.jpg new file mode 100644 index 000000000..68ba1a888 Binary files /dev/null and b/static/img/200823-django-sentry/exception-thrown-debug-page.jpg differ diff --git a/static/img/200823-django-sentry/sentry-dashboard.jpg b/static/img/200823-django-sentry/sentry-dashboard.jpg new file mode 100644 index 000000000..49a59ff31 Binary files /dev/null and b/static/img/200823-django-sentry/sentry-dashboard.jpg differ diff --git a/static/img/201009-twilio-flask-assemblyai/call-recording-url.png b/static/img/201009-twilio-flask-assemblyai/call-recording-url.png new file mode 100644 index 000000000..e2ee688f3 Binary files /dev/null and b/static/img/201009-twilio-flask-assemblyai/call-recording-url.png differ diff --git a/static/img/201009-twilio-flask-assemblyai/dial-call-sid.png b/static/img/201009-twilio-flask-assemblyai/dial-call-sid.png new file mode 100644 index 000000000..a7b527517 Binary files /dev/null and b/static/img/201009-twilio-flask-assemblyai/dial-call-sid.png differ diff --git a/static/img/201009-twilio-flask-assemblyai/ngrok.jpg b/static/img/201009-twilio-flask-assemblyai/ngrok.jpg new file mode 100644 index 000000000..253ed6bb7 Binary files /dev/null and b/static/img/201009-twilio-flask-assemblyai/ngrok.jpg differ diff --git a/static/img/201009-twilio-flask-assemblyai/twilio-console.png b/static/img/201009-twilio-flask-assemblyai/twilio-console.png new file mode 100644 index 000000000..7f0a3a66a Binary files /dev/null and b/static/img/201009-twilio-flask-assemblyai/twilio-console.png differ diff --git a/static/img/210105-django-assemblyai/assemblyai-dashboard.png b/static/img/210105-django-assemblyai/assemblyai-dashboard.png new file mode 100644 index 000000000..509b1af75 Binary files /dev/null and b/static/img/210105-django-assemblyai/assemblyai-dashboard.png differ diff --git a/static/img/210105-django-assemblyai/call-recording-url.png b/static/img/210105-django-assemblyai/call-recording-url.png new file mode 100644 index 000000000..fdf8d4bc4 Binary files /dev/null and b/static/img/210105-django-assemblyai/call-recording-url.png differ diff --git a/static/img/210105-django-assemblyai/dial-call-sid.png b/static/img/210105-django-assemblyai/dial-call-sid.png new file mode 100644 index 000000000..a79dacfb9 Binary files /dev/null and b/static/img/210105-django-assemblyai/dial-call-sid.png differ diff --git a/static/img/210105-django-assemblyai/ngrok.jpg b/static/img/210105-django-assemblyai/ngrok.jpg new file mode 100644 index 000000000..a56e5f21b Binary files /dev/null and b/static/img/210105-django-assemblyai/ngrok.jpg differ diff --git a/static/img/210105-django-assemblyai/twilio-console.png b/static/img/210105-django-assemblyai/twilio-console.png new file mode 100644 index 000000000..7f0a3a66a Binary files /dev/null and b/static/img/210105-django-assemblyai/twilio-console.png differ diff --git a/static/img/210406-python-sentry-aws-lambda/add-env-var.jpg b/static/img/210406-python-sentry-aws-lambda/add-env-var.jpg new file mode 100644 index 000000000..e1f45463d Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/add-env-var.jpg differ diff --git a/static/img/210406-python-sentry-aws-lambda/add-lambda-layer.png b/static/img/210406-python-sentry-aws-lambda/add-lambda-layer.png new file mode 100644 index 000000000..a5eb7c671 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/add-lambda-layer.png differ diff --git a/static/img/210406-python-sentry-aws-lambda/add-layer-specify-arn.jpg b/static/img/210406-python-sentry-aws-lambda/add-layer-specify-arn.jpg new file mode 100644 index 000000000..b97942149 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/add-layer-specify-arn.jpg differ diff --git a/static/img/210406-python-sentry-aws-lambda/arn-region.png b/static/img/210406-python-sentry-aws-lambda/arn-region.png new file mode 100644 index 000000000..c44697a65 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/arn-region.png differ diff --git a/static/img/210406-python-sentry-aws-lambda/aws-lambda-configuration.jpg b/static/img/210406-python-sentry-aws-lambda/aws-lambda-configuration.jpg new file mode 100644 index 000000000..4f5bb0e05 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/aws-lambda-configuration.jpg differ diff --git a/static/img/210406-python-sentry-aws-lambda/aws-lambda-landing.jpg b/static/img/210406-python-sentry-aws-lambda/aws-lambda-landing.jpg new file mode 100644 index 000000000..799013c14 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/aws-lambda-landing.jpg differ diff --git a/static/img/210406-python-sentry-aws-lambda/aws-lambda-python.jpg b/static/img/210406-python-sentry-aws-lambda/aws-lambda-python.jpg new file mode 100644 index 000000000..e3ba26649 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/aws-lambda-python.jpg differ diff --git a/static/img/210406-python-sentry-aws-lambda/configure-test.jpg b/static/img/210406-python-sentry-aws-lambda/configure-test.jpg new file mode 100644 index 000000000..0896d8e30 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/configure-test.jpg differ diff --git a/static/img/210406-python-sentry-aws-lambda/create-function-detail.png b/static/img/210406-python-sentry-aws-lambda/create-function-detail.png new file mode 100644 index 000000000..7e4c77748 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/create-function-detail.png differ diff --git a/static/img/210406-python-sentry-aws-lambda/create-function.png b/static/img/210406-python-sentry-aws-lambda/create-function.png new file mode 100644 index 000000000..33706be60 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/create-function.png differ diff --git a/static/img/210406-python-sentry-aws-lambda/deploy-starter-app.png b/static/img/210406-python-sentry-aws-lambda/deploy-starter-app.png new file mode 100644 index 000000000..4abdfe380 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/deploy-starter-app.png differ diff --git a/static/img/210406-python-sentry-aws-lambda/functions-list.jpg b/static/img/210406-python-sentry-aws-lambda/functions-list.jpg new file mode 100644 index 000000000..9229b338e Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/functions-list.jpg differ diff --git a/static/img/210406-python-sentry-aws-lambda/hello-world-python3.png b/static/img/210406-python-sentry-aws-lambda/hello-world-python3.png new file mode 100644 index 000000000..f8a9a81fa Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/hello-world-python3.png differ diff --git a/static/img/210406-python-sentry-aws-lambda/lambda-code-editor.jpg b/static/img/210406-python-sentry-aws-lambda/lambda-code-editor.jpg new file mode 100644 index 000000000..4d46f93c7 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/lambda-code-editor.jpg differ diff --git a/static/img/210406-python-sentry-aws-lambda/lambda-search-bar.png b/static/img/210406-python-sentry-aws-lambda/lambda-search-bar.png new file mode 100644 index 000000000..8388871f3 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/lambda-search-bar.png differ diff --git a/static/img/210406-python-sentry-aws-lambda/layer-with-arn.png b/static/img/210406-python-sentry-aws-lambda/layer-with-arn.png new file mode 100644 index 000000000..70033365b Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/layer-with-arn.png differ diff --git a/static/img/210406-python-sentry-aws-lambda/sentry-dsn-string.jpg b/static/img/210406-python-sentry-aws-lambda/sentry-dsn-string.jpg new file mode 100644 index 000000000..69a340fb8 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/sentry-dsn-string.jpg differ diff --git a/static/img/210406-python-sentry-aws-lambda/sentry-error-dashboard.jpg b/static/img/210406-python-sentry-aws-lambda/sentry-error-dashboard.jpg new file mode 100644 index 000000000..4fd7def93 Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/sentry-error-dashboard.jpg differ diff --git a/static/img/210406-python-sentry-aws-lambda/sentry-homepage.jpg b/static/img/210406-python-sentry-aws-lambda/sentry-homepage.jpg new file mode 100644 index 000000000..0fe92307a Binary files /dev/null and b/static/img/210406-python-sentry-aws-lambda/sentry-homepage.jpg differ diff --git a/static/img/210823-sentry-apm-lambda/arn-region.png b/static/img/210823-sentry-apm-lambda/arn-region.png new file mode 100644 index 000000000..4bca3e021 Binary files /dev/null and b/static/img/210823-sentry-apm-lambda/arn-region.png differ diff --git a/static/img/210823-sentry-apm-lambda/layer-with-arn.png b/static/img/210823-sentry-apm-lambda/layer-with-arn.png new file mode 100644 index 000000000..577cbba74 Binary files /dev/null and b/static/img/210823-sentry-apm-lambda/layer-with-arn.png differ diff --git a/static/img/210823-sentry-apm-lambda/performance-results.jpg b/static/img/210823-sentry-apm-lambda/performance-results.jpg new file mode 100644 index 000000000..0e9d3f96d Binary files /dev/null and b/static/img/210823-sentry-apm-lambda/performance-results.jpg differ diff --git a/static/img/210823-sentry-apm-lambda/performance.jpg b/static/img/210823-sentry-apm-lambda/performance.jpg new file mode 100644 index 000000000..7871121d7 Binary files /dev/null and b/static/img/210823-sentry-apm-lambda/performance.jpg differ diff --git a/static/img/210823-sentry-apm-lambda/sentry-dsn-string.png b/static/img/210823-sentry-apm-lambda/sentry-dsn-string.png new file mode 100644 index 000000000..873e68480 Binary files /dev/null and b/static/img/210823-sentry-apm-lambda/sentry-dsn-string.png differ diff --git a/static/img/fsp-fav.png b/static/img/fsp-fav.png index 28a9f6cdb..3a2f75910 100644 Binary files a/static/img/fsp-fav.png and b/static/img/fsp-fav.png differ diff --git a/static/img/headers/django-assemblyai.jpg b/static/img/headers/django-assemblyai.jpg new file mode 100644 index 000000000..585068043 Binary files /dev/null and b/static/img/headers/django-assemblyai.jpg differ diff --git a/static/img/headers/django-bootstrap.jpg b/static/img/headers/django-bootstrap.jpg new file mode 100644 index 000000000..ac7bffe14 Binary files /dev/null and b/static/img/headers/django-bootstrap.jpg differ diff --git a/static/img/headers/django-markdown.jpg b/static/img/headers/django-markdown.jpg new file mode 100644 index 000000000..9a690ccf9 Binary files /dev/null and b/static/img/headers/django-markdown.jpg differ diff --git a/static/img/headers/django-materialize.jpg b/static/img/headers/django-materialize.jpg new file mode 100644 index 000000000..c96ce0740 Binary files /dev/null and b/static/img/headers/django-materialize.jpg differ diff --git a/static/img/headers/django-sentry.jpg b/static/img/headers/django-sentry.jpg new file mode 100644 index 000000000..2256bb885 Binary files /dev/null and b/static/img/headers/django-sentry.jpg differ diff --git a/static/img/headers/django.jpg b/static/img/headers/django.jpg new file mode 100644 index 000000000..440a1fadd Binary files /dev/null and b/static/img/headers/django.jpg differ diff --git a/static/img/headers/flask-sentry.jpg b/static/img/headers/flask-sentry.jpg new file mode 100644 index 000000000..cd661161d Binary files /dev/null and b/static/img/headers/flask-sentry.jpg differ diff --git a/static/img/headers/python-assemblyai.jpg b/static/img/headers/python-assemblyai.jpg new file mode 100644 index 000000000..41945eec6 Binary files /dev/null and b/static/img/headers/python-assemblyai.jpg differ diff --git a/static/img/headers/python-flask-sentry.jpg b/static/img/headers/python-flask-sentry.jpg new file mode 100644 index 000000000..2ca81cd2d Binary files /dev/null and b/static/img/headers/python-flask-sentry.jpg differ diff --git a/static/img/headers/python-lambda-sentry.jpg b/static/img/headers/python-lambda-sentry.jpg new file mode 100644 index 000000000..18f0d40db Binary files /dev/null and b/static/img/headers/python-lambda-sentry.jpg differ diff --git a/static/img/logos/assemblyai-white-bg.png b/static/img/logos/assemblyai-white-bg.png new file mode 100644 index 000000000..319d09ede Binary files /dev/null and b/static/img/logos/assemblyai-white-bg.png differ diff --git a/static/img/logos/assemblyai-white-logo.png b/static/img/logos/assemblyai-white-logo.png new file mode 100644 index 000000000..e22e27431 Binary files /dev/null and b/static/img/logos/assemblyai-white-logo.png differ diff --git a/static/img/logos/assemblyai.jpg b/static/img/logos/assemblyai.jpg new file mode 100644 index 000000000..1c6b3cda8 Binary files /dev/null and b/static/img/logos/assemblyai.jpg differ diff --git a/static/img/logos/bodywork.jpg b/static/img/logos/bodywork.jpg new file mode 100644 index 000000000..821b77ebb Binary files /dev/null and b/static/img/logos/bodywork.jpg differ diff --git a/static/img/logos/cloudflare.png b/static/img/logos/cloudflare.png new file mode 100644 index 000000000..b6a18d47e Binary files /dev/null and b/static/img/logos/cloudflare.png differ diff --git a/static/img/logos/grafana.jpg b/static/img/logos/grafana.jpg new file mode 100644 index 000000000..d1922fa66 Binary files /dev/null and b/static/img/logos/grafana.jpg differ diff --git a/static/img/logos/openai.jpg b/static/img/logos/openai.jpg new file mode 100644 index 000000000..fd10acec4 Binary files /dev/null and b/static/img/logos/openai.jpg differ diff --git a/static/img/logos/oracle.jpg b/static/img/logos/oracle.jpg new file mode 100644 index 000000000..6e8fec361 Binary files /dev/null and b/static/img/logos/oracle.jpg differ diff --git a/static/img/logos/sentry-light.png b/static/img/logos/sentry-light.png index 37494b19f..6d9745061 100644 Binary files a/static/img/logos/sentry-light.png and b/static/img/logos/sentry-light.png differ diff --git a/static/img/logos/webrtc-wide.png b/static/img/logos/webrtc-wide.png new file mode 100644 index 000000000..050cc822c Binary files /dev/null and b/static/img/logos/webrtc-wide.png differ diff --git a/static/img/visuals/cx-oracle.jpg b/static/img/visuals/cx-oracle.jpg new file mode 100644 index 000000000..878e7d285 Binary files /dev/null and b/static/img/visuals/cx-oracle.jpg differ diff --git a/static/img/visuals/first-step.jpg b/static/img/visuals/first-step.jpg new file mode 100644 index 000000000..0158d131f Binary files /dev/null and b/static/img/visuals/first-step.jpg differ diff --git a/static/img/visuals/oracle-orm-examples.jpg b/static/img/visuals/oracle-orm-examples.jpg new file mode 100644 index 000000000..adae67764 Binary files /dev/null and b/static/img/visuals/oracle-orm-examples.jpg differ diff --git a/theme/static/css/base.css b/theme/static/css/base.css index 58c38b7cd..1afe4c68e 100644 --- a/theme/static/css/base.css +++ b/theme/static/css/base.css @@ -59,7 +59,7 @@ img.shot{width:100%;margin:6px 0 6px 0} } @page { @top {text-align:right;font-size:9pt; - content:"Full Stack Python: July 2019 Edition"} + content:"Full Stack Python: 2020 Supporter's Edition"} @bottom { text-align: right; font-size: 9pt; content: counter(page) } margin: 0.9in; size: A4; diff --git a/theme/templates/article.html b/theme/templates/article.html index 4fcea5f1c..1b2932f1e 100644 --- a/theme/templates/article.html +++ b/theme/templates/article.html @@ -25,16 +25,16 @@ {% if article %}
    -

    {{ article.title }}

    +

    {{ article.title }}

    {% if article.modified != article.date %} Post updated by - {% if article.author %}{{ article.author }}{% else %}Matt Makai{% endif %} + {% if article.author == "Matt Makai" %}Matt Makai{% else %}{{ article.author }}{% endif %} on {{ article.modified.strftime('%B %d, %Y') }}. Originally posted on {{ article.date.strftime('%B %d, %Y') }}. {% else %} - Posted by - {% if article.author %}{{ article.author }}{% else %}Matt Makai{% endif %} + Posted by + {% if article.author == "Matt Makai" %}Matt Makai{% else %}{{ article.author }}{% endif %} on {{ article.date.strftime('%B %d, %Y') }}. {% endif %}
    diff --git a/theme/templates/base.html b/theme/templates/base.html index f477ca1c7..93e3ad132 100644 --- a/theme/templates/base.html +++ b/theme/templates/base.html @@ -17,9 +17,8 @@ {% block content %}{% endblock %}
    {% block lower_banner %}{% endblock %} - + {% block bottom_banner %}{% endblock %} - {% block js %}{% endblock %} diff --git a/theme/templates/blog.html b/theme/templates/blog.html index 8a18cfed2..ed1afb06d 100644 --- a/theme/templates/blog.html +++ b/theme/templates/blog.html @@ -21,16 +21,16 @@

    Blog Tutorials

    {% endif %} -

    {{ a.title }}

    +

    {{ a.title }}

    {% if a.modified != a.date %} Post updated by - {% if a.author %}{{ a.author }}{% else %}Matt Makai{% endif %} + {% if a.author == "Matt Makai" %}Matt Makai{% else %}{{ a.author }}{% endif %} on {{ a.modified.strftime('%B %d, %Y') }}. Originally posted on {{ a.date.strftime('%B %d, %Y') }}. {% else %} - Posted by - {% if a.author %}{{ a.author }}{% else %}Matt Makai{% endif %} + Posted by + {% if a.author == "Matt Makai" %}Matt Makai{% else %}{{ a.author }}{% endif %} on {{ a.date.strftime('%B %d, %Y') }}. {% endif %}
    diff --git a/theme/templates/blog/accurate-twilio-voice-call-recording-transcriptions-assemblyai.html b/theme/templates/blog/accurate-twilio-voice-call-recording-transcriptions-assemblyai.html new file mode 100644 index 000000000..379b4da4b --- /dev/null +++ b/theme/templates/blog/accurate-twilio-voice-call-recording-transcriptions-assemblyai.html @@ -0,0 +1,6 @@ + +Learning Programming +Why use Python? +The Python Programming Language +Python Basic Data Types Tutorial: Strings +APIs diff --git a/theme/templates/blog/application-performance-monitoring-aws-lambda-functions-sentry.html b/theme/templates/blog/application-performance-monitoring-aws-lambda-functions-sentry.html new file mode 100644 index 000000000..e38e97585 --- /dev/null +++ b/theme/templates/blog/application-performance-monitoring-aws-lambda-functions-sentry.html @@ -0,0 +1,7 @@ + +Learning Programming +Web development +AWS Lambda +Sentry +Sentry homepage {% include "blog/external-link.html" %} +Sentry Python Quickstart docs {% include "blog/external-link.html" %} diff --git a/theme/templates/blog/best-resources-developers-learn-finance.html b/theme/templates/blog/best-resources-developers-learn-finance.html new file mode 100644 index 000000000..e71c81893 --- /dev/null +++ b/theme/templates/blog/best-resources-developers-learn-finance.html @@ -0,0 +1,4 @@ +Full Stack Python +Endless Metrics {% include "blog/external-link.html" %} +Money Stuff {% include "blog/external-link.html" %} +Don't Quit Your Day Job {% include "blog/external-link.html" %} diff --git a/theme/templates/blog/bootstrap-4-django-template.html b/theme/templates/blog/bootstrap-4-django-template.html new file mode 100644 index 000000000..ad1d789e0 --- /dev/null +++ b/theme/templates/blog/bootstrap-4-django-template.html @@ -0,0 +1,5 @@ + +Learning Programming +Web development +Django +Bootstrap diff --git a/theme/templates/blog/django-accurate-twilio-voice-transcriptions.html b/theme/templates/blog/django-accurate-twilio-voice-transcriptions.html new file mode 100644 index 000000000..8b9e6fcc6 --- /dev/null +++ b/theme/templates/blog/django-accurate-twilio-voice-transcriptions.html @@ -0,0 +1,5 @@ + +Learning Programming +Web development +Django +APIs diff --git a/theme/templates/blog/export-pandas-dataframes-sqlite-sqlalchemy.html b/theme/templates/blog/export-pandas-dataframes-sqlite-sqlalchemy.html new file mode 100644 index 000000000..4e0f11845 --- /dev/null +++ b/theme/templates/blog/export-pandas-dataframes-sqlite-sqlalchemy.html @@ -0,0 +1,7 @@ +Data +Data analysis +pandas +SQLAlchemy +SQLite +NumPy +Official pandas Docs {% include "blog/external-link.html" %} diff --git a/theme/templates/blog/learn-pandas-basic-commands-explore-covid-19-data.html b/theme/templates/blog/learn-pandas-basic-commands-explore-covid-19-data.html new file mode 100644 index 000000000..67906ace6 --- /dev/null +++ b/theme/templates/blog/learn-pandas-basic-commands-explore-covid-19-data.html @@ -0,0 +1,5 @@ +pandas +Data +NumPy +Data analysis +Official pandas Docs {% include "blog/external-link.html" %} diff --git a/theme/templates/blog/materialize-css-django-material-admin.html b/theme/templates/blog/materialize-css-django-material-admin.html new file mode 100644 index 000000000..c271d5953 --- /dev/null +++ b/theme/templates/blog/materialize-css-django-material-admin.html @@ -0,0 +1,6 @@ + +Learning Programming +Web development +Django +Web design +CSS \ No newline at end of file diff --git a/theme/templates/blog/monitor-python-functions-aws-lambda-sentry.html b/theme/templates/blog/monitor-python-functions-aws-lambda-sentry.html new file mode 100644 index 000000000..e681592c2 --- /dev/null +++ b/theme/templates/blog/monitor-python-functions-aws-lambda-sentry.html @@ -0,0 +1,6 @@ +Learning Programming +Web development +Monitoring +Sentry +Sentry homepage {% include "blog/external-link.html" %} +Sentry Python Quickstart docs {% include "blog/external-link.html" %} diff --git a/theme/templates/blog/render-markdown-django-3-0-django-markdown-view.html b/theme/templates/blog/render-markdown-django-3-0-django-markdown-view.html new file mode 100644 index 000000000..831ec665a --- /dev/null +++ b/theme/templates/blog/render-markdown-django-3-0-django-markdown-view.html @@ -0,0 +1,5 @@ + +Learning Programming +Web development +Django +Markdown diff --git a/theme/templates/blog/report-errors-flask-web-apps-sentry.html b/theme/templates/blog/report-errors-flask-web-apps-sentry.html new file mode 100644 index 000000000..4b3de4a37 --- /dev/null +++ b/theme/templates/blog/report-errors-flask-web-apps-sentry.html @@ -0,0 +1,5 @@ +Learning Programming +Web development +Sentry +Sentry homepage {% include "blog/external-link.html" %} +Sentry Python Quickstart docs {% include "blog/external-link.html" %} diff --git a/theme/templates/blog/report-exceptions-python-scripts-sentry.html b/theme/templates/blog/report-exceptions-python-scripts-sentry.html new file mode 100644 index 000000000..18d48fa0f --- /dev/null +++ b/theme/templates/blog/report-exceptions-python-scripts-sentry.html @@ -0,0 +1,5 @@ +Learning Programming +Monitoring +Sentry +Sentry homepage {% include "blog/external-link.html" %} +Sentry Python Quickstart docs {% include "blog/external-link.html" %} diff --git a/theme/templates/blog/sentry-application-performance-monitor-django.html b/theme/templates/blog/sentry-application-performance-monitor-django.html new file mode 100644 index 000000000..6d581b5ea --- /dev/null +++ b/theme/templates/blog/sentry-application-performance-monitor-django.html @@ -0,0 +1,6 @@ +Learning Programming +Web development +Django +Sentry +Sentry homepage {% include "blog/external-link.html" %} +Sentry Performance Monitoring docs {% include "blog/external-link.html" %} diff --git a/theme/templates/blog/sentry-handle-exceptions-django-projects.html b/theme/templates/blog/sentry-handle-exceptions-django-projects.html new file mode 100644 index 000000000..fc6d946d6 --- /dev/null +++ b/theme/templates/blog/sentry-handle-exceptions-django-projects.html @@ -0,0 +1,7 @@ + +Learning Programming +Web development +Django +Sentry +Sentry homepage {% include "blog/external-link.html" %} +Sentry Python Quickstart docs {% include "blog/external-link.html" %} \ No newline at end of file diff --git a/theme/templates/blog/track-daily-user-data-django-user-visit.html b/theme/templates/blog/track-daily-user-data-django-user-visit.html new file mode 100644 index 000000000..018dcac9c --- /dev/null +++ b/theme/templates/blog/track-daily-user-data-django-user-visit.html @@ -0,0 +1,4 @@ + +Learning Programming +Web development +Django \ No newline at end of file diff --git a/theme/templates/blog/transcribe-recordings-speech-text-assemblyai.html b/theme/templates/blog/transcribe-recordings-speech-text-assemblyai.html new file mode 100644 index 000000000..379b4da4b --- /dev/null +++ b/theme/templates/blog/transcribe-recordings-speech-text-assemblyai.html @@ -0,0 +1,6 @@ + +Learning Programming +Why use Python? +The Python Programming Language +Python Basic Data Types Tutorial: Strings +APIs diff --git a/theme/templates/book-toc.html b/theme/templates/book-toc.html index 2e536802b..7d51ee73c 100644 --- a/theme/templates/book-toc.html +++ b/theme/templates/book-toc.html @@ -19,7 +19,7 @@
  • 2. Development Environments
  • {% endif %} {% if page.slug != "change-log" and page.slug != "page-statuses" and page.slug != "future-directions" %} +

    {{ page.title }}

    {{ page.content }} {% endif %} {% endfor %} diff --git a/theme/templates/examples-extensions-descriptions/django.html b/theme/templates/examples-extensions-descriptions/django.html index a6bef893f..5afcfe281 100644 --- a/theme/templates/examples-extensions-descriptions/django.html +++ b/theme/templates/examples-extensions-descriptions/django.html @@ -1,4 +1,4 @@ -Django is a Python web framework. +Django is a Python web framework. Official Django logo. Trademark Django Software Foundation. diff --git a/theme/templates/examples-extensions-descriptions/flask.html b/theme/templates/examples-extensions-descriptions/flask.html new file mode 100644 index 000000000..9f3b1c5bf --- /dev/null +++ b/theme/templates/examples-extensions-descriptions/flask.html @@ -0,0 +1,14 @@ +Flask is a Python web framework. + +Official Flask logo. Flask Artwork License. + +

    Flask's large ecosystem of extensions make it easier for developers to +build common web app features such as authentication, +relational database access and +APIs even though support is not built into the core Flask library.

    + + +

    Code Examples Sorted by Flask Class and Function

    +

    Specific examples are shown on the following individual pages, +organized by classes and functions provided by Flask, that are frequently +used when building your own web applications.

    diff --git a/theme/templates/examples-extensions-descriptions/pandas.html b/theme/templates/examples-extensions-descriptions/pandas.html new file mode 100644 index 000000000..a032824e3 --- /dev/null +++ b/theme/templates/examples-extensions-descriptions/pandas.html @@ -0,0 +1,12 @@ +pandas is a data analysis library +built in Python. + +pandas data analysis project + +

    pandas can be used in a Python script, a +Jupyter Notebook, or even as +part of a web application.

    + +

    The following open source projects, ordered alphabetically, are +helpful as example code for how to use pandas in your own applications.

    + diff --git a/theme/templates/examples-extensions-descriptions/sqlalchemy.html b/theme/templates/examples-extensions-descriptions/sqlalchemy.html new file mode 100644 index 000000000..dca33b44d --- /dev/null +++ b/theme/templates/examples-extensions-descriptions/sqlalchemy.html @@ -0,0 +1,14 @@ +SQLAlchemy +is a well-regarded database toolkit and +object-relational mapper (ORM) +implementation written in Python. SQLAlchemy provides a generalized +interface for creating and executing database-agnostic code without +needing to write SQL statements. + +SQLAlchemy logo. + + +

    Code Examples Sorted by SQLAlchemy Package

    +

    Specific examples are shown on the following individual pages, +organized by classes and functions provided by SQLAlchemy, that are typically +used when building your own applications.

    diff --git a/theme/templates/index-sidebar.html b/theme/templates/index-sidebar.html index 84b9558ab..ccfb5ad9e 100644 --- a/theme/templates/index-sidebar.html +++ b/theme/templates/index-sidebar.html @@ -1,13 +1,2 @@
    -
    -

    {% for p in pages|sort(attribute='sortorder') %}{% if page and p.slug == page.slug %}{{ p.title }}{% endif %}{% endfor %}{% if not page %}Full Stack Python{% endif %}

    -
    - Full Stack Python is an open book that explains - concepts in plain language. -
    - Read everything online for free or purchase the - Supporter's Edition - for nicely-formatted ebooks. -
    -
    diff --git a/theme/templates/index.html b/theme/templates/index.html index 6272d17ef..3c62f365b 100644 --- a/theme/templates/index.html +++ b/theme/templates/index.html @@ -5,15 +5,15 @@ {% endblock %} -{% block css %}{% endblock %} +{% block css %}{% endblock %} {% block banner %} {% endblock %} {% block content %}
    -
    -

    Build, Deploy and Operate Python Applications

    +
    +

    Learn to Build, Deploy and Operate Python Applications

    You're knee deep in learning Python programming. The syntax is starting to make sense. The first few ahh-ha! moments hit you as you learn to use @@ -30,15 +30,20 @@

    Build, Deploy and Operate Python Applications

    need to create, deploy and operate Python-powered applications.

    -

    This guide branches out on topic because your learning +

    Full Stack Python is an + open source book + that explains technical concepts in plain language. + Read everything online for free or purchase the + Supporter's Edition + for nicely-formatted ebook (PDF, EPUB, MOBI) versions. + This guide branches out on topic because your learning requirements depend on what you're working on. Choose a topic from the links below or view the full table of contents - to see even more subjects you can learn for free on this website. + to see even more subjects you can learn.

    What do you need to learn first?

    - {% include "index-sidebar.html" %}
    diff --git a/theme/templates/nav.html b/theme/templates/nav.html index 529a36676..5b91021c4 100644 --- a/theme/templates/nav.html +++ b/theme/templates/nav.html @@ -1 +1 @@ -
    {% include "subnav.html" %}
    +
    {% include "subnav.html" %}
    diff --git a/theme/templates/page.html b/theme/templates/page.html index 570ae6d6f..19aed5b20 100644 --- a/theme/templates/page.html +++ b/theme/templates/page.html @@ -51,7 +51,27 @@

    {{ page.title }}

    {% include "examples-extensions-descriptions/django.html" %} {% include "code-examples/django.html" %} {% endif %} + {% if page.slug == "flask-code-examples" %} + {% include "examples-extensions-descriptions/flask.html" %} + {% include "code-examples/flask.html" %} + {% endif %} + {% if page.slug == "sqlalchemy-code-examples" %} + {% include "examples-extensions-descriptions/sqlalchemy.html" %} + {% include "code-examples/sqlalchemy.html" %} + {% endif %} + {% if page.slug == "pandas-code-examples" %} + {% include "examples-extensions-descriptions/pandas.html" %} + {% endif %} {{ page.content }} + {% if page.slug == "django" %} + {% include "code-examples/django.html" %} + {% endif %} + {% if page.slug == "flask" %} + {% include "code-examples/flask.html" %} + {% endif %} + {% if page.slug == "sqlalchemy" %} + {% include "code-examples/sqlalchemy.html" %} + {% endif %} {% endif %} {% if page.sortorder[0:2] == "50" %} {% else %} diff --git a/theme/templates/sponsor/assemblyai.html b/theme/templates/sponsor/assemblyai.html new file mode 100644 index 000000000..431a8c567 --- /dev/null +++ b/theme/templates/sponsor/assemblyai.html @@ -0,0 +1,7 @@ +
    +

    Sponsored By

    +
    + AssemblyAI logo +

    The automatic transcription API loved by Python developers.

    +
    +
    diff --git a/theme/templates/sponsor/sentry-assemblyai.html b/theme/templates/sponsor/sentry-assemblyai.html new file mode 100644 index 000000000..a67cdaacf --- /dev/null +++ b/theme/templates/sponsor/sentry-assemblyai.html @@ -0,0 +1,10 @@ +
    +

    Sponsored By

    +
    + Sentry logo +

    Software errors are inevitable. Chaos is not. Try Sentry for free.

    +
    + AssemblyAI logo +

    The most accurate speech-to-text API. Built for Python developers.

    +
    +
    diff --git a/theme/templates/sponsor/sentry.html b/theme/templates/sponsor/sentry.html new file mode 100644 index 000000000..a919be8fe --- /dev/null +++ b/theme/templates/sponsor/sentry.html @@ -0,0 +1,7 @@ +
    +

    Sponsored By

    +
    + Sentry logo +

    Software errors are inevitable. Chaos is not. Try Sentry for free.

    +
    +
    diff --git a/theme/templates/subnav.html b/theme/templates/subnav.html index f62d56cee..f57d81fd8 100644 --- a/theme/templates/subnav.html +++ b/theme/templates/subnav.html @@ -1,10 +1,8 @@ diff --git a/theme/templates/table-of-contents.html b/theme/templates/table-of-contents.html index 927e6086e..912e439e0 100644 --- a/theme/templates/table-of-contents.html +++ b/theme/templates/table-of-contents.html @@ -45,6 +45,8 @@

    \"Full":