This is my serializer
class SparkleTemplateSerializer(serializers.ModelSerializer):
notifications = NotificationTemplateSerializer(source='notificationtemplate_set', many=True)
rules = RuleTemplateSerializer(source='ruletemplate_set', many=True)
class Meta:
model = SparkleTemplate
fields = ['id', 'name', 'description', 'enabled', 'run_schedule', 'notifications', 'rules']
I need to show and hide "notifications" field which is foreign key as you can see, but that need to happen if some variable is true or false.
This is how I tried to do it, by adding the code below to a serializer, but I guess it doesn't work cuz of the fields property in Meta
def to_representation(self, obj):
show = NotificationTemplate._meta.get_field('show')
rep = super(SparkleTemplateSerializer, self).to_representation(obj)
if show is False:
rep.pop('notifications', None)
return rep
I also tried excluding "notifications" and creating another serializer, but that doesn't work cuz "notifications" has to be there, so I was getting errors. Thanks
EDIT 1: SparklesTemplate model
company = models.ForeignKey(
Company, on_delete=models.DO_NOTHING, blank=False, default=1)
name = models.CharField(max_length=64, blank=False)
description = models.CharField(max_length=256, blank=False, default="")
enabled = models.BooleanField(default=False, blank=False)
visible = models.BooleanField(default=True, blank=False)
# sparkle must determine just how often it should run.
# a cron string is the most flexible way to determine the schedule
run_schedule = models.CharField(max_length=128, blank=False, default="*/15 * * * *",
help_text="The cron formatted schedule that the notifications will trigger on.")
# this will be appended to the end of the get visits query
query_extra_arguments = models.CharField(max_length=256,
blank=True,
help_text="Extra arguments that will be added to the get visits query.")
branch_owner = models.ForeignKey(Branch, on_delete=models.DO_NOTHING, blank=True, default=None, null=True, help_text="Dictates the visibility of the users.")
NotificationTemplate model:
sparkle = models.ForeignKey(
SparkleTemplate, on_delete=models.CASCADE, blank=False)
enabled = models.BooleanField(default=True)
show = models.BooleanField(default=True)
class_name = models.ForeignKey(
NotificationClass, on_delete=models.CASCADE, blank=False)
class_args = models.TextField(max_length=16384, default="{}", blank=False)
Also, I mixed up the direction of the foreign key in my post, it's the opposite.
EDIT 2 View.py
class SparkleTemplateView(ListAPIView):
serializer_class = SparkleTemplateSerializer
def get_queryset(self):
user = self.request.user
return SparkleTemplate.objects.filter(branch_owner=user.branch)
CodePudding user response:
We can remove the elements in the resulting dictionary from to_representation()
by accessing the show
attribute of each item in the notifications
.
Depending on how you want the notifications to show, here are 2 options:
- Option-1: If you want to remove all
notifications
if at least 1show
isFalse
- Option-2: If you only want to remove the
notifications
whereshow
isFalse
def to_representation(self, obj):
rep = super().to_representation(obj)
# Option 1: If you want to remove all notifications if at least 1 show is False
# if any(notif["show"] is False for notif in rep["notifications"]):
# del rep['notifications'] # Or rep.pop('notifications')
# Option 2: If you only want to remove the notifications where show is False
rep["notifications"] = list(filter(lambda notif: notif["show"], rep["notifications"]))
return rep
CodePudding user response:
You can use the prefetch_related
method with a Prefetch
object, normally this is used to solve the N 1 problem but another thing is allows is to provide a queryset for the prefetched object.
Hence you can modify your view as follows:
from django.db.models import Prefetch
class SparkleTemplateView(ListAPIView):
serializer_class = SparkleTemplateSerializer
def get_queryset(self):
user = self.request.user
shown_notifications = NotificationTemplate.objects.filter(show=True)
queryset = SparkleTemplate.objects.filter(
branch_owner=user.branch
).prefetch_related(
Prefetch('notificationtemplate_set', queryset=shown_notifications)
)
return queryset
Now you can skip modifying the serializers to_representation
as you have already filtered to only show the required NotificationTemplate
objects.