From 093670adb07c9f944c30f94dd3e28a7e34a911c0 Mon Sep 17 00:00:00 2001 From: Broadus Jones Date: Mon, 10 Jan 2022 15:41:16 -0600 Subject: [PATCH 1/8] Demo --- .gitignore | 3 ++- hello/views.py | 7 ++++++- requirements.txt | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4875ad398..de2023646 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ venv staticfiles .env db.sqlite3 -getting-started/* \ No newline at end of file +database.ini +getting-started/* diff --git a/hello/views.py b/hello/views.py index c2480724b..58325b62a 100644 --- a/hello/views.py +++ b/hello/views.py @@ -2,11 +2,16 @@ from django.http import HttpResponse from .models import Greeting +import requests + # Create your views here. def index(request): # return HttpResponse('Hello from Python!') - return render(request, "index.html") + # return render(request, "index.html") + r = requests.get('http://httpbin.org/status/418') + print(r.text) + return HttpResponse('
' + r.text + '
') def db(request): diff --git a/requirements.txt b/requirements.txt index 4af6a3765..fb450cffa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ django gunicorn -django-heroku \ No newline at end of file +django-heroku +requests From 3fa9dc5c5a6a595277c7f2c857b6c3221d06bd56 Mon Sep 17 00:00:00 2001 From: Broadus Jones Date: Mon, 10 Jan 2022 16:14:03 -0600 Subject: [PATCH 2/8] set TIMES --- hello/views.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hello/views.py b/hello/views.py index 58325b62a..dc450f0cb 100644 --- a/hello/views.py +++ b/hello/views.py @@ -1,17 +1,22 @@ + from django.shortcuts import render from django.http import HttpResponse from .models import Greeting import requests +import os # Create your views here. def index(request): # return HttpResponse('Hello from Python!') # return render(request, "index.html") - r = requests.get('http://httpbin.org/status/418') - print(r.text) - return HttpResponse('
' + r.text + '
') + # r = requests.get('http://httpbin.org/status/418') + # print(r.text) + # return HttpResponse('
' + r.text + '
') + times = int(os.environ.get('TIMES',3)) + return HttpResponse('Hello! ' * times) + def db(request): From 60a8b1419ae81859266051149b56bf5725df3604 Mon Sep 17 00:00:00 2001 From: Broadus Jones Date: Tue, 11 Jan 2022 11:32:27 -0600 Subject: [PATCH 3/8] reset set TIMES to 5 --- hello/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hello/views.py b/hello/views.py index dc450f0cb..12dc835e2 100644 --- a/hello/views.py +++ b/hello/views.py @@ -14,9 +14,8 @@ def index(request): # r = requests.get('http://httpbin.org/status/418') # print(r.text) # return HttpResponse('
' + r.text + '
') - times = int(os.environ.get('TIMES',3)) + times = int(os.environ.get('TIMES', 3)) return HttpResponse('Hello! ' * times) - def db(request): From 701182b4ab71e61bca5953cacb594d2289737cb6 Mon Sep 17 00:00:00 2001 From: Broadus Jones Date: Tue, 11 Jan 2022 14:16:10 -0600 Subject: [PATCH 4/8] added docs to repo --- .gitignore | 1 + docs/__init__.py | 0 docs/admin.py | 3 + docs/apps.py | 6 ++ docs/migrations/0001_initial.py | 33 ++++++++ ...ic_folder_topic_delete_snippet_and_more.py | 80 ++++++++++++++++++ ...ter_doc_folder_alter_doc_owner_and_more.py | 39 +++++++++ docs/migrations/0004_alter_folder_parent.py | 19 +++++ docs/migrations/0005_alter_folder_owner.py | 20 +++++ ...topic_owner_remove_topic_owner_and_more.py | 38 +++++++++ .../0007_alter_doctopic_unique_together.py | 17 ++++ .../0008_alter_doctopic_unique_together.py | 17 ++++ .../0009_alter_doctopic_unique_together.py | 17 ++++ .../migrations/0010_alter_doctopic_options.py | 17 ++++ docs/migrations/0011_doc_topics.py | 18 ++++ docs/migrations/0012_topic_docs.py | 18 ++++ ...ocument_alter_document_options_and_more.py | 30 +++++++ docs/migrations/__init__.py | 0 docs/models.py | 68 +++++++++++++++ docs/permissions.py | 16 ++++ docs/serializers.py | 49 +++++++++++ docs/tests.py | 3 + docs/urls.py | 83 +++++++++++++++++++ docs/views.py | 82 ++++++++++++++++++ requirements.txt | 1 + 25 files changed, 675 insertions(+) create mode 100644 docs/__init__.py create mode 100644 docs/admin.py create mode 100644 docs/apps.py create mode 100644 docs/migrations/0001_initial.py create mode 100644 docs/migrations/0002_doc_doctopic_folder_topic_delete_snippet_and_more.py create mode 100644 docs/migrations/0003_alter_doc_options_alter_doc_folder_alter_doc_owner_and_more.py create mode 100644 docs/migrations/0004_alter_folder_parent.py create mode 100644 docs/migrations/0005_alter_folder_owner.py create mode 100644 docs/migrations/0006_remove_doctopic_owner_remove_topic_owner_and_more.py create mode 100644 docs/migrations/0007_alter_doctopic_unique_together.py create mode 100644 docs/migrations/0008_alter_doctopic_unique_together.py create mode 100644 docs/migrations/0009_alter_doctopic_unique_together.py create mode 100644 docs/migrations/0010_alter_doctopic_options.py create mode 100644 docs/migrations/0011_doc_topics.py create mode 100644 docs/migrations/0012_topic_docs.py create mode 100644 docs/migrations/0013_rename_doc_document_alter_document_options_and_more.py create mode 100644 docs/migrations/__init__.py create mode 100644 docs/models.py create mode 100644 docs/permissions.py create mode 100644 docs/serializers.py create mode 100644 docs/tests.py create mode 100644 docs/urls.py create mode 100644 docs/views.py diff --git a/.gitignore b/.gitignore index de2023646..ff3c03c11 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ staticfiles .env db.sqlite3 database.ini +database.txt getting-started/* diff --git a/docs/__init__.py b/docs/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docs/admin.py b/docs/admin.py new file mode 100644 index 000000000..8c38f3f3d --- /dev/null +++ b/docs/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/docs/apps.py b/docs/apps.py new file mode 100644 index 000000000..a59399777 --- /dev/null +++ b/docs/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class DocsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'docs' diff --git a/docs/migrations/0001_initial.py b/docs/migrations/0001_initial.py new file mode 100644 index 000000000..02aebcfdd --- /dev/null +++ b/docs/migrations/0001_initial.py @@ -0,0 +1,33 @@ +# Generated by Django 4.0 on 2021-12-28 14:24 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='Snippet', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('title', models.CharField(blank=True, default='', max_length=100)), + ('code', models.TextField()), + ('linenos', models.BooleanField(default=False)), + ('language', models.CharField(choices=[('abap', 'ABAP'), ('abnf', 'ABNF'), ('actionscript', 'ActionScript'), ('actionscript3', 'ActionScript 3'), ('ada', 'Ada'), ('adl', 'ADL'), ('agda', 'Agda'), ('aheui', 'Aheui'), ('alloy', 'Alloy'), ('ambienttalk', 'AmbientTalk'), ('amdgpu', 'AMDGPU'), ('ampl', 'Ampl'), ('ansys', 'ANSYS parametric design language'), ('antlr', 'ANTLR'), ('antlr-actionscript', 'ANTLR With ActionScript Target'), ('antlr-cpp', 'ANTLR With CPP Target'), ('antlr-csharp', 'ANTLR With C# Target'), ('antlr-java', 'ANTLR With Java Target'), ('antlr-objc', 'ANTLR With ObjectiveC Target'), ('antlr-perl', 'ANTLR With Perl Target'), ('antlr-python', 'ANTLR With Python Target'), ('antlr-ruby', 'ANTLR With Ruby Target'), ('apacheconf', 'ApacheConf'), ('apl', 'APL'), ('applescript', 'AppleScript'), ('arduino', 'Arduino'), ('arrow', 'Arrow'), ('asc', 'ASCII armored'), ('aspectj', 'AspectJ'), ('aspx-cs', 'aspx-cs'), ('aspx-vb', 'aspx-vb'), ('asymptote', 'Asymptote'), ('augeas', 'Augeas'), ('autohotkey', 'autohotkey'), ('autoit', 'AutoIt'), ('awk', 'Awk'), ('bare', 'BARE'), ('basemake', 'Base Makefile'), ('bash', 'Bash'), ('batch', 'Batchfile'), ('bbcbasic', 'BBC Basic'), ('bbcode', 'BBCode'), ('bc', 'BC'), ('befunge', 'Befunge'), ('bibtex', 'BibTeX'), ('blitzbasic', 'BlitzBasic'), ('blitzmax', 'BlitzMax'), ('bnf', 'BNF'), ('boa', 'Boa'), ('boo', 'Boo'), ('boogie', 'Boogie'), ('brainfuck', 'Brainfuck'), ('bst', 'BST'), ('bugs', 'BUGS'), ('c', 'C'), ('c-objdump', 'c-objdump'), ('ca65', 'ca65 assembler'), ('cadl', 'cADL'), ('camkes', 'CAmkES'), ('capdl', 'CapDL'), ('capnp', "Cap'n Proto"), ('cbmbas', 'CBM BASIC V2'), ('cddl', 'CDDL'), ('ceylon', 'Ceylon'), ('cfc', 'Coldfusion CFC'), ('cfengine3', 'CFEngine3'), ('cfm', 'Coldfusion HTML'), ('cfs', 'cfstatement'), ('chaiscript', 'ChaiScript'), ('chapel', 'Chapel'), ('charmci', 'Charmci'), ('cheetah', 'Cheetah'), ('cirru', 'Cirru'), ('clay', 'Clay'), ('clean', 'Clean'), ('clojure', 'Clojure'), ('clojurescript', 'ClojureScript'), ('cmake', 'CMake'), ('cobol', 'COBOL'), ('cobolfree', 'COBOLFree'), ('coffeescript', 'CoffeeScript'), ('common-lisp', 'Common Lisp'), ('componentpascal', 'Component Pascal'), ('console', 'Bash Session'), ('coq', 'Coq'), ('cpp', 'C++'), ('cpp-objdump', 'cpp-objdump'), ('cpsa', 'CPSA'), ('cr', 'Crystal'), ('crmsh', 'Crmsh'), ('croc', 'Croc'), ('cryptol', 'Cryptol'), ('csharp', 'C#'), ('csound', 'Csound Orchestra'), ('csound-document', 'Csound Document'), ('csound-score', 'Csound Score'), ('css', 'CSS'), ('css+django', 'CSS+Django/Jinja'), ('css+genshitext', 'CSS+Genshi Text'), ('css+lasso', 'CSS+Lasso'), ('css+mako', 'CSS+Mako'), ('css+mozpreproc', 'CSS+mozpreproc'), ('css+myghty', 'CSS+Myghty'), ('css+php', 'CSS+PHP'), ('css+ruby', 'CSS+Ruby'), ('css+smarty', 'CSS+Smarty'), ('cuda', 'CUDA'), ('cypher', 'Cypher'), ('cython', 'Cython'), ('d', 'D'), ('d-objdump', 'd-objdump'), ('dart', 'Dart'), ('dasm16', 'DASM16'), ('debcontrol', 'Debian Control file'), ('debsources', 'Debian Sourcelist'), ('delphi', 'Delphi'), ('devicetree', 'Devicetree'), ('dg', 'dg'), ('diff', 'Diff'), ('django', 'Django/Jinja'), ('docker', 'Docker'), ('doscon', 'MSDOS Session'), ('dpatch', 'Darcs Patch'), ('dtd', 'DTD'), ('duel', 'Duel'), ('dylan', 'Dylan'), ('dylan-console', 'Dylan session'), ('dylan-lid', 'DylanLID'), ('earl-grey', 'Earl Grey'), ('easytrieve', 'Easytrieve'), ('ebnf', 'EBNF'), ('ec', 'eC'), ('ecl', 'ECL'), ('eiffel', 'Eiffel'), ('elixir', 'Elixir'), ('elm', 'Elm'), ('emacs-lisp', 'EmacsLisp'), ('email', 'E-mail'), ('erb', 'ERB'), ('erl', 'Erlang erl session'), ('erlang', 'Erlang'), ('evoque', 'Evoque'), ('execline', 'execline'), ('extempore', 'xtlang'), ('ezhil', 'Ezhil'), ('factor', 'Factor'), ('fan', 'Fantom'), ('fancy', 'Fancy'), ('felix', 'Felix'), ('fennel', 'Fennel'), ('fish', 'Fish'), ('flatline', 'Flatline'), ('floscript', 'FloScript'), ('forth', 'Forth'), ('fortran', 'Fortran'), ('fortranfixed', 'FortranFixed'), ('foxpro', 'FoxPro'), ('freefem', 'Freefem'), ('fsharp', 'F#'), ('fstar', 'FStar'), ('futhark', 'Futhark'), ('gap', 'GAP'), ('gas', 'GAS'), ('gcode', 'g-code'), ('gdscript', 'GDScript'), ('genshi', 'Genshi'), ('genshitext', 'Genshi Text'), ('gherkin', 'Gherkin'), ('glsl', 'GLSL'), ('gnuplot', 'Gnuplot'), ('go', 'Go'), ('golo', 'Golo'), ('gooddata-cl', 'GoodData-CL'), ('gosu', 'Gosu'), ('graphviz', 'Graphviz'), ('groff', 'Groff'), ('groovy', 'Groovy'), ('gsql', 'GSQL'), ('gst', 'Gosu Template'), ('haml', 'Haml'), ('handlebars', 'Handlebars'), ('haskell', 'Haskell'), ('haxe', 'Haxe'), ('haxeml', 'Hxml'), ('hexdump', 'Hexdump'), ('hlsl', 'HLSL'), ('hsail', 'HSAIL'), ('hspec', 'Hspec'), ('html', 'HTML'), ('html+cheetah', 'HTML+Cheetah'), ('html+django', 'HTML+Django/Jinja'), ('html+evoque', 'HTML+Evoque'), ('html+genshi', 'HTML+Genshi'), ('html+handlebars', 'HTML+Handlebars'), ('html+lasso', 'HTML+Lasso'), ('html+mako', 'HTML+Mako'), ('html+myghty', 'HTML+Myghty'), ('html+ng2', 'HTML + Angular2'), ('html+php', 'HTML+PHP'), ('html+smarty', 'HTML+Smarty'), ('html+twig', 'HTML+Twig'), ('html+velocity', 'HTML+Velocity'), ('http', 'HTTP'), ('hybris', 'Hybris'), ('hylang', 'Hy'), ('i6t', 'Inform 6 template'), ('icon', 'Icon'), ('idl', 'IDL'), ('idris', 'Idris'), ('iex', 'Elixir iex session'), ('igor', 'Igor'), ('inform6', 'Inform 6'), ('inform7', 'Inform 7'), ('ini', 'INI'), ('io', 'Io'), ('ioke', 'Ioke'), ('irc', 'IRC logs'), ('isabelle', 'Isabelle'), ('j', 'J'), ('jags', 'JAGS'), ('jasmin', 'Jasmin'), ('java', 'Java'), ('javascript', 'JavaScript'), ('javascript+cheetah', 'JavaScript+Cheetah'), ('javascript+django', 'JavaScript+Django/Jinja'), ('javascript+lasso', 'JavaScript+Lasso'), ('javascript+mako', 'JavaScript+Mako'), ('javascript+mozpreproc', 'Javascript+mozpreproc'), ('javascript+myghty', 'JavaScript+Myghty'), ('javascript+php', 'JavaScript+PHP'), ('javascript+ruby', 'JavaScript+Ruby'), ('javascript+smarty', 'JavaScript+Smarty'), ('jcl', 'JCL'), ('jlcon', 'Julia console'), ('js+genshitext', 'JavaScript+Genshi Text'), ('jsgf', 'JSGF'), ('jslt', 'JSLT'), ('json', 'JSON'), ('jsonld', 'JSON-LD'), ('jsp', 'Java Server Page'), ('julia', 'Julia'), ('juttle', 'Juttle'), ('kal', 'Kal'), ('kconfig', 'Kconfig'), ('kmsg', 'Kernel log'), ('koka', 'Koka'), ('kotlin', 'Kotlin'), ('kuin', 'Kuin'), ('lasso', 'Lasso'), ('lean', 'Lean'), ('less', 'LessCss'), ('lighttpd', 'Lighttpd configuration file'), ('limbo', 'Limbo'), ('liquid', 'liquid'), ('literate-agda', 'Literate Agda'), ('literate-cryptol', 'Literate Cryptol'), ('literate-haskell', 'Literate Haskell'), ('literate-idris', 'Literate Idris'), ('livescript', 'LiveScript'), ('llvm', 'LLVM'), ('llvm-mir', 'LLVM-MIR'), ('llvm-mir-body', 'LLVM-MIR Body'), ('logos', 'Logos'), ('logtalk', 'Logtalk'), ('lsl', 'LSL'), ('lua', 'Lua'), ('make', 'Makefile'), ('mako', 'Mako'), ('maql', 'MAQL'), ('markdown', 'Markdown'), ('mask', 'Mask'), ('mason', 'Mason'), ('mathematica', 'Mathematica'), ('matlab', 'Matlab'), ('matlabsession', 'Matlab session'), ('meson', 'Meson'), ('mime', 'MIME'), ('minid', 'MiniD'), ('miniscript', 'MiniScript'), ('modelica', 'Modelica'), ('modula2', 'Modula-2'), ('monkey', 'Monkey'), ('monte', 'Monte'), ('moocode', 'MOOCode'), ('moonscript', 'MoonScript'), ('mosel', 'Mosel'), ('mozhashpreproc', 'mozhashpreproc'), ('mozpercentpreproc', 'mozpercentpreproc'), ('mql', 'MQL'), ('mscgen', 'Mscgen'), ('mupad', 'MuPAD'), ('mxml', 'MXML'), ('myghty', 'Myghty'), ('mysql', 'MySQL'), ('nasm', 'NASM'), ('ncl', 'NCL'), ('nemerle', 'Nemerle'), ('nesc', 'nesC'), ('nestedtext', 'NestedText'), ('newlisp', 'NewLisp'), ('newspeak', 'Newspeak'), ('ng2', 'Angular2'), ('nginx', 'Nginx configuration file'), ('nimrod', 'Nimrod'), ('nit', 'Nit'), ('nixos', 'Nix'), ('nodejsrepl', 'Node.js REPL console session'), ('notmuch', 'Notmuch'), ('nsis', 'NSIS'), ('numpy', 'NumPy'), ('nusmv', 'NuSMV'), ('objdump', 'objdump'), ('objdump-nasm', 'objdump-nasm'), ('objective-c', 'Objective-C'), ('objective-c++', 'Objective-C++'), ('objective-j', 'Objective-J'), ('ocaml', 'OCaml'), ('octave', 'Octave'), ('odin', 'ODIN'), ('omg-idl', 'OMG Interface Definition Language'), ('ooc', 'Ooc'), ('opa', 'Opa'), ('openedge', 'OpenEdge ABL'), ('output', 'Text output'), ('pacmanconf', 'PacmanConf'), ('pan', 'Pan'), ('parasail', 'ParaSail'), ('pawn', 'Pawn'), ('peg', 'PEG'), ('perl', 'Perl'), ('perl6', 'Perl6'), ('php', 'PHP'), ('pig', 'Pig'), ('pike', 'Pike'), ('pkgconfig', 'PkgConfig'), ('plpgsql', 'PL/pgSQL'), ('pointless', 'Pointless'), ('pony', 'Pony'), ('postgresql', 'PostgreSQL SQL dialect'), ('postscript', 'PostScript'), ('pot', 'Gettext Catalog'), ('pov', 'POVRay'), ('powershell', 'PowerShell'), ('praat', 'Praat'), ('procfile', 'Procfile'), ('prolog', 'Prolog'), ('promql', 'PromQL'), ('properties', 'Properties'), ('protobuf', 'Protocol Buffer'), ('psql', 'PostgreSQL console (psql)'), ('psysh', 'PsySH console session for PHP'), ('pug', 'Pug'), ('puppet', 'Puppet'), ('pwsh-session', 'PowerShell Session'), ('py2tb', 'Python 2.x Traceback'), ('pycon', 'Python console session'), ('pypylog', 'PyPy Log'), ('pytb', 'Python Traceback'), ('python', 'Python'), ('python2', 'Python 2.x'), ('qbasic', 'QBasic'), ('qml', 'QML'), ('qvto', 'QVTO'), ('racket', 'Racket'), ('ragel', 'Ragel'), ('ragel-c', 'Ragel in C Host'), ('ragel-cpp', 'Ragel in CPP Host'), ('ragel-d', 'Ragel in D Host'), ('ragel-em', 'Embedded Ragel'), ('ragel-java', 'Ragel in Java Host'), ('ragel-objc', 'Ragel in Objective C Host'), ('ragel-ruby', 'Ragel in Ruby Host'), ('rbcon', 'Ruby irb session'), ('rconsole', 'RConsole'), ('rd', 'Rd'), ('reasonml', 'ReasonML'), ('rebol', 'REBOL'), ('red', 'Red'), ('redcode', 'Redcode'), ('registry', 'reg'), ('resourcebundle', 'ResourceBundle'), ('restructuredtext', 'reStructuredText'), ('rexx', 'Rexx'), ('rhtml', 'RHTML'), ('ride', 'Ride'), ('rng-compact', 'Relax-NG Compact'), ('roboconf-graph', 'Roboconf Graph'), ('roboconf-instances', 'Roboconf Instances'), ('robotframework', 'RobotFramework'), ('rql', 'RQL'), ('rsl', 'RSL'), ('ruby', 'Ruby'), ('rust', 'Rust'), ('sarl', 'SARL'), ('sas', 'SAS'), ('sass', 'Sass'), ('scala', 'Scala'), ('scaml', 'Scaml'), ('scdoc', 'scdoc'), ('scheme', 'Scheme'), ('scilab', 'Scilab'), ('scss', 'SCSS'), ('sgf', 'SmartGameFormat'), ('shen', 'Shen'), ('shexc', 'ShExC'), ('sieve', 'Sieve'), ('silver', 'Silver'), ('singularity', 'Singularity'), ('slash', 'Slash'), ('slim', 'Slim'), ('slurm', 'Slurm'), ('smali', 'Smali'), ('smalltalk', 'Smalltalk'), ('smarty', 'Smarty'), ('smithy', 'Smithy'), ('sml', 'Standard ML'), ('snobol', 'Snobol'), ('snowball', 'Snowball'), ('solidity', 'Solidity'), ('sp', 'SourcePawn'), ('sparql', 'SPARQL'), ('spec', 'RPMSpec'), ('splus', 'S'), ('sql', 'SQL'), ('sqlite3', 'sqlite3con'), ('squidconf', 'SquidConf'), ('ssp', 'Scalate Server Page'), ('stan', 'Stan'), ('stata', 'Stata'), ('supercollider', 'SuperCollider'), ('swift', 'Swift'), ('swig', 'SWIG'), ('systemverilog', 'systemverilog'), ('tads3', 'TADS 3'), ('tap', 'TAP'), ('tasm', 'TASM'), ('tcl', 'Tcl'), ('tcsh', 'Tcsh'), ('tcshcon', 'Tcsh Session'), ('tea', 'Tea'), ('teal', 'teal'), ('teratermmacro', 'Tera Term macro'), ('termcap', 'Termcap'), ('terminfo', 'Terminfo'), ('terraform', 'Terraform'), ('tex', 'TeX'), ('text', 'Text only'), ('thrift', 'Thrift'), ('ti', 'ThingsDB'), ('tid', 'tiddler'), ('tnt', 'Typographic Number Theory'), ('todotxt', 'Todotxt'), ('toml', 'TOML'), ('trac-wiki', 'MoinMoin/Trac Wiki markup'), ('trafficscript', 'TrafficScript'), ('treetop', 'Treetop'), ('tsql', 'Transact-SQL'), ('turtle', 'Turtle'), ('twig', 'Twig'), ('typescript', 'TypeScript'), ('typoscript', 'TypoScript'), ('typoscriptcssdata', 'TypoScriptCssData'), ('typoscripthtmldata', 'TypoScriptHtmlData'), ('ucode', 'ucode'), ('unicon', 'Unicon'), ('urbiscript', 'UrbiScript'), ('usd', 'USD'), ('vala', 'Vala'), ('vb.net', 'VB.net'), ('vbscript', 'VBScript'), ('vcl', 'VCL'), ('vclsnippets', 'VCLSnippets'), ('vctreestatus', 'VCTreeStatus'), ('velocity', 'Velocity'), ('verilog', 'verilog'), ('vgl', 'VGL'), ('vhdl', 'vhdl'), ('vim', 'VimL'), ('wast', 'WebAssembly'), ('wdiff', 'WDiff'), ('webidl', 'Web IDL'), ('whiley', 'Whiley'), ('x10', 'X10'), ('xml', 'XML'), ('xml+cheetah', 'XML+Cheetah'), ('xml+django', 'XML+Django/Jinja'), ('xml+evoque', 'XML+Evoque'), ('xml+lasso', 'XML+Lasso'), ('xml+mako', 'XML+Mako'), ('xml+myghty', 'XML+Myghty'), ('xml+php', 'XML+PHP'), ('xml+ruby', 'XML+Ruby'), ('xml+smarty', 'XML+Smarty'), ('xml+velocity', 'XML+Velocity'), ('xorg.conf', 'Xorg'), ('xquery', 'XQuery'), ('xslt', 'XSLT'), ('xtend', 'Xtend'), ('xul+mozpreproc', 'XUL+mozpreproc'), ('yaml', 'YAML'), ('yaml+jinja', 'YAML+Jinja'), ('yang', 'YANG'), ('zeek', 'Zeek'), ('zephir', 'Zephir'), ('zig', 'Zig')], default='python', max_length=100)), + ('style', models.CharField(choices=[('abap', 'abap'), ('algol', 'algol'), ('algol_nu', 'algol_nu'), ('arduino', 'arduino'), ('autumn', 'autumn'), ('borland', 'borland'), ('bw', 'bw'), ('colorful', 'colorful'), ('default', 'default'), ('emacs', 'emacs'), ('friendly', 'friendly'), ('fruity', 'fruity'), ('gruvbox-dark', 'gruvbox-dark'), ('gruvbox-light', 'gruvbox-light'), ('igor', 'igor'), ('inkpot', 'inkpot'), ('lovelace', 'lovelace'), ('manni', 'manni'), ('material', 'material'), ('monokai', 'monokai'), ('murphy', 'murphy'), ('native', 'native'), ('paraiso-dark', 'paraiso-dark'), ('paraiso-light', 'paraiso-light'), ('pastie', 'pastie'), ('perldoc', 'perldoc'), ('rainbow_dash', 'rainbow_dash'), ('rrt', 'rrt'), ('sas', 'sas'), ('solarized-dark', 'solarized-dark'), ('solarized-light', 'solarized-light'), ('stata', 'stata'), ('stata-dark', 'stata-dark'), ('stata-light', 'stata-light'), ('tango', 'tango'), ('trac', 'trac'), ('vim', 'vim'), ('vs', 'vs'), ('xcode', 'xcode'), ('zenburn', 'zenburn')], default='friendly', max_length=100)), + ('highlighted', models.TextField()), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='snippets', to='auth.user')), + ], + options={ + 'ordering': ['created'], + }, + ), + ] diff --git a/docs/migrations/0002_doc_doctopic_folder_topic_delete_snippet_and_more.py b/docs/migrations/0002_doc_doctopic_folder_topic_delete_snippet_and_more.py new file mode 100644 index 000000000..542fc36e5 --- /dev/null +++ b/docs/migrations/0002_doc_doctopic_folder_topic_delete_snippet_and_more.py @@ -0,0 +1,80 @@ +# Generated by Django 4.0 on 2022-01-05 20:33 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('docs', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Doc', + fields=[ + ('id', models.BigAutoField(auto_created=True, + primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('document', models.BinaryField()), + ('folder', models.TextField()), + ('created', models.DateTimeField(auto_now_add=True)), + ('owner', models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='docs', to='auth.user')), + ], + options={ + 'ordering': ['created'], + }, + ), + migrations.CreateModel( + name='DocTopic', + fields=[ + ('id', models.BigAutoField(auto_created=True, + primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('doc_id', models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to='docs.doc')), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, + related_name='doctopics', to='auth.user')), + ], + ), + migrations.CreateModel( + name='Folder', + fields=[ + ('id', models.BigAutoField(auto_created=True, + primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('created', models.DateTimeField(auto_now_add=True)), + ('owner', models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='folders', to='auth.user')), + ('parent', models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to='docs.folder')), + ], + ), + migrations.CreateModel( + name='Topic', + fields=[ + ('id', models.BigAutoField(auto_created=True, + primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=30)), + ('short_desc', models.CharField( + blank=True, default='', max_length=100)), + ('description', models.CharField( + blank=True, default='', max_length=1000)), + ('created', models.DateTimeField(auto_now_add=True)), + ('owner', models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='topics', to='auth.user')), + ], + ), + migrations.DeleteModel( + name='Snippet', + ), + migrations.AddField( + model_name='doctopic', + name='topic_id', + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to='docs.topic'), + ), + ] diff --git a/docs/migrations/0003_alter_doc_options_alter_doc_folder_alter_doc_owner_and_more.py b/docs/migrations/0003_alter_doc_options_alter_doc_folder_alter_doc_owner_and_more.py new file mode 100644 index 000000000..7b9480b1f --- /dev/null +++ b/docs/migrations/0003_alter_doc_options_alter_doc_folder_alter_doc_owner_and_more.py @@ -0,0 +1,39 @@ +# Generated by Django 4.0 on 2022-01-06 17:10 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('docs', '0002_doc_doctopic_folder_topic_delete_snippet_and_more'), + ] + + operations = [ + migrations.AlterModelOptions( + name='doc', + options={}, + ), + migrations.AlterField( + model_name='doc', + name='folder', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='docs.folder'), + ), + migrations.AlterField( + model_name='doc', + name='owner', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='docs', to='auth.user'), + ), + migrations.AlterField( + model_name='folder', + name='owner', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='folders', to='auth.user'), + ), + migrations.AlterField( + model_name='folder', + name='parent', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='docs.folder'), + ), + ] diff --git a/docs/migrations/0004_alter_folder_parent.py b/docs/migrations/0004_alter_folder_parent.py new file mode 100644 index 000000000..65d0ec6da --- /dev/null +++ b/docs/migrations/0004_alter_folder_parent.py @@ -0,0 +1,19 @@ +# Generated by Django 4.0 on 2022-01-06 20:23 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('docs', '0003_alter_doc_options_alter_doc_folder_alter_doc_owner_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='folder', + name='parent', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.RESTRICT, to='docs.folder'), + ), + ] diff --git a/docs/migrations/0005_alter_folder_owner.py b/docs/migrations/0005_alter_folder_owner.py new file mode 100644 index 000000000..4a5ce1c41 --- /dev/null +++ b/docs/migrations/0005_alter_folder_owner.py @@ -0,0 +1,20 @@ +# Generated by Django 4.0 on 2022-01-06 20:25 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('docs', '0004_alter_folder_parent'), + ] + + operations = [ + migrations.AlterField( + model_name='folder', + name='owner', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='fldrs', to='auth.user'), + ), + ] diff --git a/docs/migrations/0006_remove_doctopic_owner_remove_topic_owner_and_more.py b/docs/migrations/0006_remove_doctopic_owner_remove_topic_owner_and_more.py new file mode 100644 index 000000000..dc772a80b --- /dev/null +++ b/docs/migrations/0006_remove_doctopic_owner_remove_topic_owner_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 4.0 on 2022-01-07 15:03 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('docs', '0005_alter_folder_owner'), + ] + + operations = [ + migrations.RemoveField( + model_name='doctopic', + name='owner', + ), + migrations.RemoveField( + model_name='topic', + name='owner', + ), + migrations.AlterField( + model_name='doc', + name='folder', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='docs', to='docs.folder'), + ), + migrations.AlterField( + model_name='folder', + name='owner', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='folders', to='auth.user'), + ), + migrations.AlterField( + model_name='folder', + name='parent', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.RESTRICT, related_name='folders', to='docs.folder'), + ), + ] diff --git a/docs/migrations/0007_alter_doctopic_unique_together.py b/docs/migrations/0007_alter_doctopic_unique_together.py new file mode 100644 index 000000000..3b8bfbf71 --- /dev/null +++ b/docs/migrations/0007_alter_doctopic_unique_together.py @@ -0,0 +1,17 @@ +# Generated by Django 4.0 on 2022-01-07 15:54 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('docs', '0006_remove_doctopic_owner_remove_topic_owner_and_more'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='doctopic', + unique_together={('doc_id', 'topic_id')}, + ), + ] diff --git a/docs/migrations/0008_alter_doctopic_unique_together.py b/docs/migrations/0008_alter_doctopic_unique_together.py new file mode 100644 index 000000000..d12bf0526 --- /dev/null +++ b/docs/migrations/0008_alter_doctopic_unique_together.py @@ -0,0 +1,17 @@ +# Generated by Django 4.0 on 2022-01-07 15:55 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('docs', '0007_alter_doctopic_unique_together'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='doctopic', + unique_together=set(), + ), + ] diff --git a/docs/migrations/0009_alter_doctopic_unique_together.py b/docs/migrations/0009_alter_doctopic_unique_together.py new file mode 100644 index 000000000..0dbbe0ae6 --- /dev/null +++ b/docs/migrations/0009_alter_doctopic_unique_together.py @@ -0,0 +1,17 @@ +# Generated by Django 4.0 on 2022-01-07 15:57 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('docs', '0008_alter_doctopic_unique_together'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='doctopic', + unique_together={('doc_id', 'topic_id')}, + ), + ] diff --git a/docs/migrations/0010_alter_doctopic_options.py b/docs/migrations/0010_alter_doctopic_options.py new file mode 100644 index 000000000..3f89484ca --- /dev/null +++ b/docs/migrations/0010_alter_doctopic_options.py @@ -0,0 +1,17 @@ +# Generated by Django 4.0 on 2022-01-07 16:17 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('docs', '0009_alter_doctopic_unique_together'), + ] + + operations = [ + migrations.AlterModelOptions( + name='doctopic', + options={'ordering': ['doc_id']}, + ), + ] diff --git a/docs/migrations/0011_doc_topics.py b/docs/migrations/0011_doc_topics.py new file mode 100644 index 000000000..e4b640b13 --- /dev/null +++ b/docs/migrations/0011_doc_topics.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0 on 2022-01-07 19:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('docs', '0010_alter_doctopic_options'), + ] + + operations = [ + migrations.AddField( + model_name='doc', + name='topics', + field=models.ManyToManyField(through='docs.DocTopic', to='docs.Topic'), + ), + ] diff --git a/docs/migrations/0012_topic_docs.py b/docs/migrations/0012_topic_docs.py new file mode 100644 index 000000000..90506163c --- /dev/null +++ b/docs/migrations/0012_topic_docs.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0 on 2022-01-07 19:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('docs', '0011_doc_topics'), + ] + + operations = [ + migrations.AddField( + model_name='topic', + name='docs', + field=models.ManyToManyField(through='docs.DocTopic', to='docs.Doc'), + ), + ] diff --git a/docs/migrations/0013_rename_doc_document_alter_document_options_and_more.py b/docs/migrations/0013_rename_doc_document_alter_document_options_and_more.py new file mode 100644 index 000000000..ed337504a --- /dev/null +++ b/docs/migrations/0013_rename_doc_document_alter_document_options_and_more.py @@ -0,0 +1,30 @@ +# Generated by Django 4.0 on 2022-01-07 20:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('docs', '0012_topic_docs'), + ] + + operations = [ + migrations.RenameModel( + old_name='Doc', + new_name='Document', + ), + migrations.AlterModelOptions( + name='document', + options={'ordering': ['name']}, + ), + migrations.AlterModelOptions( + name='folder', + options={'ordering': ['name']}, + ), + migrations.AlterModelOptions( + name='topic', + options={'ordering': ['name']}, + ), + ] diff --git a/docs/migrations/__init__.py b/docs/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docs/models.py b/docs/models.py new file mode 100644 index 000000000..b81ad652c --- /dev/null +++ b/docs/models.py @@ -0,0 +1,68 @@ +from django.db import models + + +class Folder(models.Model): + """ + A folder is alanogous to a file system folder. It can have a parent + folder or multiple child folders. + """ + name = models.CharField(max_length=100) + parent = models.ForeignKey( + 'self', related_name='folders', null=True, on_delete=models.RESTRICT) + created = models.DateTimeField(auto_now_add=True) + owner = models.ForeignKey('auth.User', related_name='folders', + on_delete=models.RESTRICT) + + class Meta: + ordering = ['name'] + + +class Topic(models.Model): + """ + A topic is a category used for research or grouping of documents. + """ + name = models.CharField(max_length=30) + short_desc = models.CharField(max_length=100, blank=True, default='') + description = models.CharField(max_length=1000, blank=True, default='') + docs = models.ManyToManyField('Document', through='DocTopic') + created = models.DateTimeField(auto_now_add=True) + # owner = models.ForeignKey('auth.User', related_name='topics', + # on_delete=models.CASCADE) + + class Meta: + ordering = ['name'] + + +class Document(models.Model): + """ + A document is a file stored in the system. + + This model assumes it will be stored in the database. If at a lter stage + the files are stored in a file system, the document field would be removed + and the file would then be stored and retrieved from the actual folder + of the file system. + """ + name = models.CharField(max_length=100) + document = models.BinaryField() + folder = models.ForeignKey(Folder, related_name='docs', + on_delete=models.RESTRICT) + topics = models.ManyToManyField(Topic, through='DocTopic') + created = models.DateTimeField(auto_now_add=True) + owner = models.ForeignKey('auth.User', related_name='docs', + on_delete=models.RESTRICT) + + class Meta: + ordering = ['name'] + + +class DocTopic(models.Model): + doc_id = models.ForeignKey(Document, on_delete=models.CASCADE) + topic_id = models.ForeignKey(Topic, on_delete=models.CASCADE) + created = models.DateTimeField(auto_now_add=True) + # owner = models.ForeignKey('auth.User', related_name='doctopics', + # on_delete=models.CASCADE) + + class Meta: + unique_together = ('doc_id', 'topic_id') + ordering = ['doc_id'] + # order_by = 'doc_id' diff --git a/docs/permissions.py b/docs/permissions.py new file mode 100644 index 000000000..7510b2806 --- /dev/null +++ b/docs/permissions.py @@ -0,0 +1,16 @@ +from rest_framework import permissions + + +class IsOwnerOrReadOnly(permissions.BasePermission): + """ + Custom permission to only allow owners of an object to edit it. + """ + + def has_object_permission(self, request, view, obj): + # Read permissions are allowed to any request, + # so we'll always allow GET, HEAD or OPTIONS requests. + if request.method in permissions.SAFE_METHODS: + return True + + # Write permissions are only allowed to the owner of the snippet. + return obj.owner == request.user diff --git a/docs/serializers.py b/docs/serializers.py new file mode 100644 index 000000000..3f347c4d0 --- /dev/null +++ b/docs/serializers.py @@ -0,0 +1,49 @@ +from rest_framework import serializers +# from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES +from docs.models import Document, Folder, Topic, DocTopic +# from django.contrib.auth.models import User + + +class FolderSerializer(serializers.HyperlinkedModelSerializer): + parent_name = serializers.ReadOnlyField(source='parent.name') + docs = serializers.HyperlinkedRelatedField( + many=True, view_name='document-detail', read_only=True) + + class Meta: + model = Folder + fields = ['id', 'url', 'name', + 'parent_name', 'parent', + 'docs', + 'owner'] + + +class DocSerializer(serializers.HyperlinkedModelSerializer): + folder_name = serializers.ReadOnlyField(source='folder.name') + owner = serializers.ReadOnlyField(source='owner.username') + + class Meta: + model = Document + fields = ['id', 'url', 'name', 'document', + 'folder_name', 'folder', + 'topics', + 'owner'] + + +class TopicSerializer(serializers.HyperlinkedModelSerializer): + + class Meta: + model = Topic + fields = ['id', 'url', 'name', 'short_desc', 'description', 'docs'] + + +class DocTopicSerializer(serializers.HyperlinkedModelSerializer): + docs = DocSerializer(read_only=True, many=True) + topics = TopicSerializer(read_only=True, many=True) + # doc_name = serializers.ReadOnlyField(source='document.name') + + class Meta: + model = DocTopic + # fields = "__all__" + fields = ['id', 'url', 'created', + 'doc_id', 'topic_id', + 'docs', 'topics'] diff --git a/docs/tests.py b/docs/tests.py new file mode 100644 index 000000000..7ce503c2d --- /dev/null +++ b/docs/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/docs/urls.py b/docs/urls.py new file mode 100644 index 000000000..2a520b9a4 --- /dev/null +++ b/docs/urls.py @@ -0,0 +1,83 @@ +from django.urls import path, include +from rest_framework.routers import DefaultRouter +from rest_framework.urlpatterns import format_suffix_patterns +from docs import views + +from docs.views import DocViewSet, FolderViewSet, TopicViewSet, DocTopicViewSet + +from docs.views import api_root + + +# Create a router and register our viewsets with it. +router = DefaultRouter() +router.register(r'docs', views.DocViewSet) +router.register(r'topics', views.TopicViewSet) +router.register(r'doctopics', views.DocTopicViewSet) +router.register(r'folders', views.FolderViewSet) + +doc_list = DocViewSet.as_view({ + 'get': 'list', + 'post': 'create' +}) +doc_detail = DocViewSet.as_view({ + 'get': 'retrieve', + 'put': 'update', + 'patch': 'partial_update', + 'delete': 'destroy' +}) + +doctopic_list = DocTopicViewSet.as_view({ + 'get': 'list', + 'post': 'create' +}) +doctopic_detail = DocTopicViewSet.as_view({ + 'get': 'retrieve', + 'put': 'update', + 'patch': 'partial_update', + 'delete': 'destroy' +}) + +folder_list = FolderViewSet.as_view({ + 'get': 'list', + 'post': 'create' +}) +folder_detail = FolderViewSet.as_view({ + 'get': 'retrieve', + 'put': 'update', + 'patch': 'partial_update', + 'delete': 'destroy' +}) + +topic_list = TopicViewSet.as_view({ + 'get': 'list', + 'post': 'create' +}) +topic_detail = TopicViewSet.as_view({ + 'get': 'retrieve', + 'put': 'update', + 'patch': 'partial_update', + 'delete': 'destroy' +}) + +# API endpoints + +""" +There needs to be a search endpoint for each of documents, folders and topics. +""" +urlpatterns = format_suffix_patterns([ + path('', api_root), + path('docs/', doc_list, name='document-list'), + path('docs//', doc_detail, name='document-detail'), + path('folders/', folder_list, name='folder-list'), + path('folders//', folder_detail, name='folder-detail'), + path('topics/', topic_list, name='topic-list'), + path('topics//', topic_detail, name='topic-detail'), + path('doctopics/', doctopic_list, name='doctopic-list'), + path('doctopics//', doctopic_detail, name='doctopic-detail'), +]) + +urlpaterns = format_suffix_patterns(urlpatterns) + +urlpatterns += [ + path('api-auth/', include('rest_framework.urls')), +] diff --git a/docs/views.py b/docs/views.py new file mode 100644 index 000000000..e1f2b5629 --- /dev/null +++ b/docs/views.py @@ -0,0 +1,82 @@ + +# from snippets.models import Snippet +# from snippets.permissions import IsOwnerOrReadOnly +# from snippets.serializers import SnippetSerializer +# from snippets.serializers import UserSerializer + +from docs.models import Document, Folder, Topic, DocTopic +from docs.permissions import IsOwnerOrReadOnly +from docs.serializers import DocSerializer +from docs.serializers import FolderSerializer +from docs.serializers import TopicSerializer +from docs.serializers import DocTopicSerializer +# from docs.serializers import UserSerializer + +# from rest_framework import generics +from rest_framework import permissions +# from rest_framework import renderers +from rest_framework import viewsets + +from rest_framework.decorators import api_view +# from rest_framework.decorators import action +from rest_framework.response import Response +from rest_framework.reverse import reverse + +# from django.contrib.auth.models import User + + +@api_view +def api_root(request, format=None): + return Response({ + 'docs': reverse('document-list', request=request, format=format), + 'folders': reverse('folder-list', request=request, format=format), + 'topics': reverse('topic-list', request=request, format=format), + # 'users': reverse('user-list', request=request, format=format), + }) + + +# class UserViewSet(viewsets.ReadOnlyModelViewSet): +# """ +# This viewset automatically provides 'list' and 'retrieve' actions. +# """ +# queryset = User.objects.all() +# serializer_class = UserSerializer + + +class DocViewSet(viewsets.ModelViewSet): + """ + A document is in a folder and may have many topics. + """ + queryset = Document.objects.all() + serializer_class = DocSerializer + permission_classes = [permissions.IsAuthenticatedOrReadOnly, + IsOwnerOrReadOnly] + + +class FolderViewSet(viewsets.ModelViewSet): + """ + A folder may hold documents or folders. + + A folder should only be removed if it is empty. + """ + queryset = Folder.objects.all() + serializer_class = FolderSerializer + permission_classes = [permissions.IsAuthenticatedOrReadOnly, + IsOwnerOrReadOnly] + + +class TopicViewSet(viewsets.ModelViewSet): + """ + A topic is used to categorize documents. + One document may have several topics. + """ + queryset = Topic.objects.all() + serializer_class = TopicSerializer + + +class DocTopicViewSet(viewsets.ModelViewSet): + """ + The many to many data structure that connects documents to topics. + """ + queryset = DocTopic.objects.all() + serializer_class = DocTopicSerializer diff --git a/requirements.txt b/requirements.txt index fb450cffa..53c804493 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ django gunicorn django-heroku requests +psycopg2 From f33fe207234ebe3db725b421d48136389f9e344e Mon Sep 17 00:00:00 2001 From: Broadus Jones Date: Tue, 11 Jan 2022 14:40:08 -0600 Subject: [PATCH 5/8] added changed urls for docs --- gettingstarted/settings.py | 10 +++++++++- gettingstarted/urls.py | 5 ++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 9ea552a0c..71b6eb452 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -78,7 +78,7 @@ DATABASES = { "default": { - "ENGINE" : "django.db.backends.sqlite3", + "ENGINE": "django.db.backends.sqlite3", "NAME": os.path.join(BASE_DIR, "db.sqlite3") } } @@ -116,4 +116,12 @@ STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') STATIC_URL = "/static/" +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +REST_FRAMEWORK = { + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + 'PAGE_SIZE': 10 +} + + django_heroku.settings(locals()) diff --git a/gettingstarted/urls.py b/gettingstarted/urls.py index 13b759582..6ee172ea2 100644 --- a/gettingstarted/urls.py +++ b/gettingstarted/urls.py @@ -2,9 +2,11 @@ from django.contrib import admin +import hello.views +import docs.views + admin.autodiscover() -import hello.views # To add a new path, first import the app: # import blog @@ -16,6 +18,7 @@ urlpatterns = [ path("", hello.views.index, name="index"), + path("", include('docs.urls')), path("db/", hello.views.db, name="db"), path("admin/", admin.site.urls), ] From 2938652eb5ad6c323de602a16133bf937eb7fae6 Mon Sep 17 00:00:00 2001 From: Broadus Jones Date: Tue, 11 Jan 2022 14:44:59 -0600 Subject: [PATCH 6/8] added docs to INSTALLED_APPS --- gettingstarted/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 71b6eb452..223e31949 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -40,6 +40,7 @@ "django.contrib.messages", "django.contrib.staticfiles", "hello", + 'docs.apps.DocsConfig', ] MIDDLEWARE = [ From 865e2235cade54e6e0ae9d9df6335635311a98cb Mon Sep 17 00:00:00 2001 From: Broadus Jones Date: Tue, 11 Jan 2022 15:31:06 -0600 Subject: [PATCH 7/8] added rest_framework to INSTALLED_APPS and requirements.txt --- gettingstarted/settings.py | 1 + requirements.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/gettingstarted/settings.py b/gettingstarted/settings.py index 223e31949..40105c62b 100644 --- a/gettingstarted/settings.py +++ b/gettingstarted/settings.py @@ -39,6 +39,7 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + 'rest_framework', "hello", 'docs.apps.DocsConfig', ] diff --git a/requirements.txt b/requirements.txt index 53c804493..1bdf3fff6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ gunicorn django-heroku requests psycopg2 +djangorestframework From 2b6430c7ce609b6d843a15e7f3290bef67ce74ae Mon Sep 17 00:00:00 2001 From: Broadus Jones Date: Tue, 11 Jan 2022 16:05:41 -0600 Subject: [PATCH 8/8] added user views --- docs/serializers.py | 12 +++++++++++- docs/urls.py | 12 +++++++++++- docs/views.py | 22 ++++++++++++++-------- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/docs/serializers.py b/docs/serializers.py index 3f347c4d0..719d560ab 100644 --- a/docs/serializers.py +++ b/docs/serializers.py @@ -1,13 +1,14 @@ from rest_framework import serializers # from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES from docs.models import Document, Folder, Topic, DocTopic -# from django.contrib.auth.models import User +from django.contrib.auth.models import User class FolderSerializer(serializers.HyperlinkedModelSerializer): parent_name = serializers.ReadOnlyField(source='parent.name') docs = serializers.HyperlinkedRelatedField( many=True, view_name='document-detail', read_only=True) + owner = serializers.ReadOnlyField(source='owner.username') class Meta: model = Folder @@ -47,3 +48,12 @@ class Meta: fields = ['id', 'url', 'created', 'doc_id', 'topic_id', 'docs', 'topics'] + + +class UserSerializer(serializers.HyperlinkedModelSerializer): + docs = serializers.HyperlinkedRelatedField( + many=True, view_name='doc-detail', read_only=True) + + class Meta: + model = User + fields = ['url', 'id', 'username', 'docs'] diff --git a/docs/urls.py b/docs/urls.py index 2a520b9a4..d13b48d87 100644 --- a/docs/urls.py +++ b/docs/urls.py @@ -4,7 +4,7 @@ from docs import views from docs.views import DocViewSet, FolderViewSet, TopicViewSet, DocTopicViewSet - +from docs.views import UserViewSet from docs.views import api_root @@ -59,6 +59,14 @@ 'delete': 'destroy' }) +user_list = UserViewSet.as_view({ + 'get': 'list' +}) +user_detail = UserViewSet.as_view({ + 'get': 'retrieve' +}) + + # API endpoints """ @@ -74,6 +82,8 @@ path('topics//', topic_detail, name='topic-detail'), path('doctopics/', doctopic_list, name='doctopic-list'), path('doctopics//', doctopic_detail, name='doctopic-detail'), + path('users/', user_list, name='user-list'), + path('users//', user_detail, name='user-detail'), ]) urlpaterns = format_suffix_patterns(urlpatterns) diff --git a/docs/views.py b/docs/views.py index e1f2b5629..d39280dea 100644 --- a/docs/views.py +++ b/docs/views.py @@ -10,7 +10,7 @@ from docs.serializers import FolderSerializer from docs.serializers import TopicSerializer from docs.serializers import DocTopicSerializer -# from docs.serializers import UserSerializer +from docs.serializers import UserSerializer # from rest_framework import generics from rest_framework import permissions @@ -22,7 +22,7 @@ from rest_framework.response import Response from rest_framework.reverse import reverse -# from django.contrib.auth.models import User +from django.contrib.auth.models import User @api_view @@ -35,12 +35,12 @@ def api_root(request, format=None): }) -# class UserViewSet(viewsets.ReadOnlyModelViewSet): -# """ -# This viewset automatically provides 'list' and 'retrieve' actions. -# """ -# queryset = User.objects.all() -# serializer_class = UserSerializer +class UserViewSet(viewsets.ReadOnlyModelViewSet): + """ + This viewset automatically provides 'list' and 'retrieve' actions. + """ + queryset = User.objects.all() + serializer_class = UserSerializer class DocViewSet(viewsets.ModelViewSet): @@ -52,6 +52,9 @@ class DocViewSet(viewsets.ModelViewSet): permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly] + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + class FolderViewSet(viewsets.ModelViewSet): """ @@ -64,6 +67,9 @@ class FolderViewSet(viewsets.ModelViewSet): permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly] + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + class TopicViewSet(viewsets.ModelViewSet): """