Like button back end logic using Django Rest Framework - python

I have a Blog app where users can add new Post and any users can like the post.
models.py
class Post(models.Model):
title = models.CharField(max_length=60)
class PostLikes(models.Model):
likeusers = models.ManyToManyField(User)
likepost = models.ForeignKey(Post,on_delete=models.CASCADE,null=True,related_name='likepost')
serializers.py
class PostSerializers(serializers.ModelSerializer):
#likepost = serializers.SerializerMethodField() **I have to mention like count here**
class Meta:
model = Post
fields = '__all__'
class PostlikeSerializer(serializers.ModelSerializer):
class Meta:
model = PostLikes
fields = '__all__'
views.py
class LikeListCreate(APIView):
def get(self,request,pk):#function to get total number of likes to particular post
post = Post.objects.filter(pk=pk) # find which post's likes are to be extracted
like_count = post.likepost.count()# counts total user likes ,besides my code is wrong
serializer = PostlikeSerializer(like_count,many=True)
return Response(serializer.data)
def post(self,request,pk):#function to add likes to post
# how do I check if user is already liked the post ?
likeusers = request.user
likepost = Post.objects.filter(pk=pk)
serializer = PostlikeSerializer(data=request.data)
if serializer.is_valid():
serializer.save(likeusers,likepost)
return Response(serializer.data,status=status.HTTP_201_CREATED)
return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)
urls.py
path('posts/<int:pk>/like/',LikeListCreate.as_view(),name = 'post_likes'),
I am unable to implement logic in views.py module and serializers.py section too. Please help, thanks in advance
Git link to my project https://github.com/Anoop-George/BlogApp.git

You're serialising the request data but you've already extracted data from the request to get the user and the post, I would therefore suggest using that data to create the PostLike in your views.py in a standard way:
new_like = PostLikes(likeusers=request.user, likepost=likepost)
new_like.save()
I would also add that models are usually titled as singular items, i.e. PostLike and not PostLikes - you can refer to postlikes using the related_name of the ForeignKey field.

def post(self,request,pk):
likeusers = User.objects.get(id=2)// user find for testing purpose
likepost = Post.objects.filter(pk=pk)
check = PostLikes.objects.filter(Q(likeusers=like_user) & Q(likepost = likepost.last() ))
if(check.exists()):
return Response({
"status": status.HTTP_400_BAD_REQUEST,
"message":"Already Liked"
})
new_like = PostLikes.objects.create(likeusers=likeusers, likepost=likepost.last())
new_like.save()
serializer = PostlikeSerializer(new_like)
return Response(serializer.data,status=status.HTTP_201_CREATED)

Related

How to have a permission-based user system in Django?

I want to build a REST API where user can do operations on objects, based on their permissions. Consider a record that represents a car - it contains the license number, the type of the car and extra information. Also consider the following user system:
Owners - Who own the car object. Can modify it and delete it.
Editors - Who can only modify the object properties.
Viewers - Can only view the object properties.
Each record can contain multi owners/editors/viewers (The user who created the object should be automatically the owner). Also, owners can add or remove editors/viewers. In my head, I see it as a list of owners/editors/viewers.
So in case of a GET request, I want to be able to return all objects that the user has permissions for, separated into those three categories.
So under my api app, I have the following code:
The models.py file contains:
class CarRecord(models.Model):
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
The serializers.py file contains:
class CarRecordSerializer(serializers.ModelSerializer):
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
class Meta:
model = CarRecord
fields = ('__all__')
In view.py I have:
class CarRecordViews(APIView):
def get(self, request):
if not request.user.is_authenticated:
user = authenticate(username=request.data.username, password=request.data.password)
if user is not None:
return Response(data={"error": "invalid username/password"}, status=status.HTTP_401_UNAUTHORIZED)
# return all records of cars that user some type of permission for
Now, I want to get all the records of user that he has permissions to query (along with their permission type). I thought of adding a three extra fields under CarRecord - each one is a list of users that contains that permission type. But I'm not sure if it's the "Django way". So wanted to consult first with SO.
EDIT: I tried to add the following field to my CarRecord class:
owners = models.ManyToManyField(User, related_name='car_owners', verbose_name=('owners'), default=[])
Also I added:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username']
lass CarRecordSerializer(serializers.ModelSerializer):
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
owners = UserSerializer(many=True)
class Meta:
model = CarRecord
fields = ('__all__')
And the way I create the CarRecordSerializer instance is:
serializer = CarRecordSerializer(data=request.data)
But I get:
{
"error": {
"owners": [
"This field is required."
]
}
}
How to make it work? I guess is my problem is how to serialize a ManyToMany object?
EDIT2: My second attempt is:
class CarRecord(models.Model):
date_created = models.DateTimeField()
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
owners = models.ManyToManyField(User, related_name='car_owners', verbose_name=('owners'), default=[]))
creator = models.ForeignKey(User,on_delete=models.DO_NOTHING)
# ...
class CarRecordSerializer(serializers.ModelSerializer):
date_created = serializers.DateTimeField(default=datetime.now(timezone.utc))
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
creator = serializers.StringRelatedField()
owners = serializers.PrimaryKeyRelatedField(many=True,read_only=True)
class Meta:
model = CarRecord
fields = '__all__'
def create(self, validated_data):
self.owners = [self.context['creator']]
record = CarRecord(**validated_data, creator=self.context['creator'])
record.save()
return record
# ...
# In post method:
serializer = CarRecordSerializer(data=request.data, context={ 'creator': user })
But now, in GET method, I filter the owners list with the user and it can't find the objects:
> CarRecord.objects.filter(owners=user)
<QuerySet []>
Also, in the Admin section I see that all of the objects automatically have all the users in the owners/editors/viewers lists. Why is that? Owners should contain only the user that created the record and editors and viewers should be empty lists. In another query, owner can add additional owners/editors/viewers.
Here is the solution I might think is the right one
class CarRecord(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
owners = models.ManyToManyField(User, related_name='car_owners')
creator = models.ForeignKey(User,on_delete=models.DO_NOTHING)
class CarRecordSerializer(serializers.ModelSerializer):
creator = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), required=False)
owners_details = UserSerializer(source='owners', many=True, read_only=True)
class Meta:
model = CarRecord
fields = '__all__'
def create(self, validated_data):
try:
new_owners = validated_data.pop('owners')
except:
new_owners = None
car_record = super().create(validated_data)
if new_owners:
for new_owner in new_owners:
car_record.owners.add(new_owner)
return car_record
In views.py
from rest_frameword import generics
from rest_framework import permissions
class CustomCarRecordPermissions(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method == 'GET':
return True
elif request.method == 'PUT' or request.method == 'PATCH':
return request.user == obj.creator or request.user in obj.owners.all()
elif request.method == 'DELETE':
return request.user == obj.creator
return False
class CarRecordListCreate(generics.ListCreateAPIView):
permission_classes = (IsAuthenticated, )
serializer_class = CarRecordSerializer
queryset = CarRecord.objects.all()
def post(self, request, *args, **kwargs):
request.data['creator'] = request.user.id
return super().create(request, *args, **kwargs)
class CarRecordDetailView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = (CustomCarRecordPermissions, )
serializer_class = CarRecordSerializer
lookup_field = 'pk'
queryset = CarRecord.objects.all()
models is self explanatory;
In CarRecord serializers we set creator as required False and primary key related field so that we can supply request user id before create as shown in views.py post method.
In Detail view we set our custom permission; If the request is GET we allow permissions. But if the request is PUT or PATCH the owners and the creator are allowed. But if it is a delete request only creator is allowed.
I think the django-rest-framework-guardian package fits here. This package is based on django-guardian.
django-guardian is an implementation of object permissions for Django providing an extra authentication backend.
There is no change on your models.py
You should change serializers.py and views.py.
For example, your serializer should look like this
from rest_framework_guardian.serializers import ObjectPermissionsAssignmentMixin
class CarRecordSerializer(ObjectPermissionsAssignmentMixin, serializers.ModelSerializer):
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
class Meta:
model = CarRecord
fields = ('__all__')
def get_permissions_map(self, created):
current_user = self.context['request'].user
readers = Group.objects.get(name='readers')
editors = Group.objects.get(name='editors')
owners = Group.objects.get(name='owners')
return {
'view_car_record': [current_user, readers, owners],
'change_car_record': [current_user, editors],
'delete_car_record': [current_user, owners]
}
and your views should look like this:
from rest_framework_guardian import filters
class CarRecordModelViewSet(ModelViewSet):
queryset = CarRecord.objects.all()
serializer_class = CarRecordSerializer
filter_backends = [filters.ObjectPermissionsFilter]
Edit settings.py like this:
INSTALLED_APPS = [
'rest_framework',
'guardian',
]
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"guardian.backends.ObjectPermissionBackend",
]
You can define filter backends globally in your settings, too:
REST_FRAMEWORK = {
"DEFAULT_FILTER_BACKENDS": [
"django_filters.rest_framework.DjangoFilterBackend",
"rest_framework_guardian.filters.ObjectPermissionsFilter",
],
}
Don't forget! If you define the ObjectPermissionsFilter in the settings.py, your all views are affected by this filter.
If you want to restrict post request per user, you shoul implement custom permission class, like this:
from rest_framework import permissions
class CustomObjectPermissions(permissions.DjangoObjectPermissions):
"""
Similar to `DjangoObjectPermissions`, but adding 'view' permissions.
"""
perms_map = {
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
'HEAD': ['%(app_label)s.view_%(model_name)s'],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}
Check this link to get the detailed information for the CustomObjectPermissions
You can write permission class car owner user.
Your model.
class CarRecord(models.Model):
date_created = models.DateTimeField()
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
owners = models.ManyToManyField(User, related_name='car_owners', verbose_name=('owners'), default=[]))
creator = models.ForeignKey(User,on_delete=models.DO_NOTHING)
Permission class permission.py
from rest_framework.permissions import BasePermission,
from cars.models import CarRecord
class isCarAccess(BaseCommand):
def has_permission(self, request, view):
if request.method == 'OPTIONS':
return True
check_user = CarRecord.objects.filter(owners__in=[request.user])
return request.user is not None and request.user.is_authenticated and check_user
this permission class will check that does user exists, user is authenticated and as well the user belongs to the card record or not.
And you can pass this permission in your view.
from .permission import isCarAccess
from .models import CarRecord
class CarRecordViews(APIView):
permission_classes = [isCarAccess]
def get(self, request):
car_record = CarRecord.objects.filter(owners__in=[request.user])
# return all records of cars that user some type of permission for
and your settings.py
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"oauth2_provider.contrib.rest_framework.OAuth2Authentication",
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.TokenAuthentication",
),
}

Direct assignment to the forward side of a many-to-many set is prohibited. Use Class.set() instead

When I try to save Class which is in many to many relationship django throws the following error
TypeError at /class-create/
Direct assignment to the forward side of a many-to-many set is prohibited. Use Class.set() instead.
My views.py looks like this
#login_required()
def create_class(request):
tea_user = request.user.username
validate = teacher_validation(tea_user)
if validate:
if request.method == 'POST':
Link = request.POST.get('link')
Subject = request.POST.get('Subject')
Class = request.POST.get('Class')
teacher_user = Teacher.objects.get(User=request.user)
teacher = Teacher.objects.get(id=teacher_user.id)
created_class = Online_Class(Link=Link, Subject=Subject, Created_by =teacher, Class=Class)
created_class.save()
return render(request, 'online_class/Teacher/class-create.html')
else:
messages.warning(request, 'Sorry You Dont have Permission to access this page')
return redirect('logout')
And my models.py file looks like this
class Online_Class(models.Model):
Created_by = models.ForeignKey(Teacher, on_delete=models.DO_NOTHING)
Class = models.ManyToManyField(Classes)
Subject = models.CharField(max_length=100)
Link = models.CharField(max_length=200)
Joined_by = models.ManyToManyField(Student, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
choice = (('Yes','Yes'),('No', 'No'))
Class_Ended = models.CharField(choices=choice, default='No', max_length=10)
Please help me figure it out
You can not set class=Class in:
created_class = Online_Class(Link=Link, Subject=Subject, Created_by =teacher, Class=Class)
since Class is a ManyToManyField, and thus can not be set like that, you first create the OnelineClass, and then add an entry (or more entries) with created_class.Class.set(&hellip):
#login_required
def create_class(request):
tea_user = request.user.username
validate = teacher_validation(tea_user)
if validate:
if request.method == 'POST':
Link = request.POST.get('link')
Subject = request.POST.get('Subject')
Class = request.POST.get('Class')
teacher_user = Teacher.objects.get(User=request.user)
teacher = Teacher.objects.get(id=teacher_user.id)
created_class = Online_Class.objects.create(
Link=Link,
Subject=Subject,
Created_by =teacher
)
created_class.Class.set([Class])
return render(request, 'online_class/Teacher/class-create.html')
else:
messages.warning(request, 'Sorry You Dont have Permission to access this page')
return redirect('logout')
Note: normally a Django models, just like all classes in Python are given a name in PascalCase, not snake_case, so it should be: OnlineClass instead of Online_Class.
Note: normally the name of the fields in a Django model are written in snake_case, not PascalCase, so it should be: class instead of Class.
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.

Django: Update a specific field with a GET instead of a PATCH

Context
For a specific use case I need to be able to update a single field of my Visitor model using a GET request instead of a PATCH request.
My relevant Visitor model looks like this:
# models.py
class Visitor(models.Model):
visitor_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
customers = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='customer_visitors')
audiences = models.ManyToManyField(Audience, related_name='audience_visitors')
cid = models.CharField(max_length=255, unique=True)
uid = models.CharField(max_length=255)
cup = JSONField(null=True)
def __str__(self):
return self.cid
class Meta:
db_table = 'visitor'
I am using a straightforward serializer like this:
# serializers.py
class VisitorSerializer(serializers.ModelSerializer):
class Meta:
model = Visitor
fields = ('customers', 'cid', 'uid', 'cup')
I am able to update just the cup field for a specific Visitor which is looked up using the unique cid field with a PATCH like this:
# views.py
class VisitorViewSet(viewsets.ModelViewSet):
serializer_class = VisitorSerializer
queryset = Visitor.objects.all()
lookup_field = 'cid'
def list(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.serializer_class(instance, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
Problem
The problem is that I am unable to update the cup field of a Visitor based on a given unique cid field using a GET request.
What I tried
As this answer by Uri Shalit suggested, I tried to override get_serializer() inside my VisitorViewSet and tried to use it in list() like this:
# views.py
class VisitorViewSet(viewsets.ModelViewSet):
serializer_class = VisitorSerializer
queryset = Visitor.objects.all()
lookup_field = 'cid'
def get_serializer(self, *args, **kwargs):
kwargs['partial'] = True
return super(VisitorViewSet, self).get_serializer(*args, **kwargs)
def list(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
However, updating just the cup field of a specific Visitor based on the cid field works with a PATCH request but does not update said field with a GET request. There is no error either.
Expected behaviour
Making a GET request which contains cid to identify a Visitor and cup with data that needs to be updated for the given Visitor. I know it breaks REST principles but for this use case I need to do this partial update using a GET request instead of a PATCH request.
Any help or pointers in the right direction would be much appreciated!
Add a classmethod in your model.
class Visitor(models.Model):
visitor_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
customers = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='customer_visitors')
audiences = models.ManyToManyField(Audience, related_name='audience_visitors')
cid = models.CharField(max_length=255, unique=True)
uid = models.CharField(max_length=255)
cup = JSONField(null=True)
def __str__(self):
return self.cid
class Meta:
db_table = 'visitor'
#classmethod
def update_cup(cls, cid, cup_new):
instance = cls.objects.get(cid=cid)
instance.cup = new_cup
instance.save()
In ModelViewSet override the get_queryset method, see below:
IDK how u calc new_cup I guess u get it as a queryparam
def get_queryset(self):
queryset = Visitor.objects.all()
cup_new = self.request.query_params.get('cup_new', None)
cid = self.request.query_params.get('cid', None)
[obj.update_cup(obj.cid, cup_new) for obj in queryset if obj.cid == cid]
return queryset
I recommend using an api_view to accomplish what you want. api_view is an annotation provided by the rest framework so it should be available already in your case.
#api_view(["GET"])
def update_function(request):
query_params = request.GET # Getting the parameters from request
cid = query_params["cid"]
cup = query_params["cup"]
visitor = Visitor.objects.get(cid = cid)
visitor["cup"] = cup
serializer = VisitorSerializer(data = visitor, partial=True)
if serializer.is_valid():
serializer.save()
else:
print(serializer.errors)
However I am not sure about the syntax but the approch is sufficient for your problem.
Make sure to add the function to urls.py and have a look to the documentation to get better information than mine Api Views. But dont expect it to have information about you specific problem. In your case you have to understand the api_view concept and adapt it for your needs.
I think I don't understand the problem fully. Why can't you simply override the method get_object() in your view and do custom logic in it to update the object?
def get_object(self):
obj = super().get_object()
serializer = self.get_serializer(obj, data=self.request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return obj

How to pass PK into a method decorator

Hello guys i am trying to implement some form of access control on my views. My programme is structured as such:
1 project has some users which are tied to it in the form of a foreign key. I only wish to allow those whom are involved in it to view this project. The problem however is that the PK i use to query the database for my template is in my URL , users which do not have access to the project can simply change the url query and gain access to the items they do not have access to.
I came across django's user_passes_test method decorator and thought that it is exactly what i needed to implement this user access control.
Here is some code that i have came up with:
My view:
#method_decorator(user_passes_test(project_check(id)),name ='dispatch')
class ProjectDetailView(CreateView):
##this is actually not relavant##
model = SalesNotation
fields = ['sales_notes']
exclude = ['notation_id']
template_name = 'rnd/projects.html'
context_object_name = 'form'
##this is actually not relavant##
def get_context_data(self, **kwargs):
id = self.kwargs['id']
context = super(ProjectDetailView, self).get_context_data(**kwargs)
context['projects'] = SalesProject.objects.filter(sales_project_id = id)
This is my URL:
path('projects/<int:id>/', ProjectDetailView.as_view(), name = 'rnd-projects'),
This is my project model:
class SalesProject(models.Model):
sales_project_id = models.AutoField(primary_key=True)
sales_project_name = models.CharField(max_length=100)
salesExtra = models.ManyToManyField('SalesExtra', blank=True)
Here is my extended user model which i use to keep other information:
class SalesExtra(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
user_type = models.TextField(max_length=500, choices= role)
contact = models.IntegerField()
email = models.TextField(max_length=30,default = 'your email here')
Here is the method decorator that im using:
def project_check(user,id):
return SalesProject.objects.filter(sales_project_id=id).filter(salesExtra__user=user)
However it seems that i am unable to simply pass in the PK from the url as i recieve this error when running the server:
#method_decorator(user_passes_test(project_check(id) , name='dispatch'))
TypeError: project_check() missing 1 required positional argument: 'id
Any help will be greatly appreciated!
You can't. But you can just use UserPassesTestMixin instead:
from django.contrib.auth.mixins import UserPassesTestMixin
class ProjectDetailView(UserPassesTestMixin, CreateView):
##this is actually not relavant##
model = SalesNotation
fields = ['sales_notes']
exclude = ['notation_id']
template_name = 'rnd/projects.html'
context_object_name = 'form'
##this is actually not relavant##
def get_context_data(self, **kwargs):
id = self.kwargs['id']
context = super(ProjectDetailView, self).get_context_data(**kwargs)
context['projects'] = SalesProject.objects.filter(sales_project_id = id)
def test_func(self):
return SalesProject.objects.filter(sales_project_id=self.kwargs["id"]).filter(salesExtra__user=self.request.user)
Note test_func here which performs check. self.kwargs["id"] will give you id.

How to implement PUT method in Django

How can I enable the user to generate only one instance of an object “bet” with a POST method and modify it through a PUT method (for example)
forms.py
class BetForm(forms.ModelForm):
team1_score = forms.IntegerField(min_value=0, max_value=15)
team2_score = forms.IntegerField(min_value=0, max_value=15)
match = forms.ModelChoiceField(queryset=Match.objects.only('id'))
class Meta:
model = Bet
fields = ('team1_score', 'team2_score', 'match')
models.py
class Bet(models.Model):
match = models.ForeignKey(Match, on_delete=models.CASCADE, related_name='+')
team1_score = models.PositiveIntegerField(default=0)
team2_score = models.PositiveIntegerField(default=0)
def __str__(self):
return (str(self.match))
views.py
def post(self, request):
form = BetForm(request.POST)
if form.is_valid():
form.save()
team1_score = form.cleaned_data.get('team1_score')
team2_score = form.cleaned_data.get('team2_score')
match = form.cleaned_data.get('match')
form = BetForm()
return redirect ('home')
args = {'form': form, 'team1_score': team1_score, 'team2_score': team2_score, 'match': match}
return render(request, self.template_name, args)
Enable the user to generate only one instance of an object “bet”...
For that, you want to add a user field to your Bet model. Here you will save a reference to the user making the request.
class Bet(models.Model):
user = models.ForeignKey(AUTH_USER_MODEL, related_name='bets', blank=True)
match = models.ForeignKey(Match, related_name='bets')
team1_score = models.PositiveIntegerField(default=0)
team2_score = models.PositiveIntegerField(default=0)
class Meta:
unique_together = ('user', 'match')
def __str__(self):
return (str(self.match))
Notice the unique_together option which makes sure a user can only create a single Bet instance for a given match.
modify it through a PUT method (for example)
Django does not automatically parse the body for PUT requests like it does for POST. Browsers normally issue POST request on forms submission. If you still want to solve it using PUT, check this post (pun intended).
Parsing Unsupported Requests (PUT, DELETE, etc.) in Django
My suggestion is to modify your post view so it accepts an optional parameter bet_id. This you can define in urlpatterns. The view would then look like this one. You retrieve the bet if bet_id is provided and pass it to the form. This way it understands the user is modifying it.
def post(self, request, bet_id=None):
if bet_id:
bet = Bet.objects.get(pk=bet_id)
form = BetForm(request.POST, instance=bet)
else:
form = BetForm(request.POST)
if form.is_valid():
bet = form.save(commit=False)
bet.user = request.user
bet.save()
# Do what you want here
Notice that we are not saving the form immediately (commit=False), so we could assign it to a user later on. This user is the logged in user from the request object.

Categories