Clean Up API Urls and Views:

This part is to use “api” directory to organize urls and views.

  • create directory /tweets/api
    • create /tweets/api/init.py (no actual content)
    • create /tweets/api/urls.py
    • create /tweets/api/views.py
  • copy content in /tweets/urls.py and paste into /tweets/api/urls.py
  • modify the content to fit ```python from django.contrib import admin from django.urls import path

from .views import (

  1. # home_view,
  2. tweet_detail_view,
  3. tweet_list_view,
  4. tweet_create_view,
  5. tweet_delete_view,
  6. tweet_action_view,

)

urlpatterns = [ path(‘’, tweet_list_view), path(‘action/‘, tweet_action_view), path(‘create/‘, tweet_create_view), path(‘/‘, tweet_detail_view), path(‘/delete/‘, tweet_delete_view), ]

  1. - also copy, paste and modify /tweets/views.py into create /tweets/api/views.py
  2. ```python
  3. import random
  4. from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
  5. from django.shortcuts import render, redirect
  6. from django.utils.http import is_safe_url
  7. from django.conf import settings
  8. from rest_framework.authentication import SessionAuthentication
  9. from rest_framework.decorators import api_view, permission_classes, authentication_classes
  10. from rest_framework.permissions import IsAuthenticated
  11. from rest_framework.response import Response
  12. # from .models import Tweet
  13. # from .forms import TweetForm
  14. # from .serializers import (
  15. # TweetSerializer,
  16. # TweetActionSerializer,
  17. # TweetCreateSerializer
  18. # )
  19. from ..models import Tweet
  20. from ..forms import TweetForm
  21. from ..serializers import (
  22. TweetSerializer,
  23. TweetActionSerializer,
  24. TweetCreateSerializer
  25. )
  26. ALLOWED_HOSTS = settings.ALLOWED_HOSTS
  27. # def home_view(request, *args, **kwargs):
  28. # username = None
  29. # if request.user.is_authenticated:
  30. # username = request.user.username
  31. # return render(request, "pages/home.html", context={"username": username}, status=200)
  32. # def local_tweets_list_view(request, *args, **kwargs):
  33. # return render(request, "tweets/list.html")
  34. # def local_tweets_detail_view(request, tweet_id, *args, **kwargs):
  35. # return render(request, "tweets/detail.html", context={"tweet_id": tweet_id})
  36. # def local_tweets_profile_view(request, username, *args, **kwargs):
  37. # return render(request, "tweets/profile.html", context={"profile_username": username})
  38. @api_view(['POST']) # http method the client === POST
  39. # @authentication_classes([SessionAuthentication])
  40. @permission_classes([IsAuthenticated])
  41. def tweet_create_view(request, *args, **kwargs):
  42. print(request.user)
  43. serializer = TweetCreateSerializer(data=request.data)
  44. if serializer.is_valid(raise_exception=True): # send back what the error is
  45. serializer.save(user=request.user)
  46. return Response(serializer.data, status=201)
  47. return Response({}, status=400)
  48. def tweet_create_view_pure_django(request, *args, **kwargs):
  49. user = request.user
  50. if not request.user.is_authenticated:
  51. user = None
  52. if request.is_ajax():
  53. return JsonResponse({}, status=401)
  54. return redirect(settings.LOGIN_URL)
  55. form = TweetForm(request.POST or None)
  56. print('post data is', request.POST)
  57. next_url = request.POST.get("next") or None
  58. if form.is_valid():
  59. obj = form.save(commit=False)
  60. obj.user = request.user
  61. obj.save()
  62. if request.is_ajax():
  63. return JsonResponse(obj.serialize(), status=201)
  64. if next_url != None and is_safe_url(next_url, ALLOWED_HOSTS):
  65. return redirect(next_url)
  66. form = TweetForm()
  67. if form.errors:
  68. if request.is_ajax():
  69. return JsonResponse(form.errors, status=400)
  70. return render(request, 'components/form.html', context={"form": form})
  71. @api_view(['GET']) # http method the client === POST
  72. def tweet_list_view(request, *args, **kwargs):
  73. qs = Tweet.objects.all() # grab all objects in Tweet
  74. username = request.GET.get('username') # ?username=root
  75. if username != None:
  76. # filter that username w/o case sensitive
  77. qs = qs.filter(user__username__iexact=username)
  78. serializer = TweetSerializer(qs, many=True)
  79. return Response(serializer.data)
  80. def tweet_list_view_pure_django(request, *args, **kwargs):
  81. qs = Tweet.objects.all() # grab all objects in Tweet
  82. # tweets_list = [{"id" : x.id, "content" : x.content, "likes" : random.randint(0, 1000)} for x in qs]
  83. tweets_list = [x.serialize() for x in qs]
  84. data = {
  85. "isUser": False,
  86. "response": tweets_list
  87. }
  88. return JsonResponse(data)
  89. @api_view(['GET']) # http method the client === GET
  90. def tweet_detail_view(request, tweet_id, *args, **kwargs):
  91. qs = Tweet.objects.filter(id=tweet_id)
  92. if not qs.exists():
  93. return Response({}, status=404)
  94. obj = qs.first()
  95. serializer = TweetSerializer(obj)
  96. return Response(serializer.data, status=200)
  97. def tweet_detail_view_pure_django(request, tweet_id, *args, **kwargs):
  98. data = {
  99. "id": tweet_id,
  100. }
  101. status = 200
  102. try:
  103. obj = Tweet.objects.get(id=tweet_id)
  104. data['content'] = obj.content
  105. except:
  106. data['message'] = "Not found"
  107. status = 404
  108. return JsonResponse(data, status=status)
  109. @api_view(['DELETE', 'POST'])
  110. @permission_classes([IsAuthenticated])
  111. def tweet_delete_view(request, tweet_id, *args, **kwargs):
  112. qs = Tweet.objects.filter(id=tweet_id)
  113. if not qs.exists():
  114. return Response({}, status=404)
  115. qs = qs.filter(user=request.user)
  116. if not qs.exists():
  117. return Response({"message": "You cannot delete this tweet"}, status=401)
  118. obj = qs.first()
  119. obj.delete()
  120. return Response({"Tweet removed"}, status=200)
  121. @api_view(['POST'])
  122. @permission_classes([IsAuthenticated])
  123. def tweet_action_view(request, *args, **kwargs):
  124. # id is required
  125. # action: like, unlike, retweet
  126. serializer = TweetActionSerializer(data=request.data)
  127. if serializer.is_valid(raise_exception=True):
  128. data = serializer.validated_data
  129. tweet_id = data.get("id")
  130. action = data.get("action")
  131. content = data.get("content")
  132. qs = Tweet.objects.filter(id=tweet_id)
  133. if not qs.exists():
  134. return Response({}, status=404)
  135. obj = qs.first()
  136. if action == "like":
  137. # add the current user into the like list
  138. obj.likes.add(request.user)
  139. serializer = TweetSerializer(obj)
  140. return Response(serializer.data, status=200)
  141. elif action == "unlike":
  142. # remove the current user from the like list
  143. obj.likes.remove(request.user)
  144. serializer = TweetSerializer(obj)
  145. return Response(serializer.data, status=200)
  146. elif action == "retweet":
  147. new_tweet = Tweet.objects.create(
  148. user=request.user,
  149. parent=obj,
  150. content=content
  151. )
  152. serializer = TweetSerializer(new_tweet)
  153. # return Response(serializer.data, status=200)
  154. return Response(serializer.data, status=201)
  155. return Response({}, status=200)
  • modify original files
    • /tweets/views.py ```python import random from django.http import HttpResponse, JsonResponse, HttpResponseRedirect from django.shortcuts import render, redirect from django.utils.http import is_safe_url from django.conf import settings

from rest_framework.authentication import SessionAuthentication

from rest_framework.decorators import api_view, permission_classes, authentication_classes

from rest_framework.permissions import IsAuthenticated

from rest_framework.response import Response

from .models import Tweet

from .forms import TweetForm

from .serializers import (

TweetSerializer,

TweetActionSerializer,

TweetCreateSerializer

)

ALLOWED_HOSTS = settings.ALLOWED_HOSTS

def home_view(request, args, *kwargs): username = None if request.user.is_authenticated: username = request.user.username return render(request, “pages/home.html”, context={“username”: username}, status=200)

def local_tweets_list_view(request, args, *kwargs):

def tweets_list_view(request, args, *kwargs): return render(request, “tweets/list.html”)

def local_tweets_detail_view(request, tweet_id, args, *kwargs):

def tweets_detail_view(request, tweet_id, args, *kwargs): return render(request, “tweets/detail.html”, context={“tweet_id”: tweet_id})

def local_tweets_profile_view(request, username, args, *kwargs):

def tweets_profile_view(request, username, args, *kwargs): return render(request, “tweets/profile.html”, context={“profile_username”: username})

removed other parts

  1. - change urls links in /Twittme/urls.py
  2. ```python
  3. from django.contrib import admin
  4. from django.urls import path, re_path, include
  5. from django.conf import settings
  6. from django.conf.urls.static import static
  7. from django.views.generic import TemplateView
  8. from tweets.views import (
  9. # local_tweets_list_view,
  10. # local_tweets_detail_view,
  11. # local_tweets_profile_view,
  12. tweets_list_view,
  13. tweets_detail_view,
  14. tweets_profile_view,
  15. )
  16. urlpatterns = [
  17. path('admin/', admin.site.urls),
  18. # path('api/tweets/', include('tweets.urls')),
  19. path('api/tweets/', include('tweets.api.urls')),
  20. # path('', local_tweets_list_view),
  21. # path('<int:tweet_id>', local_tweets_detail_view),
  22. # path('profile/<str:username>', local_tweets_profile_view),
  23. path('', tweets_list_view),
  24. path('<int:tweet_id>', tweets_detail_view),
  25. path('profile/<str:username>', tweets_profile_view),
  26. ]
  27. if settings.DEBUG:
  28. urlpatterns += static(settings.STATIC_URL,
  29. document_root=settings.STATIC_ROOT)

And it has the same feature as the reactjs/django project before, but with a new intergrated api directory.