I wanted to get the date or tablerequireDate argument from the POST requests, how do I achieve in the below view layer ?
VIEWS.PY
class Tablecreateview(generics.CreateAPIView):
queryset = Tables.objects.all()
serializer_class = Tableserializer
def perform_create(self, serializer):
request_user = self.request.user
serializer.save(author=request_user)
MODELS.PY
class Tables(models.Model):
tablerequiretime = models.TimeField()
tablerequireDate = models.DateField()
created = models.DateTimeField(auto_now=True)
updatedat = models.DateTimeField(auto_now_add=True)
foodliketoeat = models.CharField(max_length=200)
totalpersons = models.PositiveIntegerField(
default=0, validators=[MinValueValidator(0), MaxValueValidator(20)])
author = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
def __str__(self):
return self.author.username
SERIALIZERS.PY
class Tableserializer(serializers.ModelSerializer):
class Meta:
model = Tables
exclude=('author',)
Okay you can access this field before perform_create takes place
class Tablecreateview(generics.CreateAPIView):
queryset = Tables.objects.all()
serializer_class = Tableserializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
tablerequireDate = serializer.data['tablerequireDate']
# Do you magic then perform creation
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
Another Round of a solution
class Tableserializer(ModelSerializer):
class Meta:
model = Tables
exclude=('author',)
def validate_tablerequireDate(self, data):
try:
# do validation
except ValidationError:
raise Validation.....
else:
return validated_data
Related
How do I append current logged in user to request.data when making post call to create a new chat. I tried append it to the request.data but its a querydict and immutable
// models.py
class ChatLog(models.Model):
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
participants = models.ManyToManyField(Profile, related_name='chatlogs')
def __str__(self):
return str(self.id)
class Message(models.Model):
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
chat_log = models.ForeignKey(ChatLog, on_delete=models.CASCADE, related_name='messages')
sender = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='sentmessages')
body = models.TextField()
is_read = models.BooleanField(default=False, null=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.id)
class Meta:
ordering = ['-created']
// views.py
class ChatList(generics.ListCreateAPIView):
serializer_class = ChatSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
user = self.request.user.profile
return user.chatlogs.all()
def post(self, request, *args, **kwargs):
serializer = ChatSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
The ListCreateAPIView specifically has the perform_create method you can override. By default it just does:
def perform_create(self, serializer):
serializer.save()
You can override that to add additional data to the serializer for example:
def perform_create(self, serializer):
serializer.save(sender=self.request.user)
Get rid of your post method, you're just overriding and repeating the automagic for which you're using generic views in the first place.
I want to give only the information of the user who requested with self.request.user, but for some reason, this way I get the information of all users.
How can I improve this so that we can retrieve only the information of the user who requested it?
Please let me know if you know anything about this.
View
class StatisticsViewSet(APIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = EntrySerializer
def get(self, request):
queryset = self.request.user.entries.all()
serializer = StatisticsSerializer(queryset)
return Response(serializer.data)
Serializer
class StatisticsSerializer(serializers.Serializer):
daily_report = serializers.SerializerMethodField()
daily_report_week = serializers.SerializerMethodField()
def get_daily_report(self, obj):
data = Entry.objects.filter(user=obj.user).values(
'created_at__year', 'created_at__month',
'created_at__day').annotate(Sum('time')).order_by(
'created_at__year', 'created_at__month', 'created_at__day')
........
...
...
Model
class Entry(models.Model):
project = models.ForeignKey(Project,
related_name='entries',
on_delete=models.CASCADE)
time = models.IntegerField(default=0)
user = models.ForeignKey(User,
related_name='entries',
on_delete=models.CASCADE)
created_at = models.DateTimeField(default=datetime.now)
def __str__(self):
return '%s - %s' % (self.project.name, self.created_at)
You can filter the queryset inside the serializer using the context
Serializer:
class StatisticsSerializer(serializers.Serializer):
daily_report = serializers.SerializerMethodField()
daily_report_week = serializers.SerializerMethodField()
def get_daily_report(self, obj):
user = self.context['request'].user
data = Entry.objects.filter(user=user).values(
'created_at__year', 'created_at__month',
'created_at__day').annotate(Sum('time')).order_by(
'created_at__year', 'created_at__month', 'created_at__day')
View:
class StatisticsViewSet(APIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = EntrySerializer
def get(self, request):
queryset = self.request.user.entries.all()
serializer = StatisticsSerializer(queryset, context = {'request': self.request)
return Response(serializer.data)
I will try to make a check for the uniqueness of the field at the validation level in the serializer and can not understand why the validator is not called at all.
models.py
class Vendor(models.Model):
active = models.BooleanField(default=False)
...
class VendorContacts(models.Model):
vendor = models.ForeignKey('Vendors', related_name='contacts', on_delete=models.CASCADE)
email = models.CharField(max_length=80, blank=True, null=True)
.....
serializer.py
class VendorContactCreateSerializer(serializers.ModelSerializer):
email = serializers.CharField(validators=[RegexValidator(regex=r'[^#]+#[^\.]+\..+',
message='Enter valid email address')])
vendor = serializers.PrimaryKeyRelatedField(queryset=Vendors.objects.all(), required=False, allow_null=True)
class Meta:
model = VendorContacts
fields = (.....
)
def create(self, validated_data):
.....
#some logic
def validate_email(self, value):
print('Start validation')
exist_contact = VendorContacts.objects.filter(email=value)
if exist_contact:
vc = get_object_or_404(VendorContacts, email=value)
v = vc.vendor
if v.active:
raise serializers.ValidationError('Email {} already exists'.format(value))
return value
In the above serializer, I perform a check at the def validate_email() model field level.
print('Start validation') is not called.
I tried the same at the object level through def validate(): but it is not called either.
UPD
views.py
class VendorContactsCreateView(APIView):
permission_classes = [permissions.AllowAny, ]
serializer_class = VendorContactCreateSerializer
def post(self, request, *args, **kwargs):
data = request.data
serializer = VendorContactCreateSerializer(data=data)
try:
serializer.is_valid(raise_exception=True)
serializer.save()
except ValidationError:
return Response({"errors": (serializer.errors,)},
status=status.HTTP_400_BAD_REQUEST)
else:
return Response(request.data, status=status.HTTP_200_OK)
While building my API, I didn't think about the logic behind notifications. Please, How do I solve a problem like this on a potentially big project? let us assume I have the code below:
model.py
class Showcase(models.Model):
title = models.CharField(max_length=50)
description = models.TextField(null=True)
skill_type = models.ForeignKey(Skill, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="Showcases")
content = models.TextField(null=True)
created_on = models.DateTimeField(auto_now=True)
updated_on = models.DateTimeField(auto_now_add=True)
voters = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="upvotes")
slug = models.SlugField(max_length=255, unique=True)
serializer.py
class ShowcaseSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(read_only=True)
created_on = serializers.SerializerMethodField(read_only=True)
likes_count = serializers.SerializerMethodField(read_only=True)
user_has_voted = serializers.SerializerMethodField(read_only=True)
slug = serializers.SlugField(read_only=True)
comment_count = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Showcase
exclude = ['voters', 'updated_on']
def get_created_on(self, instance):
return instance.created_on.strftime("%d %B %Y")
def get_likes_count(self, instance):
return instance.voters.count()
def get_user_has_voted(self, instance):
request = self.context.get("request")
return instance.voters.filter(pk=request.user.pk).exists()
def get_comment_count(self, instance):
return instance.comments.count()
view.py
# SHOWCASE APIView
class showcaseCreateViewSet(generics.ListCreateAPIView):
'''
Create showcases view. user must be logged in to do this
'''
queryset = Showcase.objects.all()
serializer_class = ShowcaseSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class ShowcaseLikeAPIView(APIView):
'''
Can like(post) and unlike(delete) the showcases, must be
authenticated to do this
'''
serializer_class = ShowcaseDetaiedSerializer
permission_classes = [IsAuthenticated]
def delete(self, request, slug):
showcase = get_object_or_404(Showcase, slug=slug)
user = self.request.user
showcase.voters.remove(user)
showcase.save()
serializer_context = {"request": request}
serializer = self.serializer_class(showcase, context=serializer_context)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request, slug):
showcase = get_object_or_404(Showcase, slug=slug)
user = self.request.user
showcase.voters.add(user)
showcase.save()
serializer_context = {"request": request}
serializer = self.serializer_class(showcase, context=serializer_context)
return Response(serializer.data, status=status.HTTP_200_OK)
with the code above that likes a user's post(Showcase), I am trying to figure out how the user can get notified when a user likes his post.
and the things I am considering for the notification, the user that gets notified, the user that makes the action, the post(in this case showcase) that is getting the action, the message that gets passed, a boolean field for if it has been read. The method that comes to my head is creating an app for that but after nothing else. please, how do I solve a problem like this, or what is the best/recommended way to solve this?
I'm new to creating REST API so I might misunderstand something.
I'm creating REST API using Django Rest Framework. And I'm trying to create an object and send it from my mobile app.
However, API returns 400. I think it still cannot associate the object with the request user and I'm wondering how to do it.
models.py
class Item(models.Model):
item_name = models.CharField()
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
serializers.py
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('item_name', 'created_by')
and views.py
class ListItems(generics.ListCreateAPIView):
queryset = Item.objects.all()
serializer_class = ItemSerializer
What I want to know is how to associate the object with the request user when posting the object like as we do like
if form.is_valid():
item = form.save(commit=False)
item.created_by = request.user
item.save()
I think the easiest approach is like this:
class ItemSerializer(serializers.ModelSerializer):
created_by = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
Reference can be found here
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('item_name',)
class ListItems(generics.ListCreateAPIView):
...
def perform_create(self, serializer):
serializer.save(created_by=self.request.user)
you can do this way
One of the possible way to overwrite serializer_create method. As user is not associated with request.data first we need to make sure, this is write_only field and also need to assign current user from modelSerializer's self.context.request.user. Following addition should solve the problem.
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('item_name', 'created_by')
extra_kwargs = {'created_by': {'write_only': True}}
def create(self, validated_data):
item = Item(
item_name=validated_data['item_name'],
created_by=self.context.request.user
)
item.save()
return item
Reference link
It works for me
models.py
class Category(models.Model):
name = models.CharField('Category', max_length=200, unique=True, help_text='Name of the category')
slug = models.SlugField('Slug', max_length=100, db_index=True, unique=True, help_text='Name of the category in format URL')
def __str__(self):
return (self.name)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Category, self).save(*args, **kwargs)
serializers.py
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = [
'id', 'name', 'slug'
]
read_only_fields = [
'slug',
]
Finally, I get the user in the view, before to save the post.
views.py
class CategoryList(APIView):te a new category instance.
permission_classes = (IsAuthenticatedOrReadOnly,)
def get(self, request, format=None):
categories = Category.objects.all()
serializer = CategorySerializer(categories, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request, format=None):
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
serializer.save(created_by=self.request.user)
Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)