Since I first came into contact with DRF, I have been able to understand how DRF is written, generally similar to the django MVT framework, except that Template is replaced by Serializer.
#Ps: Small white talks to himself, big guys please ignore it!!
Goal Establishment
Before we get started, we need to decide two things: what to do? How do you do it? However, I didn't find any interesting projects (or I wasn't good enough...), so I did the simplest:
- Logon function
- Comment function
- Focus on functionality
Use the database as: MySQL
requirement analysis
Now that you have a simple need, you should consider how to do the above functions. Clearly, all three are user-related.
Secondly, the premise of the comment function is that there is so much to comment on, so we add a Tweet-like feature to it: Picture + Text + Comment + Concern.
The general steps are as follows:
- Configuration data model
- Logon function
- Pictures, Long Text and Praise
- follow
Start Time
Before we get started, we need three app s (not counting merchandise information):
Once created, it will probably look like the following image (python manage startapp xxx x)*3
friendships is the focus function app, mysite is the login function, comment function app, scenery is the image upload, with emotional app.
1. Configuration data model
1.1 Rewrite User Model
The User model that comes with Django is somewhat unsatisfactory to do with a Tweet-like function, so we add the data features we want to build on it, such as phone number and gender.
''' position : mysite/models auther : Sthons ''' ... from django.contrib.auth.models import AbstractUser,BaseUserManager class UserManage(BaseUserManager): def _create_user(self,phone,username,password,**kwargs): if not phone: raise ValueError('Please enter your mobile number') if not password: raise ValueError('Please input a password') user = self.model(phone=phone,username=username,**kwargs) user.set_password(password) user.save() return user def create_user(self,phone,username,password,**kwargs): kwargs['is_superuser'] = False return self._create_user(phone=phone,username=username,password=password,**kwargs) def create_superuser(self,phone,username,password,**kwargs): kwargs['is_superuser'] = True return self._create_user(phone=phone, username=username, password=password, **kwargs) ... ... class User(AbstractUser): gender=( ('male','male'), ('female','female'), ('default','secrecy') ) id = models.AutoField(primary_key=True) username = models.CharField(max_length=20, unique=True) sex = models.CharField(max_length=20, choices=gender, default='default') phone = models.CharField(max_length=25, unique=True) USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['phone',] objects = UserManage() def __str__(self): return f'Id: {self.id},Username: {self.username}' ...
- USERNAME_FIELD: Set the authentication identity, defaulting to the user name when admin logs in. Since we override the User model, we need to define it manually. # Ps: You can also change to something else, such as a mailbox number, a mobile number, etc.
- REQUIRED_FIELDS: When a user is created through the create superuser administration command, a list of field names to prompt for is shown below.
1.2 Configure other data models
''' position : mysite/models auther : Sthons ''' class Message(models.Model): id = models.AutoField(primary_key=True) user = models.ForeignKey(User,on_delete=models.CASCADE) content = models.TextField(max_length=400) scenery = models.ForeignKey(Scenery, null=True, on_delete=models.SET_NULL) created_at = models.DateTimeField(auto_now=True) thumbs = models.IntegerField(default=0) # ----------------------------------------------------------------------------------- ''' position : scenery/models auther : Sthons ''' from django.db import models class Scenery(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=140,null=True) img = models.ImageField(upload_to='scenery/images/') text = models.TextField(max_length=280) thumbs = models.IntegerField(default=0) def __str__(self): return f'Landscape Name:{self.title}' # ----------------------------------------------------------------------------------- ''' position : friendships/models auther : Sthons ''' class Friendship(models.Model): # Focuser from_user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='follower_friendship_set') # Focused to_user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='following_friendship_set') created_at = models.DateTimeField( auto_now_add=True ) class Meta: index_together = ( ('from_user_id', 'created_at'), ('to_user_id', 'created_at'), ) unique_together = (('from_user_id', 'to_user_id'),) def __str__(self): return '{} followed {}'.format(self.from_user_id, self.to_user_id)
1.3 Migrate Database
- python manage makemigrations
- python manage migrate
2. Realization of login registration function
2.1 Registration Function
Create a serializers in mysite. Py file, where you enter the following to build our first serialization model.
''' position : mysite/serializer auther : Sthons ''' ... from rest_framework import serializers from mysite.models import User ... ... class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ( 'id', 'username', 'password', 'phone', 'email', 'sex', 'date_joined' ) ... ... class SignupSerializer(serializers.ModelSerializer): class Meta: model = User fields = ('username','password','email','phone','sex') username = serializers.CharField(max_length=14) password = serializers.CharField(max_length=256) email = serializers.EmailField() phone = serializers.CharField(max_length=256) def validate(self, attrs): if User.objects.filter(username=attrs['username']).exists(): raise ValidationError({ "message": [ "The user name is already registered" ] }) if User.objects.filter(email=attrs['email']).exists(): raise ValidationError({ "message": [ "This mailbox is already in use" ] }) if User.objects.filter(phone=attrs['phone']).exists(): raise ValidationError({ "message": [ "The mobile number is already in use" ] }) return attrs def create(self, validated_data): username = validated_data['username'] password = validated_data['password'] email = validated_data['email'] sex = validated_data['sex'] phone = validated_data['phone'] user = User.objects.create( username=username, password=password, email=email, phone=phone, sex=sex ) return user ...
Ideas:
Write a function validate to validate, then raise error s to send error information
Validated_in create Data can be any variable name (it doesn't conflict with other function names) to accept parameters
Write mysite/views later. Py content allows it to be presented in an intuitive way:
''' position : mysite/views auther : Sthons ''' class MysiteViewSet(viewsets.ModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer permission_classes = (AllowAny,) # Logon status @action(methods=['GET'], detail=False) def login_status(self, request): data = {} data['Login_status'] = request.user.is_authenticated if request.user.is_authenticated: data['user'] = UserSerializer(request.user).data return Response(data) # register @action(methods=["POST"], detail=False, serializer_class=SignupSerializer) def signup(self, request): data = SignupSerializer(data=request.data) if not data.is_valid(): return Response({ "success": False, "message": "Please check input", "errors": data.errors, }, status=400) user = data.save() user.set_password(data.validated_data['password']) user.save() login(request, user) return Response({ "success": True, "user": UserSerializer(user).data }, status=201)
Ideas:
* Serialize the data in the request through the serializer
Via is_valid test exception
Submit data to the database via save
Since the password we entered manually is not encrypted, set_is used here The password built-in function encrypts the password and submits it to the database again
Login built-in function for user login
* Last returned json data with status code 201
Last URLs in the root directory. Register it in the pyfile and add it to the url:
''' position : Django_vue_Project1/urls.py auther : Sthons ''' ... site_router = routers.DefaultRouter() ... ... site_router.register(r'mysite', MysiteViewSet, basename='mysite') ... ... urlpatterns = [ path('admin/', admin.site.urls), path('',include(site_router.urls)), path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), ] ...
Design sketch:
2.2 Logon Function
The code for login and registration is written in the same way as before, which I've just written here.
''' position : mysite/views auther : Sthons ''' ... @action(methods=['POST'], detail=False, serializer_class=LoginSerializer) def login(self, request): serializer = LoginSerializer(data=request.data) if not serializer.is_valid(): return Response({ "success": False, "message": "Please check input.", "errors": serializer.errors, }, status=400) username = serializer.validated_data['username'] password = serializer.validated_data['password'] user = authenticate(request, username=username, password=password) if not user: return Response({ "success": False, "message": "Username and password does not match." }, status=400) login(request, user) return Response({ "success": True, "user": UserSerializer(instance=user).data, }) ...
''' position : mysite/serializer auther : Sthons ''' ... from rest_framework import serializers from rest_framework.exceptions import ValidationError from mysite.models import User ... ... # Write an extra serialization here, which you'll use later class SimpleUserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ('id','username') ... ... class LoginSerializer(serializers.ModelSerializer): class Meta: model = User fields = ('username','password') username = serializers.CharField(max_length=14) password = serializers.CharField(max_length=256) def validate(self, attrs): if not User.objects.filter(username=attrs['username']).exists(): raise ValidationError({ "message": [ "user name does not exist" ] }) return attrs ...
#Ps: Actually, this is the end. After all, the code is written in almost the same way, mainly with ideas.
3. Picture upload, long text and compliments
3.1 Picture, Message
''' position : scenery/views auther : Sthons ''' class SceneryViewSet(viewsets.ModelViewSet): queryset = Scenery.objects.all() permission_classes = (IsAuthenticated,) serializer_class = ScenerySerializer @action(methods=['POST'],detail=False,serializer_class = AddPicSerializer) def addScenery(self,request): serializer = AddPicSerializer(data=request.data) if not serializer.is_valid(): return Response({ "success":False, "message":"Please check your input" },status=400) scenery = serializer.save() return Response({ "success": True, "scenery": ScenerySerializer(scenery).data },status=200)
''' position : scenery/serializer auther : Sthons ''' from rest_framework import serializers from mysite.models import Message from mysite.serializers import * from scenery.models import Scenery class SimpleScenerySerializer(serializers.ModelSerializer): class Meta: model = Scenery fields = ('id','title') class ScenerySerializer(serializers.ModelSerializer): class Meta: model = Scenery fields = ('id', 'title', 'img', 'text', 'thumbs') class AddPicSerializer(serializers.ModelSerializer): class Meta: model = Scenery fields = ('title', 'img', 'text') title = serializers.CharField(max_length=140) img = serializers.ImageField() text = serializers.CharField(max_length=280) def create(self, validated_data): title = validated_data['title'] img = validated_data['img'] text = validated_data['text'] scenery = Scenery.objects.create( title=title, img=img, text=text, thumbs=0 ) return scenery
3.2 Comment Module
First of all, the contents of the serializer:
''' position : scenery/serializer auther : Sthons ''' class SimpleEssaySerializer(serializers.ModelSerializer): class Meta: model = Message fields = '__all__' class EssaySerializer(serializers.ModelSerializer): user = SimpleUserSerializer() scenery = SimpleScenerySerializer() class Meta: model = Message fields = ('id', 'user', 'scenery', 'content', 'thumbs', 'created_at') # Show all content class AllEssaySerializer(serializers.ModelSerializer): scenery = SimpleScenerySerializer() class Meta: model = Message fields = ('id', 'scenery', 'content', 'thumbs', 'created_at') # Add Content class AddEssaySerializer(serializers.ModelSerializer): scenery = ScenerySerializer class Meta: model = Message fields = ('id','scenery','content') content = serializers.CharField(max_length=400) def create(self, validated_data): content = validated_data['content'] user = self.context['request'].user scenery = validated_data['scenery'] essay = Message.objects.create( user=user, content=content, scenery=scenery ) return essay
Note here that fields can affect the json parameter characteristics you pass in
#Ps: The name of the serializer here is not very good. The simple prefix should have only one or three data characteristics according to my naming habits, but overall it's not a big problem.
scenery/views.py
''' position : scenery/views auther : Sthons ''' class EssayViewSet(viewsets.ModelViewSet): queryset = Message.objects.all() permission_classes = (IsAuthenticated,) serializer_class = AddEssaySerializer def create(self, request, *args, **kwargs): if not request.user.is_authenticated: return Response({ "message":"Please sign in before speaking" },status=403) serializer = AddEssaySerializer(data=request.data, context={'request': request}) if not serializer.is_valid(): return Response({ "message" : "Please check", "errors" : serializer.errors },status=400) user = EssaySerializer(serializer.save()).data return Response( user, status=201 ) def list(self, request, *args, **kwargs): essay = Message.objects.filter( user_id=request.user.id ).order_by('-created_at') serializer = EssaySerializer(essay, many=True).data return Response({ "essay": serializer })
DRF built-in licensing parameters are used here:
- IsAuthenticated: Authenticated user
- AllowAny: Everyone
- IsAdmin: Administrator
Let's get a general idea:
- The first step is to determine whether a user is logged in through the IsAuthenticated that comes with django.
- Then serialize the data and pass it back to the background with the context. Of course, it's okay to leave the context blank. I'm just here to make it easier to add functionality later
- Submit data to database after passing data validation and return json data
Last in urls. Register the view just written in py:
... site_router.register(r'scenery', SceneryViewSet, basename='scenery') site_router.register(r'context', EssayViewSet, basename='context') ...
See the effect:
First of all, the picture and message modules, you can see that the data has been uploaded successfully, and as for how the pictures are displayed, I don't think of a solution at this time (real white behavior)
Following is the comment:
You can see whether this part of the information is heavy, first according to the foreign key settings of our database: models.SET_NULL, set the value to empty when the data pointed to by the foreign key is deleted, in order to restore the effects of "this content is not available", "cracking".
And the Scenery checkbox below works because:
If parentheses are the details and no parentheses are the references, it is up to us to define what the style is:
4. Focus on Functions
#Ps: Before you write the code for this module, make sure you know who is watching and who is watching.
4.1 Concern
Add code first:
''' position : friendships/views auther : Sthons ''' ... class FriendshipViewSet(viewsets.GenericViewSet): queryset = User.objects.all() serializer_class = FriendshipSerializerForCreate @action(methods=["POST"], detail=True, permission_classes=[IsAuthenticated, ]) def follow(self, request, pk): if Friendship.objects.filter(from_user=request.user, to_user=pk).exists(): return Response({ "success": True, "duplicate": True }, status=201) serializer = FriendshipSerializerForCreate(data={ "from_user_id": request.user.id, "to_user_id": pk }) if not serializer.is_valid(): return Response({ "success": False, "errors": serializer.errors }, status=400) serializer.save() return Response({ 'success': True }, status=201) ...
''' position : friendships/serializer auther : Sthons ''' ... from friendships.models import Friendship from rest_framework import serializers from rest_framework.exceptions import ValidationError from mysite.serializers import UserSerializer ... ... class FriendshipSerializerForCreate(serializers.ModelSerializer): from_user_id = serializers.CharField(max_length=60) to_user_id = serializers.CharField(max_length=60) class Meta: model = Friendship fields = ("from_user_id", "to_user_id") def validate(self, data): if data["from_user_id"] == data["to_user_id"]: raise ValidationError({ "message": [ "You can't care about yourself!!!" ] }) return data def create(self, data): from_user_id = data["from_user_id"] to_user_id = data["to_user_id"] user = Friendship.objects.create( from_user_id=from_user_id, to_user_id=to_user_id ) return user ...
In fact, it is not difficult to focus on modules. The real difficulty lies in the disordered thinking in the programming process. In fact, the problem is mainly the named pot. Anything can be done as long as the name is obtained well.
Again here:
from_user => follower
to_user => watched
When the follower is you and the follower is Li Si
It's like you paid attention to Li Si.
4.2 Check your attention and your fans
With that foundation, the rest is simple:
''' position : friendships/serializer auther : Sthons ''' ... # Your concern class FollowingSerializer(serializers.ModelSerializer): user = UserSerializer(source="to_user") class Meta: model = Friendship fields = ('user', 'created_at',) # Your fans class FollowerSerializer(serializers.ModelSerializer): user = UserSerializer(source="from_user") class Meta: model = Friendship fields = ('user', 'created_at',) ...
''' position : friendships/views auther : Sthons ''' ... # Your concern @action(methods=["GET"], detail=True, permission_classes=[AllowAny, ]) def followings(self, request, pk): user = Friendship.objects.filter(from_user_id=pk).order_by('-created_at') serializer = FollowingSerializer(user, many=True).data return Response({ "followings": serializer }, status=200) # Your fans @action(methods=['GET'], detail=True) def followers(self, request, pk): follower = Friendship.objects.filter(to_user_id=pk).order_by('-created_at') return Response({ "followers": FollowerSerializer(follower, many=True).data }) ...
Finally, close:
''' position : friendships/views auther : Sthons ''' ... @action(methods=['POST'], detail=True) def unfollow(self, request, pk): # write your code here if request.user.id == pk: return Response({ "success": False, "message": "?????" }) if not Friendship.objects.filter(to_user_id=pk, from_user_id=request.user.id).exists(): return Response({ "success": True, "deleted": 0 }) unuser = Friendship.objects.filter(to_user_id=pk, from_user_id=request.user.id) unuser.delete() return Response({ "success": True, "deleted": 1 }) ...
The idea is simple: just judge if you have a relationship with someone you care about=>him, and if so, delete the relationship from the database.
Last paste using method:
Reference to the following figure:
Person with ID number 2
follow: * Focus
followers: What you care about
following:: Focus on your
unfollow: * Close
Well, that's all for this article. Although I know nobody's watching it, I still hope the handsome brothers and beautiful sisters I've seen will point out a compliment.
(╯‵□′)╯︵┻━┻