Followers and Following:

This part we need to actually import “Follow” function.
I did some tests yesterday, and that note includes some related techniques:
https://www.yuque.com/akiencore/qgdgg5/ksg9eu

import new features and models:

  • in /profiles/models.py
    • add FollowerRelation
    • add 3 variables in Profile ```python class FollowerRelation(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) profile = models.ForeignKey(“Profile”, on_delete=models.CASCADE) timestamp = models.DateTimeField(auto_now_add=True)

class Profile(models.Model):

  1. # A OneToOneField is essentially the same as a ForeignKey
  2. user = models.OneToOneField(User, on_delete=models.CASCADE)
  3. location = models.CharField(
  4. max_length=220, null=True, blank=True) # allow null and blank
  5. bio = models.TextField(blank=True, null=True)
  6. # new
  7. timestamp = models.DateTimeField(auto_now_add=True)
  8. updated = models.DateTimeField(auto_now=True)
  9. followers = models.ManyToManyField(User, related_name="following", blank=True)
  10. """
  11. project_obj = Profile.objects.first()
  12. project_obj.followers.all() -> All users following this profile
  13. users.following.all() -> All users I follow
  14. """
  1. - becuase we have changed the model, makemigration and migrate as usual
  2. ```bash
  3. [root@localhost Twittme]# python3 ./manage.py makemigrations
  4. You are trying to add the field 'timestamp' with 'auto_now_add=True' to profile 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 'profiles':
  14. profiles/migrations/0002_auto_20200729_2241.py
  15. - Add field followers to profile
  16. - Add field timestamp to profile
  17. - Add field updated to profile
  18. - Create model FollowerRelation
  19. [root@localhost Twittme]# python3 ./manage.py migrate
  20. Operations to perform:
  21. Apply all migrations: admin, auth, contenttypes, profiles, sessions, tweets
  22. Running migrations:
  23. Applying profiles.0002_auto_20200729_2241... OK

test case:

  • we simulate a following step in test file
  • in /profiles/tests.py
    • setup 2 users, run 2 tests cases
      • make sure 2 corresponding profiles are created
      • add a follower to a user, and check their following status ```python from django.test import TestCase

Create your tests here.

from django.contrib.auth import get_user_model from .models import Profile

User = get_user_model()

class ProfileTestCase(TestCase): def setUp(self): self.user = User.objects.create_user( username=’cfe’, password=’somepassword’) self.userb = User.objects.create_user( username=’cfe-2’, password=’somepassword2’)

  1. def test_profile_created_via_signal(self):
  2. qs = Profile.objects.all()
  3. self.assertEqual(qs.count(), 2) # the count of profiles is 2
  4. def test_following(self):
  5. first = self.user
  6. second = self.userb
  7. first.profile.followers.add(second) # first is followed by second
  8. second_user_following_whom = second.following.all() # check who second is following
  9. qs = second_user_following_whom.filter(user=first) # check is second following first
  10. first_user_following_no_one = first.following.all()
  11. self.assertTrue(qs.exists()) # second should now following first
  12. self.assertFalse(first_user_following_no_one.exists()) # first should now not following anyone
  1. run test case for only "profiles" app:
  2. ```bash
  3. [root@localhost Twittme]# python3 ./manage.py test profiles
  4. Creating test database for alias 'default'...
  5. System check identified no issues (0 silenced).
  6. ..
  7. ----------------------------------------------------------------------
  8. Ran 2 tests in 1.159s
  9. OK
  10. Destroying test database for alias 'default'...

all 2 cases passed.