[
  {
    "path": ".circleci/config.yml",
    "content": "version: 2\njobs:\n  build:\n    docker:\n      # specify the version you desire here\n      - image: circleci/python:3.6.1\n\n\n    working_directory: ~/repo\n\n    steps:\n      - checkout\n\n      # Download and cache dependencies\n      - restore_cache:\n          keys:\n          - v1-dependencies-{{ checksum \"pollsapi/requirements.txt\" }}\n          # fallback to using the latest cache if no exact match is found\n          - v1-dependencies-\n\n      - run:\n          name: install dependencies\n          command: |\n            python3 -m venv venv\n            . venv/bin/activate\n            pip install -r pollsapi/requirements.txt\n\n      - save_cache:\n          paths:\n            - ./venv\n          key: v1-dependencies-{{ checksum \"requirements.txt\" }}\n\n      # run tests!\n      # this example uses Django's built-in test-runner\n      # other common Python testing frameworks include pytest and nose\n      # https://pytest.org\n      # https://nose.readthedocs.io\n      - run:\n          name: run tests\n          command: |\n            . venv/bin/activate\n            cd pollsapi\n            python manage.py test\n\n      - store_artifacts:\n          path: test-reports\n          destination: test-reports\n\n"
  },
  {
    "path": ".gitignore",
    "content": "# sphinx build folder\n_build\n\n# Compiled source #\n###################\n*.com\n*.class\n*.dll\n*.exe\n*.o\n*.so\n\n# Packages #\n############\n# it's better to unpack these files and commit the raw source\n# git has its own built in compression methods\n*.7z\n*.dmg\n*.gz\n*.iso\n*.jar\n*.rar\n*.tar\n*.zip\n\n# Logs and databases #\n######################\n*.log\n*.sql\n*.sqlite\n\n# OS generated files #\n######################\n.DS_Store\nehthumbs.db\nIcon?\nThumbs.db\n\n# Editor backup files #\n#######################\n*~"
  },
  {
    "path": "LICENSE",
    "content": "This work is licensed under a CC-BY-SA 4.0 (Creative Commons Attribution-ShareAlike 4.0 International License) licence. \nThe full text is available at: https://creativecommons.org/licenses/by-sa/4.0/\n"
  },
  {
    "path": "README.md",
    "content": " Building APIs with Django and Django Rest Framework\n==================================================================\n\n[Read it online](http://books.agiliq.com/projects/django-api-polls-tutorial/)\n\nAn opinionated guide to building APIs with modern tools.\n\n\n\nDramatis personæ\n================\n\n* Python: A programming language\n* Django: A framework for Python\n* Django rest framework: A flexible toolkit for building APIs\n* CircleCI: Keeps your documentation and API in sync\n\n\nChapters\n========\n\n* The importance of Documentation driven development and summary of API we will need\n* What we will build and the API\n* [Models and Admin (Probably the same as Django tutorial)](http://books.agiliq.com/projects/django-api-polls-tutorial/en/latest/chapter1.html)\n* [Building API with Django-Rest-Framework](http://books.agiliq.com/projects/django-api-polls-tutorial/en/latest/chapter2.html)\n* [Authentication and access control with DRF](http://books.agiliq.com/projects/django-api-polls-tutorial/en/latest/chapter3.html)\n* [Testing and CI: Introduction to Django testing, language agnostic API testing and CircleCI](http://books.agiliq.com/projects/django-api-polls-tutorial/en/latest/chapter4.html)\n* Consuming and collaborating with API: Introduce Postman, ngrok, angular\n"
  },
  {
    "path": "docs/Documenting-API-with-RAML.rst.draft",
    "content": "Documenting API with RAML\n============================\n\nIn this chapter we will see how to use raml for all the views of our API.\n\nRAML is an acronym for \"RESTful API Modeling Language\". It is a YAML based language for describing the RESTful APIs. RAML contains certain sections for describing the APIs. Each section has it's purpose and we'll look into each one of these by using our polls application.\n\n\n1. Root\n----------------------\n\nRoot section is specifies the basic things like title, baseUri etc. These are applied through out the rest of the API\n\n.. code-block:: python\n\n    #%RAML 0.8\n        ---\n        title: django polls API\n        baseUri: http://api.example.com/{version}\n        version: v1\n        mediaType: application/json\n\n\n2. Resources\n---------------------\n\nIt's important to consider how your API consumers will use your API. So we'll list out all the resources that are available in our API.\n\n.. code-block:: python\n\n    /polls:\n    /choices:\n    /votes:\n\nNotice that these resources all begin with a slash (/). In RAML, this is how you indicate a resource. Any methods and parameters nested under these top level resources belong to and act upon that resource.\n\nNow, since each of these resources is a collection of individual objects (specific poll, choice), we'll need to define some sub-resources to fill out the collection.\n\nTo view all the API endpoints, we need to specify them in a JSON file with the following format. You may call it pollaspi.json.\n\n.. code-block:: python\n\n    /polls:\n        /{pollId}:\n\nThis lets the API consumer interact with the key resource and its nested resources. For example a GET request to http://api.example.com/polls/1 returns details about the one particular poll whose pollId is 1.\n\n\n3. Methods\n--------------\n\nThe above mentioned resources can be accessed via 4 most common HTTP methods(Verbs).\n\nGET - Retrieve the information defined in the request URI.\n\nPUT - Replace the addressed collection. At the object-level, create or update it.\n\nPOST - Create a new entry in the collection. This method is generally not used at the object-level.\n\nDELETE - Delete the information defined in the request URI.\n\nYou can add as many methods as you like to each resource of your BookMobile API, at any level. However, each HTTP method can only be used once per resource.\n\nNest the methods to allow developers to perform these actions under your resources. Note that you must use lower-case for methods in your RAML API definition.\n\n.. code-block:: python\n\n    /polls:\n        get:\n        post:\n\n\nURI Parameters\n---------------\n\nThe resources that we defined are collections of smaller, relevant objects.\n\n.. code-block:: python\n\n    /polls:\n        /{pollId}:\n\n\nQuery Parameters:\n--------------------\n\nQuery parameters are used for filtering a collection. We already have collections-based resource types that are further defined by object-based URI parameters. We'll see how we can use query paramters for them.\n\n.. code-block:: python\n\n    /polls:\n        get:\n            description: Get list of polls\n            queryParameters:\n                pollId:\n\nAn API's resources and methods often have a number of associated query parameters. Each query parameter may have any number of optional attributes to further define it.\n\nNow, we'll specify attributes for the query parameters we defined above.\n\n.. code-block:: python\n\n    /polls:\n        get:\n            description: Get list of polls\n            queryParameters:\n                pollId:\n                    description: Specify the poll id you want to retrieve\n                    type: integer\n                    example: 1\n\n\nResponses:\n-------------\n\nResponses MUST be a map of one or more HTTP status codes, and each response may include descriptions, examples.\n\n.. code-block:: python\n\n    responses:\n        200:\n            body:\n                application/json:\n                example:\n                {\n                    \"data\":\n                    {\n                        \"Id\": 1,\n                        \"question\": \"Will A be the leader next time?\",\n                        \"created_by\": \"user1\",\n                        \"pub_date\": \"08:02:2014\"\n                    },\n                    \"success\": true,\n                    \"status\": 200\n                }\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nPAPER         =\nBUILDDIR      = _build\n\n# User-friendly check for sphinx-build\nifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)\n$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)\nendif\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n\n.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext\n\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  applehelp  to make an Apple Help Book\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  latexpdfja to make LaTeX files and run them through platex/dvipdfmx\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  xml        to make Docutils-native XML files\"\n\t@echo \"  pseudoxml  to make pseudoxml-XML files for display purposes\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\t@echo \"  coverage   to run coverage check of the documentation (if enabled)\"\n\nclean:\n\trm -rf $(BUILDDIR)/*\n\nhtml:\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\ndirhtml:\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\nsinglehtml:\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\npickle:\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\njson:\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\nhtmlhelp:\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\nqthelp:\n\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp\n\t@echo\n\t@echo \"Build finished; now you can run \"qcollectiongenerator\" with the\" \\\n\t      \".qhcp project file in $(BUILDDIR)/qthelp, like this:\"\n\t@echo \"# qcollectiongenerator $(BUILDDIR)/qthelp/BuildingAPIDjango.qhcp\"\n\t@echo \"To view the help file:\"\n\t@echo \"# assistant -collectionFile $(BUILDDIR)/qthelp/BuildingAPIDjango.qhc\"\n\napplehelp:\n\t$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp\n\t@echo\n\t@echo \"Build finished. The help book is in $(BUILDDIR)/applehelp.\"\n\t@echo \"N.B. You won't be able to view it unless you put it in\" \\\n\t      \"~/Library/Documentation/Help or install it in your application\" \\\n\t      \"bundle.\"\n\ndevhelp:\n\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp\n\t@echo\n\t@echo \"Build finished.\"\n\t@echo \"To view the help file:\"\n\t@echo \"# mkdir -p $$HOME/.local/share/devhelp/BuildingAPIDjango\"\n\t@echo \"# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/BuildingAPIDjango\"\n\t@echo \"# devhelp\"\n\nepub:\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\nlatex:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\nlatexpdf:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\nlatexpdfja:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through platex and dvipdfmx...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\ntext:\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\nman:\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\ntexinfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\ninfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\ngettext:\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\nchanges:\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\ndoctest:\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n\ncoverage:\n\t$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage\n\t@echo \"Testing of coverage in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/coverage/python.txt.\"\n\nxml:\n\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml\n\t@echo\n\t@echo \"Build finished. The XML files are in $(BUILDDIR)/xml.\"\n\npseudoxml:\n\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml\n\t@echo\n\t@echo \"Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml.\"\n"
  },
  {
    "path": "docs/access-control.rst",
    "content": "Access Control\n=================================\n\nIn this chapter, we will add access control to our APIs,\nand add APIs to create and authenticate users.\n\nRight now our APIs are completely permissive. Anyone can create, access and delete anything.\nWe want to add these access controls.\n\n\n- A user must be authenticated to access a poll or the list of polls.\n- Only an authenticated users can create a poll.\n- Only an authenticated user can create a choice.\n- Authenticated users can create choices only for polls they have created.\n- Authenticated users can delete only polls they have created.\n- Only an authenticated user can vote. Users can vote for other people's polls.\n\nTo enable the access control, we need to add two more APIs\n\n- API to create a user, we will call this endpoint :code:`/users/`\n- API to verify a user and get a token to identify them, we will call this endpoint :code:`/login/`\n\n\n\nCreating a user\n--------------------------\n\n\nWe will add an user serializer, which will allow creating. Add the following code to :code:`serializers.py`.\n\n.. code-block:: python\n\n    # ...\n    from django.contrib.auth.models import User\n    \n    # ...\n    class UserSerializer(serializers.ModelSerializer):\n\n        class Meta:\n            model = User\n            fields = ('username', 'email', 'password')\n            extra_kwargs = {'password': {'write_only': True}}\n\n        def create(self, validated_data):\n            user = User(\n                email=validated_data['email'],\n                username=validated_data['username']\n            )\n            user.set_password(validated_data['password'])\n            user.save()\n            return user\n\nWe have overriden the ModelSerializer method's :code:`create()` to save the :code:`User` instances. We ensure that we set the password correctly using :code:`user.set_password`, rather than setting the raw password as the hash. We also don't want to get back the password in response which we ensure using :code:`extra_kwargs = {'password': {'write_only': True}}`.\n\nLet us also add views to the User Serializer for creating the user and connect it to the urls.py\n\n.. code-block:: python\n\n    # in apiviews.py\n    # ...\n    from .serializers import PollSerializer, ChoiceSerializer, VoteSerializer, UserSerializer\n\n    # ...\n    class UserCreate(generics.CreateAPIView):\n        serializer_class = UserSerializer\n\n    # in urls.py\n    # ...\n    from .apiviews import PollViewSet, ChoiceList, CreateVote, UserCreate\n\n\n    urlpatterns = [\n        # ...\n        path(\"users/\", UserCreate.as_view(), name=\"user_create\"),\n    ]\n\nWe can test this api by posting to :code:`/users/` with this json.\n\n.. code-block:: json\n\n    {\n        \"username\": \"nate.silver\",\n        \"email\": \"nate.silver@example.com\",\n        \"password\": \"FiveThirtyEight\"\n    }\n\nWhich give back this response.\n\n.. code-block:: json\n\n    {\n        \"username\": \"nate.silver\",\n        \"email\": \"nate.silver@example.com\"\n    }\n\nTry posting the same json, and you will get a error response (HTTP status code 400)\n\n.. code-block:: json\n\n    {\n        \"username\": [\n            \"A user with that username already exists.\"\n        ]\n    }\n\n\nAuthentication scheme setup\n-----------------------------\n\nWith Django Rest Framework, we can set up a default authentication scheme which is applied to all views using :code:`DEFAULT_AUTHENTICATION_CLASSES`. We will use the token authentication in this tutorial. In your settings.py, add this.\n\n.. code-block:: python\n\n    REST_FRAMEWORK = {\n        'DEFAULT_AUTHENTICATION_CLASSES': (\n            'rest_framework.authentication.TokenAuthentication',\n            'rest_framework.authentication.SessionAuthentication',\n        )\n    }\n\nYou also need to enable :code:`rest_framework.authtoken` app, so update :code:`INSTALLED_APPS` in your settings.py.\n\n.. code-block:: python\n\n    INSTALLED_APPS = (\n        ...\n        'rest_framework.authtoken'\n    )\n\nRun :code:`python manage.py migrate` to create the new tables.\n\n.. We want to ensure that, by default all apis are only allowed to authenticated users. Add this to your :code:`settings.py`.\n\n.. code-block:: python\n\n    REST_FRAMEWORK = {\n        # ...\n        'DEFAULT_PERMISSION_CLASSES': (\n            'rest_framework.permissions.IsAuthenticated',\n        )\n    }\n\nAlso, dont forget to give exemption to :code:`UserCreate` view for authentication by overriding the global setting. The :code:`UserCreate` in :code:`polls/apiviews.py` should look as follows.\n\n.. code-block:: python\n\n    class UserCreate(generics.CreateAPIView):\n        authentication_classes = ()\n        permission_classes = ()\n        serializer_class = UserSerializer\n\nNote the :code:`authentication_classes = ()` and :code:`permission_classes = ()` to exempt :code:`UserCreate` from global authentication scheme.\n\nWe want to ensure that tokens are created when user is created in :code:`UserCreate` view, so we update the :code:`UserSerializer`. Change your :code:`serializers.py` like this\n\n.. code-block:: python\n\n    from rest_framework.authtoken.models import Token\n\n    class UserSerializer(serializers.ModelSerializer):\n\n        class Meta:\n            model = User\n            fields = ('username', 'email', 'password')\n            extra_kwargs = {'password': {'write_only': True}}\n\n        def create(self, validated_data):\n            user = User(\n                email=validated_data['email'],\n                username=validated_data['username']\n            )\n            user.set_password(validated_data['password'])\n            user.save()\n            Token.objects.create(user=user)\n            return user\n\n\n\nThe login API\n-----------------------------\n\nSince we have added :code:`rest_framework.authentication.TokenAuthentication`, we will need to set a header like this :code:`Authorization: Token c2a84953f47288ac1943a3f389a6034e395ad940` to authenticate. We need an API where a user can give their username and password, and get a token back.\n\nWe will not be adding a serializer, because we never save a token using this API.\n\nAdd a view and connect it to urls.\n\n.. code-block:: python\n\n    # in apiviews.py\n    # ...\n    from django.contrib.auth import authenticate\n\n    class LoginView(APIView):\n        permission_classes = ()\n\n        def post(self, request,):\n            username = request.data.get(\"username\")\n            password = request.data.get(\"password\")\n            user = authenticate(username=username, password=password)\n            if user:\n                return Response({\"token\": user.auth_token.key})\n            else:\n                return Response({\"error\": \"Wrong Credentials\"}, status=status.HTTP_400_BAD_REQUEST)\n\n\n    # in urls.py\n    # ...\n\n    from .apiviews import PollViewSet, ChoiceList, CreateVote, UserCreate, LoginView\n\n\n\n    urlpatterns = [\n        path(\"login/\", LoginView.as_view(), name=\"login\"),\n        # ...\n    ]\n\nWARNING: You have to create a user using the :code:`/user/` endpoint before logging in using the :code:`/login/` endpoint. Using a previously existing user will result in a \"User has no auth_token\" error because we have not created a token for them. You can create tokens for them manually by using the django shell :code:`$ python manage.py shell`.\n\n    >>> from django.contrib.auth.models import User\n    >>> from rest_framework.authtoken.models import Token\n    >>> user = User.objects.get(pk=pk_of_user_without_token)\n    >>> Token.objects.create(user=user)\n    <Token: e2b9fa2d4ae27fe1fdcf17b6e37711334d07e167>\n\nDo a POST with a correct username and password, and you will get a response like this.\n\n.. code-block:: json\n\n    {\n        \"token\": \"c300998d0e2d1b8b4ed9215589df4497de12000c\"\n    }\n\n\nPOST with a incorrect username and password, and you will get a response like this, with a HTTP status of 400.\n\n.. code-block:: json\n\n    {\n        \"error\": \"Wrong Credentials\"\n    }\n\nAnother way to create this login endpoint is using :code:`obtain_auth_token` method provide by DRF\n\n.. code-block:: python\n\n    # in urls.py\n    # ...\n    from rest_framework.authtoken import views\n\n    urlpatterns = [\n        path(\"login/\", views.obtain_auth_token, name=\"login\"),\n        # ...\n    ]\n\n\nFine grained access control\n-----------------------------\n\nTry accessing the :code:`/polls/` API without any header. You will get an error with a http status code of :code:`HTTP 401 Unauthorized` like this.\n\n.. code-block:: json\n\n    {\n        \"detail\": \"Authentication credentials were not provided.\"\n    }\n\nAdd an authorization header :code:`Authorization: Token <your token>`, and you can access the API.\n\nFrom now onwards we will use a HTTP header like this, :code:`Authorization: Token <your token>` in all further requests.\n\nWe have two remaining things we need to enforce.\n\n- Authenticated users can create choices only for polls they have created.\n- Authenticated users can delete only polls they have created.\n\nWe will do that by overriding :code:`PollViewSet.destroy` and :code:`ChoiceList.post`.\n\n.. code-block:: python\n\n    # ...\n    from rest_framework.exceptions import PermissionDenied\n\n\n    class PollViewSet(viewsets.ModelViewSet):\n        # ...\n\n        def destroy(self, request, *args, **kwargs):\n            poll = Poll.objects.get(pk=self.kwargs[\"pk\"])\n            if not request.user == poll.created_by:\n                raise PermissionDenied(\"You can not delete this poll.\")\n            return super().destroy(request, *args, **kwargs)\n\n\n    class ChoiceList(generics.ListCreateAPIView):\n        # ...\n\n        def post(self, request, *args, **kwargs):\n            poll = Poll.objects.get(pk=self.kwargs[\"pk\"])\n            if not request.user == poll.created_by:\n                raise PermissionDenied(\"You can not create choice for this poll.\")\n            return super().post(request, *args, **kwargs)\n\nIn both cases, we are checking :code:`request.user` against the expected user, and raising\na :code:`PermissionDenied` error if it does not match.\n\nYou can check this by doing a DELETE on someone elses :code:`Poll`. You will get an error with :code:`HTTP 403 Forbidden` and response.\n\n\n.. code-block:: json\n\n    {\n        \"detail\": \"You can not delete this poll.\"\n    }\n\n\nSimilarly, trying to create choice for someone else's :code:`Poll` will get an error with :code:`HTTP 403 Forbidden` and response\n\n.. code-block:: json\n\n    {\n        \"detail\": \"You can not create choice for this poll.\"\n    }\n\n\nNext steps:\n-----------------\n\nIn the next chapter we will look at adding tests for our API and serializers. We will also look at how to use :code:`flake8` and run our tests in a CI environment.\n"
  },
  {
    "path": "docs/apis-without-drf.rst",
    "content": "A simple API with pure Django\n========================================\n\nIn this chapter, we will build an API with pure Django. We will not use Django Rest Framework (Or any other library).\nTo start add some :code:`Poll` using the admin.\n\nThe endpoints and the URLS\n+++++++++++++++++++++++++++++++\n\nOur API will have two endpoints returning data in JSON format.\n\n* :code:`/polls/` GETs list of :code:`Poll`\n* :code:`/polls/<id>/` GETs data of a specific :code:`Poll`\n\nConnecting urls to the views\n++++++++++++++++++++++++++++++\n\nWrite two place holder view functions and connect them in your :code:`urls.py`. We will finish :code:`polls_list` and :code:`polls_detail` shortly.\n\n.. code-block:: python\n\n    # In views.py\n    def polls_list(request):\n        pass\n\n    def polls_detail(request, pk):\n        pass\n\n\n    # in urls.py\n    from django.urls import path\n    from .views import polls_list, polls_detail\n\n    urlpatterns = [\n        path(\"polls/\", polls_list, name=\"polls_list\"),\n        path(\"polls/<int:pk>/\", polls_detail, name=\"polls_detail\")\n    ]\n\n\nWriting the views\n++++++++++++++++++++++++\n\nWe will now write the :code:`polls_list` and :code:`polls_detail`\n\n.. code-block:: python\n\n    from django.shortcuts import render, get_object_or_404\n    from django.http import JsonResponse\n\n    from .models import Poll\n\n    def polls_list(request):\n        MAX_OBJECTS = 20\n        polls = Poll.objects.all()[:MAX_OBJECTS]\n        data = {\"results\": list(polls.values(\"question\", \"created_by__username\", \"pub_date\"))}\n        return JsonResponse(data)\n\n\n    def polls_detail(request, pk):\n        poll = get_object_or_404(Poll, pk=pk)\n        data = {\"results\": {\n            \"question\": poll.question,\n            \"created_by\": poll.created_by.username,\n            \"pub_date\": poll.pub_date\n        }}\n        return JsonResponse(data)\n\nThis should be standard Django for you. :code:`polls = Poll.objects.all()[:20]` gets us upto 20 :code:`Poll` objects.\nWe get a list of dictionaries using :code:`{\"results\": list(polls.values(\"question\", \"created_by__username\", \"pub_date\"))}` and return it with a :code:`JsonResponse`. A :code:`JsonResponse` is a like :code:`HttpResponse` with :code:`content-type=application/json`.\n\nSimilarly, `polls_detail` gets a specific Poll using :code:`get_object_or_404(Poll, pk=pk)`, and returns it wrapped in :code:`JsonResponse`.\n\n\nUsing the API\n++++++++++++++++++++++++\n\nYou can now access the API using curl, wget, postman, browser or any other API consuming tools. Here is the response with curl.\n\n.. code-block:: bash\n\n    $ curl http://localhost:8000/polls/\n\n    {\"results\": [{\"pk\": 1, \"question\": \"What is the weight of an unladen swallow?\", \"created_by__username\": \"shabda\", \"pub_date\": \"2018-03-12T10:14:19.002Z\"}, {\"pk\": 2, \"question\": \"What do you prefer, Flask or Django?\", \"created_by__username\": \"shabda\", \"pub_date\": \"2018-03-12T10:15:55.949Z\"}, {\"pk\": 3, \"question\": \"What is your favorite vacation spot?\", \"created_by__username\": \"shabda\", \"pub_date\": \"2018-03-12T10:16:11.998Z\"}]}\n\nYou should consider using postman or a similar tool. This is how your API looks in Postman.\n\n.. image:: postman_polls_detail.png\n\n\nWhy do we need DRF?\n++++++++++++++++++++++++\n\n**(DRF = Django Rest Framework)**\n\nWe were able to build the API with just Django, without using DRF, so why do we need DRF?\nAlmost always, you will need common tasks with your APIs, such as access control, serialization, rate limiting and more.\n\nDRF provides a well thought out set of base components and convenient hook points for building APIs. We will be using DRF in the rest of the chapters.\n"
  },
  {
    "path": "docs/conf.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# Building API Django documentation build configuration file, created by\n# sphinx-quickstart on Thu Apr 23 19:31:51 2015.\n#\n# This file is execfile()d with the current directory set to its\n# containing dir.\n#\n# Note that not all possible configuration values are present in this\n# autogenerated file.\n#\n# All configuration values have a default; values that are commented out\n# serve to show the default.\n\nimport sys\nimport os\nimport shlex\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#sys.path.insert(0, os.path.abspath('.'))\n\n# -- General configuration ------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = []\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix(es) of source filenames.\n# You can specify multiple suffix as a list of string:\n# source_suffix = ['.rst', '.md']\nsource_suffix = '.rst'\n\n# The encoding of source files.\n#source_encoding = 'utf-8-sig'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# General information about the project.\nproject = u'Building API Django'\ncopyright = u'2015-2018, Agiliq'\nauthor = u'Agiliq'\n\n# The version info for the project you're documenting, acts as replacement for\n# |version| and |release|, also used in various other places throughout the\n# built documents.\n#\n# This will track the Django version against which this is written.\nversion = '2.0'\n# The full version, including alpha/beta/rc tags.\nrelease = '2.0'\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#\n# This is also used if you do content translation via gettext catalogs.\n# Usually you set \"language\" from the command line for these cases.\nlanguage = None\n\n# There are two options for replacing |today|: either, you set today to some\n# non-false value, then it is used:\n#today = ''\n# Else, today_fmt is used as the format for a strftime call.\n#today_fmt = '%B %d, %Y'\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\nexclude_patterns = ['_build']\n\n# The reST default role (used for this markup: `text`) to use for all\n# documents.\n#default_role = None\n\n# If true, '()' will be appended to :func: etc. cross-reference text.\n#add_function_parentheses = True\n\n# If true, the current module name will be prepended to all description\n# unit titles (such as .. function::).\n#add_module_names = True\n\n# If true, sectionauthor and moduleauthor directives will be shown in the\n# output. They are ignored by default.\n#show_authors = False\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\n\n# A list of ignored prefixes for module index sorting.\n#modindex_common_prefix = []\n\n# If true, keep warnings as \"system message\" paragraphs in the built documents.\n#keep_warnings = False\n\n# If true, `todo` and `todoList` produce output, else they produce nothing.\ntodo_include_todos = False\n\n\n# -- Options for HTML output ----------------------------------------------\nhtml_theme = 'sphinx_rtd_theme'\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#html_theme_options = {}\n\n# Add any paths that contain custom themes here, relative to this directory.\n#html_theme_path = []\n\n# The name for this set of Sphinx documents.  If None, it defaults to\n# \"<project> v<release> documentation\".\n#html_title = None\n\n# A shorter title for the navigation bar.  Default is the same as html_title.\n#html_short_title = None\n\n# The name of an image file (relative to this directory) to place at the top\n# of the sidebar.\n#html_logo = None\n\n# The name of an image file (within the static path) to use as favicon of the\n# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32\n# pixels large.\n#html_favicon = None\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\n\n# Add any extra paths that contain custom files (such as robots.txt or\n# .htaccess) here, relative to this directory. These files are copied\n# directly to the root of the documentation.\n#html_extra_path = []\n\n# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,\n# using the given strftime format.\n#html_last_updated_fmt = '%b %d, %Y'\n\n# If true, SmartyPants will be used to convert quotes and dashes to\n# typographically correct entities.\n#html_use_smartypants = True\n\n# Custom sidebar templates, maps document names to template names.\n#html_sidebars = {}\n\n# Additional templates that should be rendered to pages, maps page names to\n# template names.\n#html_additional_pages = {}\n\n# If false, no module index is generated.\n#html_domain_indices = True\n\n# If false, no index is generated.\n#html_use_index = True\n\n# If true, the index is split into individual pages for each letter.\n#html_split_index = False\n\n# If true, links to the reST sources are added to the pages.\n#html_show_sourcelink = True\n\n# If true, \"Created using Sphinx\" is shown in the HTML footer. Default is True.\n#html_show_sphinx = True\n\n# If true, \"(C) Copyright ...\" is shown in the HTML footer. Default is True.\n#html_show_copyright = True\n\n# If true, an OpenSearch description file will be output, and all pages will\n# contain a <link> tag referring to it.  The value of this option must be the\n# base URL from which the finished HTML is served.\n#html_use_opensearch = ''\n\n# This is the file name suffix for HTML files (e.g. \".xhtml\").\n#html_file_suffix = None\n\n# Language to be used for generating the HTML full-text search index.\n# Sphinx supports the following languages:\n#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'\n#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'\n#html_search_language = 'en'\n\n# A dictionary with options for the search language support, empty by default.\n# Now only 'ja' uses this config value\n#html_search_options = {'type': 'default'}\n\n# The name of a javascript file (relative to the configuration directory) that\n# implements a search results scorer. If empty, the default will be used.\n#html_search_scorer = 'scorer.js'\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'BuildingAPIDjangodoc'\n\n# -- Options for LaTeX output ---------------------------------------------\n\nlatex_elements = {\n# The paper size ('letterpaper' or 'a4paper').\n#'papersize': 'letterpaper',\n\n# The font size ('10pt', '11pt' or '12pt').\n#'pointsize': '10pt',\n\n# Additional stuff for the LaTeX preamble.\n#'preamble': '',\n\n# Latex figure (float) alignment\n#'figure_align': 'htbp',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n  (master_doc, 'BuildingAPIDjango.tex', u'Building APIs with Django and Django Rest Framework',\n   u'Agiliq', 'manual'),\n]\n\n# The name of an image file (relative to this directory) to place at the top of\n# the title page.\n#latex_logo = None\n\n# For \"manual\" documents, if this is true, then toplevel headings are parts,\n# not chapters.\n#latex_use_parts = False\n\n# If true, show page references after internal links.\n#latex_show_pagerefs = False\n\n# If true, show URL addresses after external links.\n#latex_show_urls = False\n\n# Documents to append as an appendix to all manuals.\n#latex_appendices = []\n\n# If false, no module index is generated.\n#latex_domain_indices = True\n\n\n# -- Options for manual page output ---------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    (master_doc, 'buildingapidjango', u'Building API Django Documentation',\n     [author], 1)\n]\n\n# If true, show URL addresses after external links.\n#man_show_urls = False\n\n\n# -- Options for Texinfo output -------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n  (master_doc, 'BuildingAPIDjango', u'Building API Django Documentation',\n   author, 'BuildingAPIDjango', 'One line description of project.',\n   'Miscellaneous'),\n]\n\n# Documents to append as an appendix to all manuals.\n#texinfo_appendices = []\n\n# If false, no module index is generated.\n#texinfo_domain_indices = True\n\n# How to display URL addresses: 'footnote', 'no', or 'inline'.\n#texinfo_show_urls = 'footnote'\n\n# If true, do not generate a @detailmenu in the \"Top\" node's menu.\n#texinfo_no_detailmenu = False\n"
  },
  {
    "path": "docs/index.rst",
    "content": "Building APIs with Django and Django Rest Framework\n======================================================\n\nBuilding APIs with Django and DRF takes over where the Django tutorials stop.\nIn the Django tutorials, you built a regular Django polls app. We will rebuild an API for a similar app.\n\nIn the chapters to come, we will build a REST(ish) api with authorization, rate limiting, first with pure Django and then with DRF.\nWe will cover testing, continuous integration, documentation tools and API collaboration tools.\n\n.. image:: cover.jpg\n\nChapters:\n\n.. toctree::\n   :maxdepth: 2\n\n   introduction\n   setup-models-admin\n   apis-without-drf\n   serailizers\n   views-and-generic-views\n   more-views-and-viewsets\n   access-control\n   testing-and-ci\n\n\nAppendix\n==================\n\n.. toctree::\n   :maxdepth: 2\n\n   postman\n   swagger\n\n\n* :ref:`genindex`\n* :ref:`modindex`\n* :ref:`search`\n\n"
  },
  {
    "path": "docs/introduction.rst",
    "content": "Introductions\n=================\n\n*Building APIs with Django and Django Rest Framework* starts where the `Django \"Polls\" tutorial <https://docs.djangoproject.com/en/2.0/intro/tutorial01/>`_ stops, and takes you through building the polls app, but this time using APIs. You will learn the basics of Django Rest Framework including serialization, views, generic views, viewsets, testing, access control. You will also learn about API documentation using swagger and raml.\n\nWho is this book for?\n-------------------------\n\nIf you have finished the Django \"Polls\" tutorial, and want to learn using DRF to build APIs, this book is perfect for you. This book assumes some knowledge of Django and Python, which you should have built if you have finished the \"Poll\" turtorial. No existing knowledge of DRF is assumed.\n\n\nHow to read this book?\n-------------------------\n\nThe chapters are meant to be read in order. If you have existing knowledge of some chapters, you can quickly go through that chapter, but I highly recommend reading them in order as each chapter builds on the previous.\n\n\n"
  },
  {
    "path": "docs/make.bat",
    "content": "@ECHO OFF\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sphinx-build\r\n)\r\nset BUILDDIR=_build\r\nset ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .\r\nset I18NSPHINXOPTS=%SPHINXOPTS% .\r\nif NOT \"%PAPER%\" == \"\" (\r\n\tset ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%\r\n\tset I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%\r\n)\r\n\r\nif \"%1\" == \"\" goto help\r\n\r\nif \"%1\" == \"help\" (\r\n\t:help\r\n\techo.Please use `make ^<target^>` where ^<target^> is one of\r\n\techo.  html       to make standalone HTML files\r\n\techo.  dirhtml    to make HTML files named index.html in directories\r\n\techo.  singlehtml to make a single large HTML file\r\n\techo.  pickle     to make pickle files\r\n\techo.  json       to make JSON files\r\n\techo.  htmlhelp   to make HTML files and a HTML help project\r\n\techo.  qthelp     to make HTML files and a qthelp project\r\n\techo.  devhelp    to make HTML files and a Devhelp project\r\n\techo.  epub       to make an epub\r\n\techo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\r\n\techo.  text       to make text files\r\n\techo.  man        to make manual pages\r\n\techo.  texinfo    to make Texinfo files\r\n\techo.  gettext    to make PO message catalogs\r\n\techo.  changes    to make an overview over all changed/added/deprecated items\r\n\techo.  xml        to make Docutils-native XML files\r\n\techo.  pseudoxml  to make pseudoxml-XML files for display purposes\r\n\techo.  linkcheck  to check all external links for integrity\r\n\techo.  doctest    to run all doctests embedded in the documentation if enabled\r\n\techo.  coverage   to run coverage check of the documentation if enabled\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"clean\" (\r\n\tfor /d %%i in (%BUILDDIR%\\*) do rmdir /q /s %%i\r\n\tdel /q /s %BUILDDIR%\\*\r\n\tgoto end\r\n)\r\n\r\n\r\nREM Check if sphinx-build is available and fallback to Python version if any\r\n%SPHINXBUILD% 2> nul\r\nif errorlevel 9009 goto sphinx_python\r\ngoto sphinx_ok\r\n\r\n:sphinx_python\r\n\r\nset SPHINXBUILD=python -m sphinx.__init__\r\n%SPHINXBUILD% 2> nul\r\nif errorlevel 9009 (\r\n\techo.\r\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\r\n\techo.installed, then set the SPHINXBUILD environment variable to point\r\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\r\n\techo.may add the Sphinx directory to PATH.\r\n\techo.\r\n\techo.If you don't have Sphinx installed, grab it from\r\n\techo.http://sphinx-doc.org/\r\n\texit /b 1\r\n)\r\n\r\n:sphinx_ok\r\n\r\n\r\nif \"%1\" == \"html\" (\r\n\t%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/html.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"dirhtml\" (\r\n\t%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"singlehtml\" (\r\n\t%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"pickle\" (\r\n\t%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can process the pickle files.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"json\" (\r\n\t%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can process the JSON files.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"htmlhelp\" (\r\n\t%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can run HTML Help Workshop with the ^\r\n.hhp project file in %BUILDDIR%/htmlhelp.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"qthelp\" (\r\n\t%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can run \"qcollectiongenerator\" with the ^\r\n.qhcp project file in %BUILDDIR%/qthelp, like this:\r\n\techo.^> qcollectiongenerator %BUILDDIR%\\qthelp\\BuildingAPIDjango.qhcp\r\n\techo.To view the help file:\r\n\techo.^> assistant -collectionFile %BUILDDIR%\\qthelp\\BuildingAPIDjango.ghc\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"devhelp\" (\r\n\t%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"epub\" (\r\n\t%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The epub file is in %BUILDDIR%/epub.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latex\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; the LaTeX files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latexpdf\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tcd %BUILDDIR%/latex\r\n\tmake all-pdf\r\n\tcd %~dp0\r\n\techo.\r\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latexpdfja\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tcd %BUILDDIR%/latex\r\n\tmake all-pdf-ja\r\n\tcd %~dp0\r\n\techo.\r\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"text\" (\r\n\t%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The text files are in %BUILDDIR%/text.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"man\" (\r\n\t%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The manual pages are in %BUILDDIR%/man.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"texinfo\" (\r\n\t%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"gettext\" (\r\n\t%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The message catalogs are in %BUILDDIR%/locale.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"changes\" (\r\n\t%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.The overview file is in %BUILDDIR%/changes.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"linkcheck\" (\r\n\t%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Link check complete; look for any errors in the above output ^\r\nor in %BUILDDIR%/linkcheck/output.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"doctest\" (\r\n\t%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Testing of doctests in the sources finished, look at the ^\r\nresults in %BUILDDIR%/doctest/output.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"coverage\" (\r\n\t%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Testing of coverage in the sources finished, look at the ^\r\nresults in %BUILDDIR%/coverage/python.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"xml\" (\r\n\t%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The XML files are in %BUILDDIR%/xml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"pseudoxml\" (\r\n\t%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.\r\n\tgoto end\r\n)\r\n\r\n:end\r\n"
  },
  {
    "path": "docs/more-views-and-viewsets.rst",
    "content": "More views and viewsets\n======================================\n\nA better URL structure\n-----------------------------\n\nWe have three API endpoints\n\n- :code:`/polls/` and :code:`/polls/<pk>/`\n- :code:`/choices/`\n- :code:`/vote/`\n\nThey get the work done, but we can make our API more intuitive by nesting them correctly. Our redesigned urls look like this:\n\n- :code:`/polls/` and :code:`/polls/<pk>`\n- :code:`/polls/<pk>/choices/` to GET the choices for a specific poll, and to create choices for a specific poll. (Idenitfied by the :code:`<pk>`)\n- :code:`/polls/<pk>/choices/<choice_pk>/vote/` - To vote for the choice identified by :code:`<choice_pk>` under poll with :code:`<pk>`.\n\nChanging the views\n-----------------------------\n\nWe will make changes to :code:`ChoiceList` and :code:`CreateVote`, because the :code:`/polls/` and :code:`/polls/<pk>` have not changed.\n\n.. code-block:: python\n\n    from rest_framework import generics\n    from rest_framework.views import APIView\n    from rest_framework import status\n    from rest_framework.response import Response\n\n    from .models import Poll, Choice\n    from .serializers import PollSerializer, ChoiceSerializer, VoteSerializer\n\n    # ...\n    # PollList and PollDetail views\n\n    class ChoiceList(generics.ListCreateAPIView):\n        def get_queryset(self):\n            queryset = Choice.objects.filter(poll_id=self.kwargs[\"pk\"])\n            return queryset\n        serializer_class = ChoiceSerializer\n\n\n    class CreateVote(APIView):\n        serializer_class = VoteSerializer\n        \n        def post(self, request, pk, choice_pk):\n            voted_by = request.data.get(\"voted_by\")\n            data = {'choice': choice_pk, 'poll': pk, 'voted_by': voted_by}\n            serializer = VoteSerializer(data=data)\n            if serializer.is_valid():\n                vote = serializer.save()\n                return Response(serializer.data, status=status.HTTP_201_CREATED)\n            else:\n                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n\nAnd change your urls.py to a nested structure.\n\n.. code-block:: python\n\n    #...\n    urlpatterns = [\n        path(\"polls/<int:pk>/choices/\", ChoiceList.as_view(), name=\"choice_list\"),\n        path(\"polls/<int:pk>/choices/<int:choice_pk>/vote/\", CreateVote.as_view(), name=\"create_vote\"),\n\n    ]\n\n\nYou can see the changes by doing a GET to :code:`http://localhost:8000/polls/1/choices/`, which should give you.\n\n.. code-block:: json\n\n    [\n        {\n            \"id\": 1,\n            \"votes\": [],\n            \"choice_text\": \"Flask\",\n            \"poll\": 1\n        },\n        {\n            \"id\": 2,\n            \"votes\": [\n            ],\n            \"choice_text\": \"Django\",\n            \"poll\": 1\n        }\n    ]\n\nYou can vote for choices 2, of poll 1 by doing a POST to :code:`http://localhost:8000/polls/1/choices/2/vote/` with data :code:`{\"voted_by\": 1}`.\n\n.. code-block:: json\n\n    {\n        \"id\": 2,\n        \"choice\": 2,\n        \"poll\": 1,\n        \"voted_by\": 1\n    }\n\nLets get back to :code:`ChoiceList`.\n\n.. code-block:: python\n\n    # urls.py\n    #...\n    urlpatterns = [\n        # ...\n        path(\"polls/<int:pk>/choices/\", ChoiceList.as_view(), name=\"choice_list\"),\n    ]\n\n    # apiviews.py\n    # ...\n\n    class ChoiceList(generics.ListCreateAPIView):\n        def get_queryset(self):\n            queryset = Choice.objects.filter(poll_id=self.kwargs[\"pk\"])\n            return queryset\n        serializer_class = ChoiceSerializer\n\nFrom the urls, we pass on :code:`pk` to :code:`ChoiceList`. We override the :code:`get_queryset` method, to filter on choices with this :code:`poll_id`, and let DRF handle the rest.\n\n\nAnd for :code:`CreateVote`,\n\n.. code-block:: python\n\n    # urls.py\n    #...\n    urlpatterns = [\n        # ...\n        path(\"polls/<int:pk>/choices/<int:choice_pk>/vote/\", CreateVote.as_view(), name=\"create_vote\"),\n    ]\n\n    # apiviews.py\n    # ...\n\n    class CreateVote(APIView):\n\n        def post(self, request, pk, choice_pk):\n            voted_by = request.data.get(\"voted_by\")\n            data = {'choice': choice_pk, 'poll': pk, 'voted_by': voted_by}\n            serializer = VoteSerializer(data=data)\n            if serializer.is_valid():\n                serializer.save()\n                return Response(serializer.data, status=status.HTTP_201_CREATED)\n            else:\n                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n\nWe pass on poll id and choice id. We subclass this from :code:`APIView`, rather than a generic view, because we competely customize the behaviour. This is similar to our earlier :code:`APIView`, where in we are passing the data to a serializer, and saving or returning an error depending on whether the serializer is valid.\n\nIntroducing Viewsets and Routers\n-----------------------------------\n\nOur urls are looking good, and we have a views with very little code duplication, but we can do better.\n\nThe :code:`/polls/` and :code:`/polls/<pk>/` urls require two view classes, with the same serializer and base queryset. We can group them into a viewset, and connect them to the urls using a router.\n\nThis is what it will look like:\n\n.. code-block:: python\n\n    # urls.py\n    # ...\n    from rest_framework.routers import DefaultRouter\n    from .apiviews import PollViewSet\n\n\n    router = DefaultRouter()\n    router.register('polls', PollViewSet, basename='polls')\n\n\n    urlpatterns = [\n        # ...\n    ]\n\n    urlpatterns += router.urls\n\n    # apiviews.py\n    # ...\n    from rest_framework import viewsets\n\n    from .models import Poll, Choice\n    from .serializers import PollSerializer, ChoiceSerializer, VoteSerializer\n\n\n    class PollViewSet(viewsets.ModelViewSet):\n        queryset = Poll.objects.all()\n        serializer_class = PollSerializer\n\nThere is no change at all to the urls or to the responses. You can verify this by doing a GET to\n:code:`/polls/` and :code:`/polls/<pk>/`.\n\n\nChoosing the base class to use\n-----------------------------------\n\nWe have seen 4 ways to build API views until now\n\n- Pure Django views\n- :code:`APIView` subclasses\n- :code:`generics.*` subclasses\n- :code:`viewsets.ModelViewSet`\n\nSo which one should you use when? My rule of thumb is,\n\n- Use :code:`viewsets.ModelViewSet` when you are going to allow all or most of CRUD operations on a model.\n- Use :code:`generics.*` when you only want to allow some operations on a model\n- Use :code:`APIView` when you want to completely customize the behaviour.\n\nNext steps\n-----------------\n\nIn the next chapter, we will look at adding access control to our apis.\n"
  },
  {
    "path": "docs/postman.rst",
    "content": "Testing and Using API with Postman\n==========================================\n\nIn this chapter, we'll learn how to use the Postman app for testing our APIs.\n\nPostman can be installed from `the Postman site <https://www.getpostman.com/>`_. It is a versatile tool for working with APIs.\n\nIn this books, you will be creating and using APIs. We'll see how we can make use of Postman for this.\n\n\nMaking HTTP request\n------------------------\n\nPostman is pretty intutive, but the image below should make the app easy to understand.\n\n.. image:: postman.png\n\nThere are 4 key elements in making an HTTP request.\n\n1. URL:\n    This specifies to which URL we need to make a request for. In other terms where our API endpoint resides.\n\n2. Method:\n    Each API endpoint has a method which serves it's purpose. The methods for eg., can be GET for retrieving some data, POST for creating or updating, DELETE for deleting a record.\n\n3. Headers:\n    Headers provide required information about the request or the response or about the object sent in the body. Some times we use authentication headers too, in order to access the API endpoint.\n\n4. Body:\n    The request body is where we send the object. The object which may be required for the service.\n\n\nResponse\n------------\n\nResponse is available in the bottom section, usually in a JSON format, but may also vary depending up on the API service.\n\n\nCollections\n--------------\n\nWe can save all the relative API endpoints to collections. In our example, we can save all our polls related endpoints as a collection or all the users related endpoints as another collection. This way all the APIs are organized.\n\n\nAuthentication\n---------------\n\nPostman also supports few authentication mechanisms like Basic Auth, Digest Auth and Oauth1. This allows us to use these authentication methods for the APIs.\n"
  },
  {
    "path": "docs/serailizers.rst",
    "content": "Serializing and Deserializing Data\n========================================\n\nDRF makes the process of building web API's simple and flexible. With batteries included,\nit comes with well designed base classes which allows us to serialize and deserialize data.\n\n\nSerialization and Deserialization\n--------------------------------------\n\nThe first thing we need for our API is to provide a way to serialize model instances into representations. Serialization is the process of making a streamable representation of the data which we can transfer over the network. Deserialization is its reverse process.\n\n\nCreating Serializers\n-----------------------\n\nLets get started with creating serializer classes which will serialize and deserialize the model instances to json representations. Create a file named :code:`polls/serializers.py`. We will use :code:`ModelSerializer` which will reduce code duplication by automatically determing the set of fields and by creating implementations of the :code:`create()` and :code:`update()` methods.\n\nOur :code:`polls/serializers.py` looks like this.\n\n.. code-block:: python\n\n    from rest_framework import serializers\n\n    from .models import Poll, Choice, Vote\n\n\n    class VoteSerializer(serializers.ModelSerializer):\n        class Meta:\n            model = Vote\n            fields = '__all__'\n\n\n    class ChoiceSerializer(serializers.ModelSerializer):\n        votes = VoteSerializer(many=True, required=False)\n\n        class Meta:\n            model = Choice\n            fields = '__all__'\n\n\n    class PollSerializer(serializers.ModelSerializer):\n        choices = ChoiceSerializer(many=True, read_only=True, required=False)\n\n        class Meta:\n            model = Poll\n            fields = '__all__'\n\n\nThe :code:`PollSerializer` in detail\n----------------------------------------\n\nOur :code:`PollSerializer` looks like this.\n\n.. code-block:: python\n\n    ...\n\n    class PollSerializer(serializers.ModelSerializer):\n        choices = ChoiceSerializer(many=True, read_only=True, required=False)\n\n        class Meta:\n            model = Poll\n            fields = '__all__'\n\nWhat have we got with this? The :code:`PollSerializer` class has a number of methods,\n\n* A :code:`is_valid(self, ..)` method which can tell if the data is sufficient and valid to create/update a model instance.\n* A :code:`save(self, ..)` method, which knows how to create or update an instance.\n* A :code:`create(self, validated_data, ..)` method which knows how to create an instance. This method can be overriden to customize the create behaviour.\n* A :code:`update(self, instance, validated_data, ..)` method which knows how to update an instance. This method can be overriden to customize the update behaviour.\n\n\nUsing the :code:`PollSerializer`\n----------------------------------------\n\nLet's use the serializer to create a :code:`Poll` object.\n\n.. code-block:: ipython\n\n    In [1]: from polls.serializers import PollSerializer\n\n    In [2]: from polls.models import Poll\n\n    In [3]: poll_serializer = PollSerializer(data={\"question\": \"Mojito or Caipirinha?\", \"created_by\": 1})\n\n    In [4]: poll_serializer.is_valid()\n    Out[4]: True\n\n    In [5]: poll = poll_serializer.save()\n\n    In [6]: poll.pk\n    Out[6]: 5\n\n\nThe :code:`poll.pk` line tells us that the object has been commited to the DB. You can also use the serializer to update a :code:`Poll` object. ::\n\n\n    In [9]: poll_serializer = PollSerializer(instance=poll, data={\"question\": \"Mojito, Caipirinha or margarita?\", \"created_by\": 1})\n\n    In [10]: poll_serializer.is_valid()\n    Out[10]: True\n\n    In [11]: poll_serializer.save()\n    Out[11]: <Poll: Mojito, Caipirinha or margarita?>\n\n    In [12]: Poll.objects.get(pk=5).question\n    Out[12]: 'Mojito, Caipirinha or margarita?'\n\nWe can see that calling save on a Serializer with instance causes that instance to be updated. :Code:`Poll.objects.get(pk=5).question` verifies that the Poll was updated.\n\n\nIn the next chapter, we will use the serializers to write views.\n"
  },
  {
    "path": "docs/setup-models-admin.rst",
    "content": "Setup, Models and Admin\n=============================\n\nIn this tutorial we will walk through a process of creating an API for a basic poll application. We will be using Python 3.6.x, Django 2.0.x and Django Rest Framework 3.7.x for creating API.\n\nFirst things first, let's install the required modules within a virtual environment.\n\n.. code-block:: python\n\n    mkvirtualenv pollsapi\n    pip install Django\n    pip install djangorestframework\n\nCreating a project\n--------------------\n\nEarliest in order, to create a project we should move to the directory where we would like to store our code. For this go to command line and use cd command. Then trigger the startproject command.\n\n.. code-block:: python\n\n    django-admin startproject pollsapi\n\nThis command gives us a 'pollsapi' directoy. The contents of this directory look like this::\n\n    manage.py\n\n    pollsapi/\n        __init__.py\n        settings.py\n        urls.py\n        wsgi.py\n\nDatabase setup\n------------------\n\nWe will use SQlite database, which is already included with Python. The :code:`pollsapi/settings.py` file would already have the correct settings.\n\n.. code-block:: python\n\n    DATABASES = {\n        'default': {\n            'ENGINE': 'django.db.backends.sqlite3',\n            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),\n        }\n    }\n\nNow, use the migrate command which builds the needed database tables in regard to the :code:`django_pollsapi/settings.py` file.\n\n.. code-block:: python\n\n    python manage.py migrate\n\n\nCreating models\n---------------------\n\nBefore creating our database models, let us create our pollsapi App.\n\n.. code-block:: python\n\n    python manage.py startapp polls\n\nThe above command results in a 'polls' directory containing different files::\n\n    admin.py\n    apps.py\n    models.py\n    tests.py\n    views.py\n\nStep in to 'models.py' file and start writing the models. For creating the polls api we are going to create a :code:`Poll` model, a :code:`Choice` model and a :code:`Vote` model. Once we are done with designing our models, the :code:`models.py` file should look like this:\n\nThese models are the same as you would have seen in the Django introduction tutorial.\n\n.. code-block:: python\n\n    from django.db import models\n    from django.contrib.auth.models import User\n\n\n    class Poll(models.Model):\n        question = models.CharField(max_length=100)\n        created_by = models.ForeignKey(User, on_delete=models.CASCADE)\n        pub_date = models.DateTimeField(auto_now=True)\n\n        def __str__(self):\n            return self.question\n\n\n    class Choice(models.Model):\n        poll = models.ForeignKey(Poll, related_name='choices', on_delete=models.CASCADE)\n        choice_text = models.CharField(max_length=100)\n\n        def __str__(self):\n            return self.choice_text\n\n\n    class Vote(models.Model):\n        choice = models.ForeignKey(Choice, related_name='votes', on_delete=models.CASCADE)\n        poll = models.ForeignKey(Poll, on_delete=models.CASCADE)\n        voted_by = models.ForeignKey(User, on_delete=models.CASCADE)\n\n        class Meta:\n            unique_together = (\"poll\", \"voted_by\")\n\n\nThe above models have been designed in such a way that, it would make our API bulding a smooth process.\n\nActivating models\n----------------------\n\nWith the simple lines of code in the 'models.py' Django can create a database schema and a Python database-access API which has the capability to access the objects of Poll, Choice, Vote. To create the database tables to our models, 'rest_framework' and 'polls' app needs to be added to the \"INSTALLED_APPS\" in the 'django_pollsapi/settings' file.\n\n.. code-block:: python\n\n    INSTALLED_APPS = (\n    ...\n    'rest_framework',\n    'polls',\n    )\n\nNow, run the :code:`makemigrations` command which will notify Django that new models have been created and those changes needs to be applied to the migration. Run :code:`migrate` command to do the actual migration.\n\n.. code-block:: bash\n\n    $ python manage.py makemigrations polls\n\n    $ python manage.py migrate\n\n\n\nCreate an empty :code:`urls.py` in your :code:`polls` app.\n\n.. code-block:: python\n\n    urlpatterns = [\n    ]\n\n\n\nGo to :code:`pollsapi/urls.py` and include the polls urls.\n\n.. code-block:: python\n    \n    from django.urls import include, re_path\n    \n    urlpatterns = [\n        re_path(r'^', include('polls.urls')),\n    ]\n\nNow you can runserver ::\n\n    $ python manage.py runserver\n\n\nGoto any browser of your choice and hit the url :code:`http://127.0.0.1:8000`\n\nAnd we are in business, with a Django *Congratulations* page greeting us. (Though we haven't added any API endpoints yet.)\n\n.. image:: congrats.png\n\nWe will be adding API endpoints for creating and viewing polls in the next chapter.\n\nSetting up the admin\n++++++++++++++++++++++\n\nYou should register :code:`Poll` and :code:`Choice` in the admin like this.\n\n.. code-block:: python\n\n    from django.contrib import admin\n\n    from .models import Poll, Choice\n\n    admin.site.register(Poll)\n    admin.site.register(Choice)\n"
  },
  {
    "path": "docs/swagger.rst",
    "content": "Documenting APIs (with Swagger and more)\n==========================================================\n\nIn this chapter we will see how to document our API.\n\nAs you build your API, you would need to document the API to collaborate with other people. In most companies and teams, the developer using the API is different from the one building them. API documentation and collaboration tools, become even more important in such an environment.\n\nSwagger is a tool used to understand the capabilities of the service without access to source code, documentation, or through network traffic inspection. In simple terms, with swagger you can see what all API end points are available for a web application. You can use swagger for testing the requests and responses of the API endpoints.\n\nDRF comes with its own tool, coreapi, for documenting and interacting with the API.\n\nWe will use both coreapi and swagger to document our API.\n\n\n\nAdding swagger documentation\n-----------------------------\n\nInstall django-rest-swagger\n\n.. code-block:: bash\n\n    pip install django-rest-swagger\n\nUpdate your :code:`settings.py`\n\n.. code-block:: python\n\n    INSTALLED_APPS = [\n        # ...\n        'polls',\n        'rest_framework_swagger',\n    ]\n\nAdd swagger to your urls.\n\n.. code-block:: python\n\n    from rest_framework_swagger.views import get_swagger_view\n\n    schema_view = get_swagger_view(title='Polls API')\n\n    # ...\n    urlpatterns = [\n        # ...\n        path(r'swagger-docs/', schema_view),\n    ]\n\nNavigate to `/swagger-docs/`. And your swagger docs are ready in all their glory.\n\n.. image:: swagger.png\n\n\nUsing coreapi for documentation\n--------------------------------\n\n\nInstall coreapi\n\n.. code-block:: bash\n\n    pip install coreapi\n\n\nAdd coreapi urls to your urls.\n\n.. code-block:: python\n\n    from rest_framework.documentation import include_docs_urls\n    # ...\n\n    urlpatterns = [\n        # ...\n        path(r'docs/', include_docs_urls(title='Polls API')),\n    ]\n\nAnd your coreapi docs are ready in all their glory.\n\n.. image:: coreapi.png\n"
  },
  {
    "path": "docs/testing-and-ci.rst",
    "content": "Testing and Continuous Integeration\n==========================================\n\n\nIn this chapter we will add test to our API.\n\nDRF provides a few important classes which makes testing APIs simpler. We will be using these classes later in the chapter in our tests.\n\n- :code:`APIRequestFactory`: This is similar to Django's :code:`RequestFactory`. It allows you to create requests with any http method, which you can then pass on to any view method and compare responses.\n- :code:`APIClient`: similar to Django's :code:`Client`. You can GET or POST a URL, and test responses.\n- :code:`APITestCase`: similar to Django's :code:`TestCase`. Most of your tests will subclass this.\n\nNow lets us write test cases to our polls application.\n\nCreating Test Requests\n------------------------\nDjango's 'Requestfactory' has the capability to create request instances which allow us in testing view functions individually. Django Rest Framework has a class called 'APIRequestFactory' which extends the standard Django's  'RequestFactory'. This class contains almost all the http verbs like .get(), .post(), .put(), .patch() et all.\n\nSyntax for Post request:\n\n.. code-block:: python\n\n    factory = APIRequestFactory()\n    request = factory.post(uri, post data)\n\nLets add a test for the polls list.\n\n.. code-block:: python\n\n    from rest_framework.test import APITestCase\n    from rest_framework.test import APIRequestFactory\n\n    from polls import apiviews\n\n\n    class TestPoll(APITestCase):\n        def setUp(self):\n            self.factory = APIRequestFactory()\n            self.view = apiviews.PollViewSet.as_view({'get': 'list'})\n            self.uri = '/polls/'\n\n        def test_list(self):\n            request = self.factory.get(self.uri)\n            response = self.view(request)\n            self.assertEqual(response.status_code, 200,\n                             'Expected Response Code 200, received {0} instead.'\n                             .format(response.status_code))\n\n\n\nIn the above lines of code, we are trying to access the PollList view. We are asserting that the HTTP response code is 200.\n\nNow run the test command.\n\n.. code-block:: python\n\n    python manage.py test\n\nAnd it will display the below message.\n\n.. code-block:: bash\n\n    Creating test database for alias 'default'...\n    System check identified no issues (0 silenced).\n    F\n    ======================================================================\n    FAIL: test_list (polls.tests.TestPoll)\n    ----------------------------------------------------------------------\n    Traceback (most recent call last):\n      File \"/Users/shabda/repos/building-api-django/pollsapi/polls/tests.py\", line 19, in test_list\n        .format(response.status_code))\n    AssertionError: 401 != 200 : Expected Response Code 200, received 401 instead.\n\n    ----------------------------------------------------------------------\n    Ran 1 test in 0.002s\n\n    FAILED (failures=1)\n    Destroying test database for alias 'default'...\n\nOuch! Our test failed. This happened because the view is not accessible without authentication. So we need to create a user and test the view after getting authenticated.\n\n\nTesting APIs with authentication\n------------------------------------\n\nTo test apis with authentication, a test user needs to be created so that we can make requests in context of that user. Let's create a test user. Change your tests to\n\n.. code-block:: python\n\n    from django.contrib.auth import get_user_model\n    from rest_framework.authtoken.models import Token\n    # ...\n\n    class TestPoll(APITestCase):\n        def setUp(self):\n            # ...\n            self.user = self.setup_user()\n            self.token = Token.objects.create(user=self.user)\n            self.token.save()\n\n        @staticmethod\n        def setup_user():\n            User = get_user_model()\n            return User.objects.create_user(\n                'test',\n                email='testuser@test.com',\n                password='test'\n            )\n\n        def test_list(self):\n            request = self.factory.get(self.uri, \n                HTTP_AUTHORIZATION='Token {}'.format(self.token.key))\n            request.user = self.user\n            response = self.view(request)\n            self.assertEqual(response.status_code, 200,\n                             'Expected Response Code 200, received {0} instead.'\n                             .format(response.status_code))\n\n\nNow run the test command.\n\n.. code-block:: python\n\n    python manage.py test\n\nYou should get this response\n\n.. code-block:: bash\n\n    Creating test database for alias 'default'...\n    System check identified no issues (0 silenced).\n    .\n    ----------------------------------------------------------------------\n    Ran 1 test in 0.119s\n\n    OK\n    Destroying test database for alias 'default'...\n\nUsing :code:`APIClient`\n--------------------------\n\nThe same test can be written using :code:`APIClient`. It has :code:`get`, :code:`.post` and family. Unlike creating requests first, with :code:`APIClient` you can GET or POST to a url directly and get a response.\n\nAdd a test like this:\n\n.. code-block:: python\n\n    from rest_framework.test import APIClient\n\n    # ...\n\n\n    class TestPoll(APITestCase):\n        def setUp(self):\n            self.client = APIClient()\n            # ...\n\n        # ...\n        def test_list2(self):\n            response = self.client.get(self.uri)\n            self.assertEqual(response.status_code, 200,\n                             'Expected Response Code 200, received {0} instead.'\n                             .format(response.status_code))\n\nLet us test it now.\n\n.. code-block:: bash\n\n    python manage.py test polls.tests.TestPoll\n\n\n    Creating test database for alias 'default'...\n    System check identified no issues (0 silenced).\n    F\n    ======================================================================\n    FAIL: test_list2 (polls.tests.TestPoll)\n    ----------------------------------------------------------------------\n    Traceback (most recent call last):\n      File \"/Users/shabda/repos/building-api-django/pollsapi/polls/tests.py\", line 37, in test_list2\n        .format(response.status_code))\n    AssertionError: 401 != 200 : Expected Response Code 200, received 401 instead.\n\n    ----------------------------------------------------------------------\n    Ran 1 test in 0.136s\n\n    FAILED (failures=1)\n    Destroying test database for alias 'default'...\n\nWe are seeing the same failure we saw in the test with :code:`APIRequestFactory`. You can login a :code:`APIClient` by calling\n:code:`APIClient.login`. Lets update the test.\n\n.. code-block:: python\n\n    class TestPoll(APITestCase):\n        # ...\n\n        def test_list2(self):\n            self.client.login(username=\"test\", password=\"test\")\n            response = self.client.get(self.uri)\n            self.assertEqual(response.status_code, 200,\n                             'Expected Response Code 200, received {0} instead.'\n                             .format(response.status_code))\n\n.. code-block:: bash\n\n    python manage.py test polls.tests.TestPoll\n    Creating test database for alias 'default'...\n    System check identified no issues (0 silenced).\n    .\n    ----------------------------------------------------------------------\n    Ran 1 test in 0.260s\n\n    OK\n    Destroying test database for alias 'default'...\n\nVoilà! The test passed successfully.\n\n:code:`.post` and create\n--------------------------------------------------\n\nWe now know how to test our GET APIs. We can use the :code:`APIClient` with :code:`.post` method this time.\n\nLet us try creating a new poll by sending the 'question', and 'created_by' parameters which are needs in the POST method. The test function looks as follows.\n\n.. code-block:: python\n\n\n    class TestPoll(APITestCase):\n\n        # ...\n        def test_create(self):\n            self.client.login(username=\"test\", password=\"test\")\n            params = {\n                \"question\": \"How are you?\",\n                \"created_by\": 1\n                }\n            response = self.client.post(self.uri, params)\n            self.assertEqual(response.status_code, 201,\n                             'Expected Response Code 201, received {0} instead.'\n                             .format(response.status_code))\n\n\nWe are asserting that the the http code is 201 if the test passes succesfully. Lets run the tests.\n\n.. code-block:: bash\n\n    python manage.py test polls.tests.TestPoll.test_create\n\n    Creating test database for alias 'default'...\n    System check identified no issues (0 silenced).\n    .\n    ----------------------------------------------------------------------\n    Ran 1 test in 0.267s\n\n    OK\n    Destroying test database for alias 'default'...\n\n\nTime to celebrate with the API :)\n\n\nContinuous integration with CircleCI\n---------------------------------------\n\nWe have the tests, but we also want it to run on every commit. If you are using Github, CircleCI provides a very well in integrated service to run your tests. We will use Circleci. v2\n\nWe can configure our application to use Circle CI  by adding a file named :code:`.circleci/config.yml` which is a YAML(a human-readable data serialization format) text file. It automatically detects when a commit has been made and pushed to a Github repository that is using CircleCI, and each time this happens, it will try to build the project and runs tests. The build failure or success is notified to the developer.\n\nSetting up CircleCI\n---------------------------------------\n\n- Sign-in: To get started with Circle CI we can sign-in with our github account on circleci.com.\n- Activate Github webhook: Once the Signup process gets completed we need to enable the service hook in the github profile page.\n- Add .circle/config.yml: We should add the yml file to the project.\n\nWriting circle configuration file\n---------------------------------------\n\nIn order for circle CI to build our project we need to tell the system a little bit about it. we will be needed to add a file named :code:`.circleci/config.yml` to the root of our repository. We also need to create a :code:`pollsapi/requirements.txt` to define our dependencies.\n\nAdd this to your :code:`pollsapi/requirements.txt`\n\n.. code-block:: text\n\n    Django==2.0.3\n    djangorestframework==3.7.7\n\nAnd then add this to :code:`.circleci/config.yml`\n\n\n.. code-block:: yaml\n\n  version: 2\n  jobs:\n    build:\n      docker:\n        # specify the version you desire here\n        - image: circleci/python:3.6.1\n\n\n      working_directory: ~/repo\n\n      steps:\n        - checkout\n\n        # Download and cache dependencies\n        - restore_cache:\n            keys:\n            - v1-dependencies-{{ checksum \"pollsapi/requirements.txt\" }}\n            # fallback to using the latest cache if no exact match is found\n            - v1-dependencies-\n\n        - run:\n            name: install dependencies\n            command: |\n              python3 -m venv venv\n              . venv/bin/activate\n              pip install -r pollsapi/requirements.txt\n\n        - save_cache:\n            paths:\n              - ./venv\n            key: v1-dependencies-{{ checksum \"requirements.txt\" }}\n\n        - run:\n            name: run tests\n            command: |\n              . venv/bin/activate\n              cd pollsapi\n              python manage.py test\n\n        - store_artifacts:\n            path: test-reports\n            destination: test-reports\n\nBelow are the important keywords that are used in writting circleci config.yml file.\n\n- :code:`image`: Defines the base image including the language and version to use\n- :code:`run`: It specifies a :code:`command` which will be run to setup environent and run tests. :code:`pip install -r pollsapi/requirements.txt` sets up the environment and :code:`pip install -r pollsapi/requirements.txt`\n\nIf everything passed successfully, you should see a green checkmark\n\n.. image:: circleci.png\n\nCongratulations, you have tests running in a CI environment.\n\nFrom now onwards whenever we push our code to our repository a new build will be created for it and the tests will run.\n\nWe are at the end of the first part of our book. You can read the appendix, which tell about some documentation tools and api consumption tools. Go forward and build some amazing apps and apis.\n\n"
  },
  {
    "path": "docs/views-and-generic-views.rst",
    "content": "Views and Generic Views\n============================\n\nIn this chapter, we will create views using :code:`APIVIew`, and :code:`generics.ListCreateAPIView` and family.\n\nCreating Views with :code:`APIView`\n-----------------------------------------\n\n\nTo start with, we will use the :code:`APIView` to build the polls list and poll detail API we built in the chapter, :doc:`apis-without-drf`.\n\nAdd this to a new file :code:`polls/apiviews.py`\n\n.. code-block:: python\n\n    from rest_framework.views import APIView\n    from rest_framework.response import Response\n    from django.shortcuts import get_object_or_404\n\n    from .models import Poll, Choice\n    from  .serializers import PollSerializer\n\n    class PollList(APIView):\n        def get(self, request):\n            polls = Poll.objects.all()[:20]\n            data = PollSerializer(polls, many=True).data\n            return Response(data)\n\n\n    class PollDetail(APIView):\n        def get(self, request, pk):\n            poll = get_object_or_404(Poll, pk=pk)\n            data = PollSerializer(poll).data\n            return Response(data)\n\n\nAnd change your :code:`urls.py` to\n\n.. code-block:: python\n\n    from django.urls import path\n\n    from .apiviews import PollList, PollDetail\n\n    urlpatterns = [\n        path(\"polls/\", PollList.as_view(), name=\"polls_list\"),\n        path(\"polls/<int:pk>/\", PollDetail.as_view(), name=\"polls_detail\")\n    ]\n\nDRF comes with a browsable api, so you can directly open :code:`http://localhost:8000/polls/` in the browser. It looks like this\n\n\n.. image:: browsable-api-poll-details.png\n\n\nYou can now do an :code:`options` request to `/polls/`, which gives\n\n.. code-block:: json\n\n\n    {\n        \"name\": \"Poll List\",\n        \"description\": \"\",\n        \"renders\": [\n            \"application/json\",\n            \"text/html\"\n        ],\n        \"parses\": [\n            \"application/json\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\"\n        ]\n    }\n\n\nThis is how it looks like in postman.\n\n.. image:: postman-poll-detail-options.png\n\nUsing DRF generic views to simplify code\n-----------------------------------------\n\n\nThe :code:`PollList` and :code:`PollDetail` get the work done, but there are bunch of common operations, we can do it in abstract away.\n\nThe generic views of Django Rest Framework help us in code reusablity. They infer the response format and allowed methods from the serializer class and base class.\n\nChange your :code:`apiviews.py` to the below code, and leave urls.py as is.\n\n.. code-block:: python\n\n    from rest_framework import generics\n\n    from .models import Poll, Choice\n    from .serializers import PollSerializer, ChoiceSerializer,\\\n        VoteSerializer\n\n\n    class PollList(generics.ListCreateAPIView):\n        queryset = Poll.objects.all()\n        serializer_class = PollSerializer\n\n\n    class PollDetail(generics.RetrieveDestroyAPIView):\n        queryset = Poll.objects.all()\n        serializer_class = PollSerializer\n\nWith this change, GET requests to :code:`/polls/` and :code:`/polls/<pk>/`, continue to work as was, but we have a more data available with OPTIONS.\n\nDo an OPTIONs request to :code:`/polls/`, and you will get a response like this.\n\n.. code-block:: javascript\n\n    {\n        \"name\": \"Poll List\",\n        \"description\": \"\",\n        \"renders\": [\n            \"application/json\",\n            \"text/html\"\n        ],\n        \"parses\": [\n            \"application/json\",\n            \"application/x-www-form-urlencoded\",\n            \"multipart/form-data\"\n        ],\n        \"actions\": {\n            \"POST\": {\n                \"id\": {\n                    \"type\": \"integer\",\n                    \"required\": false,\n                    \"read_only\": true,\n                    \"label\": \"ID\"\n                },\n                // ...\n                },\n                \"question\": {\n                    \"type\": \"string\",\n                    \"required\": true,\n                    \"read_only\": false,\n                    \"label\": \"Question\",\n                    \"max_length\": 100\n                },\n                \"pub_date\": {\n                    \"type\": \"datetime\",\n                    \"required\": false,\n                    \"read_only\": true,\n                    \"label\": \"Pub date\"\n                },\n                \"created_by\": {\n                    \"type\": \"field\",\n                    \"required\": true,\n                    \"read_only\": false,\n                    \"label\": \"Created by\"\n                }\n            }\n        }\n    }\n\nThis tells us\n\n* Our API now accepts POST\n* The required data fields\n* The type of each data field.\n\nPretty nifty! This is what it looks like in Postman.\n\n\n.. image:: postman-options-2.png\n\nMore generic views\n------------------------\n\n\nLet us add the view to create choices and for voting. We will look more closely at this code shortly.\n\n.. code-block:: python\n\n    from rest_framework import generics\n\n    from .models import Poll, Choice\n    from .serializers import PollSerializer, ChoiceSerializer, VoteSerializer\n\n\n    class PollList(generics.ListCreateAPIView):\n        queryset = Poll.objects.all()\n        serializer_class = PollSerializer\n\n\n    class PollDetail(generics.RetrieveDestroyAPIView):\n        queryset = Poll.objects.all()\n        serializer_class = PollSerializer\n\n\n    class ChoiceList(generics.ListCreateAPIView):\n        queryset = Choice.objects.all()\n        serializer_class = ChoiceSerializer\n\n\n    class CreateVote(generics.CreateAPIView):\n        serializer_class = VoteSerializer\n\n\nConnect the new apiviews to urls.py.\n\n.. code-block:: python\n\n    # ...\n    from .apiviews import ChoiceList, CreateVote, # ...\n\n    urlpatterns = [\n        # ...\n        path(\"choices/\", ChoiceList.as_view(), name=\"choice_list\"),\n        path(\"vote/\", CreateVote.as_view(), name=\"create_vote\"),\n\n    ]\n\n\n\n\nThere is a lot going on here, let us look at the attributes we need to override or set.\n\n- :code:`queryset`: This determines the initial queryset. The queryset can be further filtered, sliced or ordered by the view.\n- :code:`serializer_class`: This will be used for validating and deserializing the input and for serializing the output.\n\nWe have used three different classes from :code:`rest_framework.generic`. The names of the classes are representative of what they do, but lets quickly look at them.\n\n- :code:`ListCreateAPIView`: Get a list of entities, or create them. Allows GET and POST.\n- :code:`RetrieveDestroyAPIView`: Retrieve an individual entity details, or delete the entity. Allows GET and DELETE.\n- :code:`CreateAPIView`: Allows creating entities, but not listing them. Allows POST.\n\nCreate some choices by POSTing to :code:`/choices/`.\n\n.. code-block:: json\n\n    {\n        \"choice_text\": \"Flask\",\n        \"poll\": 2\n    }\n\nThe response looks like this\n\n.. code-block:: json\n\n    {\n        \"id\": 4,\n        \"votes\": [],\n        \"choice_text\": \"Flask\",\n        \"poll\": 2\n    }\n\nYou can also retrieve the :code:`Poll` to by doing a :code:`GET` to :code:`/polls/<pk>/`. You should get something like this\n\n.. code-block:: json\n\n    {\n        \"id\": 2,\n        \"choices\": [\n            {\n                \"id\": 3,\n                \"votes\": [],\n                \"choice_text\": \"Django\",\n                \"poll\": 2\n            },\n            {\n                \"id\": 4,\n                \"votes\": [],\n                \"choice_text\": \"Flask\",\n                \"poll\": 2\n            }\n        ],\n        \"question\": \"What do you prefer, Flask or Django?\",\n        \"pub_date\": \"2018-03-12T10:15:55.949721Z\",\n        \"created_by\": 1\n    }\n\nIf you make a mistake while POSTing, the API will warn you. POST a json with :code:`choice_text` missing to :code:`/choices/`.\n\n.. code-block:: json\n\n    {\n        \"poll\": 2\n    }\n\nYou will get a response like this\n\n.. code-block:: json\n\n    {\n        \"choice_text\": [\n            \"This field is required.\"\n        ]\n    }\n\nCheck the status code is 400 Bad Request.\n\nNext Steps\n--------------\n\nWe have working API at this point, but we can simplify our API with a better URL design and remove some code duplication using viewsets. We will be doing that in the next chapter.\n"
  },
  {
    "path": "pollsapi/.gitignore",
    "content": "*.pyc\ndb.sqlite3\n__pycache__\n"
  },
  {
    "path": "pollsapi/docs.raml",
    "content": "#%RAML 1.0\n  ---\n    title: Django polls API\n    baseUri: http://api.example.com/{version}\n    version: v1\n    mediaType: application/json\n    types:\n        Poll:\n            type: object\n            properties:\n                question:\n                    required: true\n                    type: string\n                created_by:\n                    required: true\n                    type: User\n                pub_date:\n                    required: true\n                    type: date\n        Choice:\n            type: object\n            properties:\n                poll:\n                    required: true\n                    type: Poll\n                choice_text:\n                    required: true\n                    type: string\n        Vote:\n            type: object\n            properties:\n                choice:\n                    required: true\n                    type: Choice\n                poll:\n                    required: true\n                    type: Poll\n                voted_by:\n                    required: true\n                    type: User\n    /polls:\n        get:\n            description: Get list of polls\n            queryParameters:\n                pollId:\n                    description: Specify the poll id you want to retrieve\n                    type: integer\n            responses:\n                200:\n                    body:\n                        application/json:\n                        example:\n                        {\n                            \"data\":\n                            {\n                                \"Id\": 1,\n                                \"question\": \"Will A be the leader next time?\",\n                                \"created_by\": \"user1\",\n                                \"pub_date\": \"08:02:2014\"\n                            },\n                            \"success\": true,\n                            \"status\": 200\n                        }\n        post:\n            description: Post a poll\n            queryParameters:\n                question:\n                    description: Question you want to create for poll\n                    type: string\n                    required: true\n                created_by:\n                    description: Poll created by the user\n                    type: User\n                    required: true\n                pub_date:\n                    description: Poll created on\n                    type: date\n                    required: true\n            responses:\n                200:\n                    body:\n                        application/json:\n                        example:\n                        {\n                            \"success\": true,\n                            \"status\": 201\n                        }\n    /choices:\n        get:\n            description: Get list of choices\n            queryParameters:\n                choiceId:\n                    description: Specify the choice id you want to retrieve\n                    type: integer\n            responses:\n                200:\n                    body:\n                        application/json:\n                        example:\n                        {\n                            \"data\":\n                            {\n                                \"Id\": 1,\n                                \"poll\": \"Will A be the leader next time?\",\n                                \"choice_text\": \"user1\"\n                            },\n                            \"success\": true,\n                            \"status\": 200\n                        }\n        post:\n            description: Post a choice\n            queryParameters:\n                poll:\n                    description: Choice you want to create for poll\n                    type: string\n                    required: true\n                choice_text:\n                    description: Choice for the poll\n                    type: string\n                    required: true\n            responses:\n                200:\n                    body:\n                        application/json:\n                        example:\n                        {\n                            \"success\": true,\n                            \"status\": 201\n                        }\n    /votes:\n        get:\n            description: Get votes of polls\n            queryParameters:\n                pollId:\n                    description: Specify the vote id you want to retrieve\n                    type: integer\n            responses:\n                200:\n                    body:\n                        application/json:\n                        example:\n                        {\n                            \"data\":\n                            {\n                                \"Id\": 1,\n                                \"poll\": \"Will A be the leader next time?\",\n                                \"choice\": \"user1\",\n                                \"voted_by\": \"user2\"\n                            },\n                            \"success\": true,\n                            \"status\": 200\n                        }\n        post:\n            description: Post a vote\n            queryParameters:\n                choice:\n                    description: Choice for the poll\n                    type: Choice\n                    required: true\n                poll:\n                    description: Poll to be voted\n                    type: Poll\n                    required: true\n                voted_by:\n                    description: Poll voted by\n                    type: User\n                    required: true\n            responses:\n                200:\n                    body:\n                        application/json:\n                        example:\n                        {\n                            \"success\": true,\n                            \"status\": 201\n                        }\n"
  },
  {
    "path": "pollsapi/docs.swagger.json",
    "content": "{\n    \"swagger\": \"2.0\",\n    \"info\": {\n        \"description\": \"This is a sample server for polls api.\",\n        \"version\": \"1.0.0\",\n        \"title\": \"Polls API\",\n        \"termsOfService\": \"http://example.com/terms/\",\n        \"contact\": {\"email\": \"apiteam@example.com\"},\n        \"license\": {\"name\": \"Apache 2.0\", \"url\": \"http://www.apache.org/licenses/LICENSE-2.0.html\"}\n    },\n    \"host\": \"polls.example.com\",\n    \"basePath\": \"/v2\",\n    \"tags\": [\n        {\n            \"name\": \"polls\",\n            \"description\": \"Everything about your Polls\",\n            \"externalDocs\": {\"description\": \"Find out more\",\"url\":\"http://example.com\"}\n        },\n        {\n            \"name\": \"choices\",\n            \"description\": \"Access to choices for the polls\"\n        },\n        {\n            \"name\": \"user\",\n            \"description\": \"Operations about user\",\n            \"externalDocs\": {\"description\": \"Find out more about our store\",\"url\":\"http://example.com\"}\n        }\n    ],\n    \"schemes\": [\"http\"],\n    \"paths\": {\n        \"/polls\": {\n            \"get\": {\n                \"tags\": [\"poll\"],\n                \"summary\": \"Get all the polls\",\n                \"description\": \"\",\n                \"operationId\": \"pollList\",\n                \"consumes\": [\"application/json\",\"application/xml\"],\n                \"produces\": [\"application/xml\",\"application/json\"],\n                \"parameters\": [{\n                    \"in\": \"query\",\n                    \"name\": \"body\",\n                    \"description\": \"Get all the polls.\",\n                    \"required\": false,\n                    \"schema\":{\"$ref\":\"#/pollsapi/Poll\"}\n                }],\n                \"responses\": {\"200\":{\"description\":\"Successfull operation\"}},\n            },\n            \"post\":{\n                \"tags\": [\"poll\"],\n                \"summary\": \"Create a new poll\",\n                \"description\": \"Creates a new poll.\",\n                \"operationId\": \"createPoll\",\n                \"consumes\":[\"application/json\",\"application/xml\"],\n                \"produces\":[\"application/xml\",\"application/json\"],\n                \"parameters\":[{\n                    \"in\":\"query\",\n                    \"name\":\"body\",\n                    \"description\": \"Poll object that needs to be added.\",\n                    \"required\": true,\n                    \"schema\": {\"$ref\":\"#/pollsapi/Poll\"}\n                }],\n                \"responses\": {\n                    \"200\": {\"description\":\"Poll created successfully\"}\n                }\n            }\n        },\n        \"/choices\": {\n            \"get\": {\n                \"tags\": [\"choice\"],\n                \"summary\": \"Get all the choices\",\n                \"description\": \"\",\n                \"operationId\": \"choiceList\",\n                \"consumes\": [\"application/json\",\"application/xml\"],\n                \"produces\": [\"application/xml\",\"application/json\"],\n                \"parameters\": [{\n                    \"in\": \"query\",\n                    \"name\": \"body\",\n                    \"description\": \"Get all the choices.\",\n                    \"required\": false,\n                    \"schema\":{\"$ref\":\"#/pollsapi/Choice\"}\n                }],\n                \"responses\": {\"200\":{\"description\":\"Successfull operation\"}},\n            },\n            \"post\":{\n                \"tags\": [\"choice\"],\n                \"summary\": \"Create a new choice\",\n                \"description\": \"Creates a new choice.\",\n                \"operationId\": \"createChoice\",\n                \"consumes\":[\"application/json\",\"application/xml\"],\n                \"produces\":[\"application/xml\",\"application/json\"],\n                \"parameters\":[{\n                    \"in\":\"query\",\n                    \"name\":\"body\",\n                    \"description\": \"Choice object that needs to be added.\",\n                    \"required\": true,\n                    \"schema\": {\"$ref\":\"#/pollsapi/Poll\"}\n                }],\n                \"responses\": {\n                    \"200\": {\"description\":\"Poll created successfully\"}\n                }\n            }\n        },\n        \"/user\": {\n            \"get\": {\n                \"tags\": [\"user\"],\n                \"summary\": \"Get user details\",\n                \"description\": \"\",\n                \"operationId\": \"user\",\n                \"consumes\": [\"application/json\",\"application/xml\"],\n                \"produces\": [\"application/xml\",\"application/json\"],\n                \"parameters\": [{\n                    \"in\": \"query\",\n                    \"name\": \"body\",\n                    \"description\": \"Get the user.\",\n                    \"required\": false,\n                    \"schema\":{\"$ref\":\"#/pollsapi/User\"}\n                }],\n                \"responses\": {\"200\":{\"description\":\"Successfull operation\"}},\n            },\n            \"post\":{\n                \"tags\": [\"user\"],\n                \"summary\": \"Create a new user\",\n                \"description\": \"Creates a new user.\",\n                \"operationId\": \"createUser\",\n                \"consumes\":[\"application/json\",\"application/xml\"],\n                \"produces\":[\"application/xml\",\"application/json\"],\n                \"parameters\":[{\n                    \"in\":\"query\",\n                    \"name\":\"body\",\n                    \"description\": \"User object that needs to be added.\",\n                    \"required\": true,\n                    \"schema\": {\"$ref\":\"#/pollsapi/User\"}\n                }],\n                \"responses\": {\n                    \"200\": {\"description\":\"User created successfully\"}\n                }\n            }\n        },\n        \"/vote\": {\n            \"post\":{\n                \"tags\": [\"vote\"],\n                \"summary\": \"Create a new vote\",\n                \"description\": \"Creates a new vote.\",\n                \"operationId\": \"createVote\",\n                \"consumes\":[\"application/json\",\"application/xml\"],\n                \"produces\":[\"application/xml\",\"application/json\"],\n                \"parameters\":[{\n                    \"in\":\"query\",\n                    \"name\":\"body\",\n                    \"description\": \"Vote object that needs to be added.\",\n                    \"required\": true,\n                    \"schema\": {\"$ref\":\"#/pollsapi/Vote\"}\n                }],\n                \"responses\": {\n                    \"200\": {\"description\":\"Vote created successfully\"}\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "pollsapi/manage.py",
    "content": "#!/usr/bin/env python\nimport os\nimport sys\n\nif __name__ == \"__main__\":\n    os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"pollsapi.settings\")\n    try:\n        from django.core.management import execute_from_command_line\n    except ImportError as exc:\n        raise ImportError(\n            \"Couldn't import Django. Are you sure it's installed and \"\n            \"available on your PYTHONPATH environment variable? Did you \"\n            \"forget to activate a virtual environment?\"\n        ) from exc\n    execute_from_command_line(sys.argv)\n"
  },
  {
    "path": "pollsapi/polls/__init__.py",
    "content": ""
  },
  {
    "path": "pollsapi/polls/admin.py",
    "content": "from django.contrib import admin\n\nfrom .models import Poll, Choice\n\nadmin.site.register(Poll)\nadmin.site.register(Choice)\n"
  },
  {
    "path": "pollsapi/polls/apiviews.py",
    "content": "from rest_framework import generics\nfrom rest_framework.views import APIView\nfrom rest_framework import status\nfrom rest_framework.response import Response\nfrom rest_framework import viewsets\nfrom rest_framework.exceptions import PermissionDenied\n\nfrom django.contrib.auth import authenticate\n\nfrom .models import Poll, Choice\nfrom .serializers import PollSerializer, ChoiceSerializer, VoteSerializer, UserSerializer\n\n\nclass PollViewSet(viewsets.ModelViewSet):\n    queryset = Poll.objects.all()\n    serializer_class = PollSerializer\n\n    def destroy(self, request, *args, **kwargs):\n        poll = Poll.objects.get(pk=self.kwargs[\"pk\"])\n        if not request.user == poll.created_by:\n            raise PermissionDenied(\"You can not delete this poll.\")\n        return super().destroy(request, *args, **kwargs)\n\n\nclass ChoiceList(generics.ListCreateAPIView):\n    serializer_class = ChoiceSerializer\n\n    def get_queryset(self):\n        queryset = Choice.objects.filter(poll_id=self.kwargs[\"pk\"])\n        return queryset\n\n    def post(self, request, *args, **kwargs):\n        poll = Poll.objects.get(pk=self.kwargs[\"pk\"])\n        if not request.user == poll.created_by:\n            raise PermissionDenied(\"You can not create choice for this poll.\")\n        return super().post(request, *args, **kwargs)\n\n\n\nclass CreateVote(APIView):\n\n    def post(self, request, pk, choice_pk):\n        voted_by = request.data.get(\"voted_by\")\n        data = {'choice': choice_pk, 'poll': pk, 'voted_by': voted_by}\n        serializer = VoteSerializer(data=data)\n        if serializer.is_valid():\n            vote = serializer.save()\n            return Response(serializer.data, status=status.HTTP_201_CREATED)\n        else:\n            return Response({\"error\": \"Wrong Credentials\"}, status=status.HTTP_400_BAD_REQUEST)\n\n\nclass UserCreate(generics.CreateAPIView):\n    serializer_class = UserSerializer\n\n\nclass LoginView(APIView):\n    def post(self, request,):\n        username = request.data.get(\"username\")\n        password = request.data.get(\"password\")\n        user = authenticate(username=username, password=password)\n        if user:\n            return Response({\"token\": user.auth_token.key})\n        else:\n            return Response({\"error\": \"Wrong Credentials\"}, status=status.HTTP_400_BAD_REQUEST)\n\n"
  },
  {
    "path": "pollsapi/polls/apps.py",
    "content": "from django.apps import AppConfig\n\n\nclass PollsConfig(AppConfig):\n    name = 'polls'\n"
  },
  {
    "path": "pollsapi/polls/migrations/0001_initial.py",
    "content": "# Generated by Django 2.0.3 on 2018-03-08 17:01\n\nfrom django.conf import settings\nfrom django.db import migrations, models\nimport django.db.models.deletion\n\n\nclass Migration(migrations.Migration):\n\n    initial = True\n\n    dependencies = [\n        migrations.swappable_dependency(settings.AUTH_USER_MODEL),\n    ]\n\n    operations = [\n        migrations.CreateModel(\n            name='Choice',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('choice_text', models.CharField(max_length=100)),\n            ],\n        ),\n        migrations.CreateModel(\n            name='Poll',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('question', models.CharField(max_length=100)),\n                ('pub_date', models.DateTimeField(auto_now=True)),\n                ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),\n            ],\n        ),\n        migrations.CreateModel(\n            name='Vote',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('choice', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='votes', to='polls.Choice')),\n                ('poll', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.Poll')),\n                ('voted_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),\n            ],\n        ),\n        migrations.AddField(\n            model_name='choice',\n            name='poll',\n            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='polls.Poll'),\n        ),\n        migrations.AlterUniqueTogether(\n            name='vote',\n            unique_together={('poll', 'voted_by')},\n        ),\n    ]\n"
  },
  {
    "path": "pollsapi/polls/migrations/__init__.py",
    "content": ""
  },
  {
    "path": "pollsapi/polls/models.py",
    "content": "from django.db import models\nfrom django.contrib.auth.models import User\n\n\nclass Poll(models.Model):\n    question = models.CharField(max_length=100)\n    created_by = models.ForeignKey(User, on_delete=models.CASCADE)\n    pub_date = models.DateTimeField(auto_now=True)\n\n    def __str__(self):\n        return self.question\n\n\nclass Choice(models.Model):\n    poll = models.ForeignKey(Poll, related_name='choices',on_delete=models.CASCADE)\n    choice_text = models.CharField(max_length=100)\n\n    def __str__(self):\n        return self.choice_text\n\n\nclass Vote(models.Model):\n    choice = models.ForeignKey(Choice, related_name='votes', on_delete=models.CASCADE)\n    poll = models.ForeignKey(Poll, on_delete=models.CASCADE)\n    voted_by = models.ForeignKey(User, on_delete=models.CASCADE)\n\n    class Meta:\n        unique_together = (\"poll\", \"voted_by\")\n"
  },
  {
    "path": "pollsapi/polls/serializers.py",
    "content": "from django.contrib.auth.models import User\nfrom rest_framework.authtoken.models import Token\n\nfrom rest_framework import serializers\n\nfrom .models import Poll, Choice, Vote\n\n\nclass VoteSerializer(serializers.ModelSerializer):\n    class Meta:\n        model = Vote\n        fields = '__all__'\n\n\nclass ChoiceSerializer(serializers.ModelSerializer):\n    votes = VoteSerializer(many=True, required=False)\n\n    class Meta:\n        model = Choice\n        fields = '__all__'\n\n\nclass PollSerializer(serializers.ModelSerializer):\n    choices = ChoiceSerializer(many=True, read_only=True, required=False)\n\n    class Meta:\n        model = Poll\n        fields = '__all__'\n\n\nclass UserSerializer(serializers.ModelSerializer):\n\n        class Meta:\n            model = User\n            fields = ('username', 'email', 'password')\n            extra_kwargs = {'password': {'write_only': True}}\n\n        def create(self, validated_data):\n            user = User(\n                email=validated_data['email'],\n                username=validated_data['username']\n            )\n            user.set_password(validated_data['password'])\n            user.save()\n            Token.objects.create(user=user)\n            return user\n\n\n"
  },
  {
    "path": "pollsapi/polls/tests.py",
    "content": "from django.contrib.auth import get_user_model\n\n\nfrom rest_framework.test import APITestCase\nfrom rest_framework.test import APIClient, APIRequestFactory\n\nfrom polls import apiviews\n\n\nclass TestPoll(APITestCase):\n    def setUp(self):\n        self.factory = APIRequestFactory()\n        self.client = APIClient()\n        self.uri = '/polls/'\n        self.user = self.setup_user()\n        self.view = apiviews.PollViewSet.as_view({'post': 'list'})\n\n    @staticmethod\n    def setup_user():\n        User = get_user_model()\n        return User.objects.create_user(\n            'test',\n            email='testuser@test.com',\n            password='test'\n        )\n\n    def _test_list(self):\n        request = self.factory.get(self.uri)\n        request.user = self.user\n        response = self.view(request)\n        self.assertEqual(response.status_code, 200,\n                         'Expected Response Code 200, received {0} instead.'\n                         .format(response.status_code))\n\n    def test_list2(self):\n        self.client.login(username=\"test\", password=\"test\")\n        response = self.client.get(self.uri)\n        self.assertEqual(response.status_code, 200,\n                         'Expected Response Code 200, received {0} instead.'\n                         .format(response.status_code))\n\n    def test_create(self):\n        self.client.login(username=\"test\", password=\"test\")\n        params = {\n            \"question\": \"How are you?\",\n            \"created_by\": 1\n            }\n        response = self.client.post(self.uri, params)\n        self.assertEqual(response.status_code, 201,\n                         'Expected Response Code 201, received {0} instead.'\n                         .format(response.status_code))\n\n"
  },
  {
    "path": "pollsapi/polls/urls.py",
    "content": "from django.urls import path\n\nfrom .apiviews import PollViewSet, ChoiceList, CreateVote, UserCreate, LoginView\n\nfrom rest_framework.routers import DefaultRouter\n\nfrom rest_framework.documentation import include_docs_urls\n\nfrom rest_framework_swagger.views import get_swagger_view\n\nschema_view = get_swagger_view(title='Polls API')\n\n\nrouter = DefaultRouter()\nrouter.register('polls', PollViewSet, base_name='polls')\n\n\nurlpatterns = [\n    path(\"login/\", LoginView.as_view(), name=\"login\"),\n    path(\"users/\", UserCreate.as_view(), name=\"user_create\"),\n    path(\"polls/<int:pk>/choices/\", ChoiceList.as_view(), name=\"polls_list\"),\n    path(\"polls/<int:pk>/choices/<int:choice_pk>/vote/\", CreateVote.as_view(), name=\"polls_list\"),\n    path(r'docs/', include_docs_urls(title='Polls API')),\n    path(r'swagger-docs/', schema_view),\n]\n\nurlpatterns += router.urls\n"
  },
  {
    "path": "pollsapi/polls/views.py",
    "content": "from django.shortcuts import render, get_object_or_404\nfrom django.http import JsonResponse\n\nfrom .models import Poll\n\ndef polls_list(request):\n    MAX_OBJECTS = 20\n    polls = Poll.objects.all()[:20]\n    data = {\"results\": list(polls.values(\"pk\", \"question\", \"created_by__username\", \"pub_date\"))}\n    return JsonResponse(data)\n\n\ndef polls_detail(request, pk):\n    poll = get_object_or_404(Poll, pk=pk)\n    data = {\"results\": {\n        \"question\": poll.question,\n        \"created_by\": poll.created_by.username,\n        \"pub_date\": poll.pub_date\n    }}\n    return JsonResponse(data)\n"
  },
  {
    "path": "pollsapi/pollsapi/__init__.py",
    "content": ""
  },
  {
    "path": "pollsapi/pollsapi/settings.py",
    "content": "\"\"\"\nDjango settings for pollsapi project.\n\nGenerated by 'django-admin startproject' using Django 2.0.3.\n\nFor more information on this file, see\nhttps://docs.djangoproject.com/en/2.0/topics/settings/\n\nFor the full list of settings and their values, see\nhttps://docs.djangoproject.com/en/2.0/ref/settings/\n\"\"\"\n\nimport os\n\n# Build paths inside the project like this: os.path.join(BASE_DIR, ...)\nBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\n\n\n# Quick-start development settings - unsuitable for production\n# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/\n\n# SECURITY WARNING: keep the secret key used in production secret!\nSECRET_KEY = 'n*z@*&0ein2+poiu$rhkv2c0a@^2gbzg=g!_e%+dz#2ik5f$g2'\n\n# SECURITY WARNING: don't run with debug turned on in production!\nDEBUG = True\n\nALLOWED_HOSTS = []\n\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': (\n        'rest_framework.authentication.TokenAuthentication',\n        'rest_framework.authentication.SessionAuthentication',\n    ),\n    'DEFAULT_PERMISSION_CLASSES': (\n        'rest_framework.permissions.IsAuthenticated',\n    )\n}\n# Application definition\n\nINSTALLED_APPS = [\n    'django.contrib.admin',\n    'django.contrib.auth',\n    'django.contrib.contenttypes',\n    'django.contrib.sessions',\n    'django.contrib.messages',\n    'django.contrib.staticfiles',\n    'rest_framework',\n    'rest_framework.authtoken',\n    'polls',\n    'rest_framework_swagger',\n]\n\nMIDDLEWARE = [\n    'django.middleware.security.SecurityMiddleware',\n    'django.contrib.sessions.middleware.SessionMiddleware',\n    'django.middleware.common.CommonMiddleware',\n    'django.middleware.csrf.CsrfViewMiddleware',\n    'django.contrib.auth.middleware.AuthenticationMiddleware',\n    'django.contrib.messages.middleware.MessageMiddleware',\n    'django.middleware.clickjacking.XFrameOptionsMiddleware',\n]\n\nROOT_URLCONF = 'pollsapi.urls'\n\nTEMPLATES = [\n    {\n        'BACKEND': 'django.template.backends.django.DjangoTemplates',\n        'DIRS': [],\n        'APP_DIRS': True,\n        'OPTIONS': {\n            'context_processors': [\n                'django.template.context_processors.debug',\n                'django.template.context_processors.request',\n                'django.contrib.auth.context_processors.auth',\n                'django.contrib.messages.context_processors.messages',\n            ],\n        },\n    },\n]\n\nWSGI_APPLICATION = 'pollsapi.wsgi.application'\n\n\n# Database\n# https://docs.djangoproject.com/en/2.0/ref/settings/#databases\n\nDATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.sqlite3',\n        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),\n    }\n}\n\n\n# Password validation\n# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators\n\nAUTH_PASSWORD_VALIDATORS = [\n    {\n        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',\n    },\n    {\n        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',\n    },\n    {\n        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',\n    },\n    {\n        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',\n    },\n]\n\n\n# Internationalization\n# https://docs.djangoproject.com/en/2.0/topics/i18n/\n\nLANGUAGE_CODE = 'en-us'\n\nTIME_ZONE = 'UTC'\n\nUSE_I18N = True\n\nUSE_L10N = True\n\nUSE_TZ = True\n\n\n# Static files (CSS, JavaScript, Images)\n# https://docs.djangoproject.com/en/2.0/howto/static-files/\n\nSTATIC_URL = '/static/'\n"
  },
  {
    "path": "pollsapi/pollsapi/urls.py",
    "content": "\"\"\"pollsapi URL Configuration\n\nThe `urlpatterns` list routes URLs to views. For more information please see:\n    https://docs.djangoproject.com/en/2.0/topics/http/urls/\nExamples:\nFunction views\n    1. Add an import:  from my_app import views\n    2. Add a URL to urlpatterns:  path('', views.home, name='home')\nClass-based views\n    1. Add an import:  from other_app.views import Home\n    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')\nIncluding another URLconf\n    1. Import the include() function: from django.urls import include, path\n    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))\n\"\"\"\nfrom django.contrib import admin\nfrom django.urls import path, include\n\nurlpatterns = [\n    path('admin/', admin.site.urls),\n    path(r'', include('polls.urls')),\n]\n"
  },
  {
    "path": "pollsapi/pollsapi/wsgi.py",
    "content": "\"\"\"\nWSGI config for pollsapi project.\n\nIt exposes the WSGI callable as a module-level variable named ``application``.\n\nFor more information on this file, see\nhttps://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/\n\"\"\"\n\nimport os\n\nfrom django.core.wsgi import get_wsgi_application\n\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"pollsapi.settings\")\n\napplication = get_wsgi_application()\n"
  },
  {
    "path": "pollsapi/requirements.txt",
    "content": "Django==2.2.13\ndjangorestframework==3.7.7\ndjango-rest-swagger==2.1.2\ncoreapi==2.3.3\n"
  },
  {
    "path": "requirements.txt",
    "content": "Sphinx\n"
  }
]