Delete Tweet API View:

In this section, add a new view to allow deleting tweets as a authenticated user.

  • add delete_view in /tweets/views.py

    1. @api_view(['DELETE', 'POST'])
    2. @permission_classes([IsAuthenticated])
    3. def tweet_delete_view(request, tweet_id, *args, **kwargs):
    4. qs = Tweet.objects.filter(id=tweet_id)
    5. if not qs.exists():
    6. return Response({}, status=404)
    7. qs = qs.filter(user=request.user)
    8. if not qs.exists():
    9. return Response({"message": "You cannot delete this tweet"}, status=401)
    10. obj = qs.first()
    11. obj.delete()
    12. return Response({"Tweet removed"}, status=200)
  • register the view and path in /Twittme/urls.py ```python from tweets.views import ( home_view, tweet_detail_view, tweet_list_view, tweet_create_view, tweet_delete_view, # new )

urlpatterns = [ path(‘admin/‘, admin.site.urls), path(‘’, home_view), path(‘tweets’, tweet_list_view), path(‘create-tweet’, tweet_create_view), path(‘tweets/‘, tweet_detail_view), path(‘api/tweets//delete’, tweet_delete_view), ]

  1. - another change in /Twittme/settings.py
  2. - allow rest_framework.renderers.BrowsableAPIRenderer in debug mode.
  3. ```python
  4. DEFAULT_RENDERER_CLASSES = [
  5. 'rest_framework.renderers.JSONRenderer',
  6. ]
  7. if DEBUG:
  8. DEFAULT_RENDERER_CLASSES += [
  9. 'rest_framework.renderers.BrowsableAPIRenderer',
  10. ]
  11. REST_FRAMEWORK = {
  12. 'DEFAULT_AUTHENTICATION_CLASSES': [
  13. 'rest_framework.authentication.SessionAuthentication'
  14. ],
  15. 'DEFAULT_RENDERER_CLASSES': DEFAULT_RENDERER_CLASSES
  16. }

to test, runserver and login, try to delete the first “Hello World”: image.png
use http://localhost:8000/api/tweets/1/delete
click “DELETE”
image.png
image.png
and access http://localhost:8000/tweets/1
image.png
not found, delete is successful.

Addling a Like Field:

This section is to provide a real Like function for users.

  • add like factor in /tweets/models.py ```python class TweetLike(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) tweet = models.ForeignKey(“Tweet”, on_delete=models.CASCADE) timestamp = models.DateTimeField(auto_now_add=True)

class Tweet(models.Model):

  1. # maps to SQL data
  2. # id = models.AutoField(primary_key=True)
  3. user = models.ForeignKey(User, on_delete=models.CASCADE) # many users can many tweets
  4. # new
  5. likes = models.ManyToManyField(User, related_name='tweet_user', blank=True, through=TweetLike) # references TweetLike
  6. content = models.TextField(blank=True, null=True)
  7. image = models.FileField(upload_to="images/", blank=True, null=True)
  8. timestamp = models.DateTimeField(auto_now_add=True) # new
  9. # ...
  1. - Then make migrations and migrate
  2. ```bash
  3. (reactjs) [root@localhost Twittme]# ./manage.py makemigrations
  4. You are trying to add the field 'timestamp' with 'auto_now_add=True' to tweet without a default; the database needs something to populate existing rows.
  5. 1) Provide a one-off default now (will be set on all existing rows)
  6. 2) Quit, and let me add a default in models.py
  7. Select an option: 1
  8. Please enter the default value now, as valid Python
  9. You can accept the default 'timezone.now' by pressing 'Enter' or you can provide another value.
  10. The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
  11. Type 'exit' to exit this prompt
  12. [default: timezone.now] >>> timezone.now
  13. Migrations for 'tweets':
  14. tweets/migrations/0005_tweet_timestamp.py
  15. - Add field timestamp to tweet
  16. (reactjs) [root@localhost Twittme]# ./manage.py migrate
  17. Operations to perform:
  18. Apply all migrations: admin, auth, contenttypes, sessions, tweets
  19. Running migrations:
  20. Applying tweets.0005_tweet_timestamp... OK
  • setup tweet like model in admin.py ```python from django.contrib import admin

Register your models here.

from .models import Tweet, TweetLike # new

class TweetLikeAdmin(admin.TabularInline): # new model = TweetLike

class TweetAdmin(admin.ModelAdmin): inlines = [TweetLikeAdmin] # new listdisplay = [‘_str‘, ‘user’] search_fields = [‘content’, ‘userusername’, ‘useremail’] # only allow searches about content, username and email class Meta: model = Tweet

admin.site.register(Tweet, TweetAdmin)

  1. to test, runserver<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1243266/1592332797450-83f095c0-555c-464b-8f74-c406f9615bfe.png#align=left&display=inline&height=402&margin=%5Bobject%20Object%5D&name=image.png&originHeight=804&originWidth=1217&size=51973&status=done&style=none&width=608.5)<br />and we have a tweet likes field here.<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1243266/1592333834443-64715cec-2be7-4660-acfa-c0e92e7701e1.png#align=left&display=inline&height=394&margin=%5Bobject%20Object%5D&name=image.png&originHeight=788&originWidth=1302&size=42447&status=done&style=none&width=651)<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1243266/1592336672025-08be171a-0663-4880-9775-6ecf3af9dd15.png#align=left&display=inline&height=362&margin=%5Bobject%20Object%5D&name=image.png&originHeight=724&originWidth=917&size=50642&status=done&style=none&width=458.5)<br />we add one like object to test later.
  2. <a name="TSakU"></a>
  3. #### Understanding Setting ManyToMany Fields:
  4. ```bash
  5. (reactjs) [root@localhost Twittme]# ./manage.py shell
  6. Python 3.6.5 (default, Sep 10 2018, 09:39:42)
  7. [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
  8. Type "help", "copyright", "credits" or "license" for more information.
  9. (InteractiveConsole)
  10. >>> from tweets.models import Tweet, TweetLike
  11. >>> TweetLike.objects.all()
  12. <QuerySet [<TweetLike: TweetLike object (3)>]>
  13. >>> TweetLike.objects.all().delete()
  14. (1, {'tweets.TweetLike': 1})
  15. >>> TweetLike.objects.all()
  16. <QuerySet []>
  17. >>> Tweet.objects.all()
  18. <QuerySet [<Tweet: Tweet object (52)>, <Tweet: Tweet object (51)>, <Tweet: Tweet object (50)>, <Tweet: Tweet object (49)>, <Tweet: Tweet object (48)>, <Tweet: Tweet object (47)>, <Tweet: Tweet object (46)>, <Tweet: Tweet object (45)>, <Tweet: Tweet object (44)>, <Tweet: Tweet object (43)>, <Tweet: Tweet object (42)>, <Tweet: Tweet object (41)>, <Tweet: Tweet object (40)>, <Tweet: Tweet object (39)>, <Tweet: Tweet object (38)>, <Tweet: Tweet object (37)>, <Tweet: Tweet object (36)>, <Tweet: Tweet object (35)>, <Tweet: Tweet object (34)>, <Tweet: Tweet object (33)>, '...(remaining elements truncated)...']>
  19. >>> obj = Tweet.objects.first()
  20. >>> obj.likes.all()
  21. <QuerySet []>
  22. >>> from django.contrib.auth import get_user_model
  23. >>> User = get_user_model()
  24. >>> User.objects.all()
  25. <QuerySet [<User: root>]>
  26. >>> me = User.objects.first()
  27. >>> me
  28. <User: root>