I would like to minimize number of queries to get data. I have 3 models:
class SubCategory(models.Model):
game = models.ForeignKey(Game, verbose_name=_("Gra"), on_delete=models.CASCADE)
name = models.CharField(verbose_name=_("Nazwa"), max_length=40)
...
class GameTask(CloneModel):
game = models.ForeignKey(Game, verbose_name='Gra', related_name='tasks', on_delete=models.CASCADE)
name = models.CharField(verbose_name='Nazwa', max_length=200)
subcategory = models.ForeignKey(SubCategory, verbose_name=_("Podkategoria"), on_delete=models.SET_NULL, blank=True, null=True)
class TaskLevel(CloneModel):
name = models.CharField(max_length=50)
master_task = models.ForeignKey(GameTask, related_name='sub_levels', on_delete=models.CASCADE)
My subcategory view looks like:
class SubCategoryList(ListAPIView, PermissionMixin):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = SubCategorySerializer
def get_queryset(self):
return SubCategory.objects.filter(game=self.get_game()).order_by("slug")
and my SubCategorySerializer:
class SubCategorySerializer(serializers.ModelSerializer):
developments = SubCategoryDevelopmentSerializer(many=True, read_only=True)
in_progress = serializers.SerializerMethodField()
class Meta:
model = SubCategory
fields = ("id", "name", "slug", "description", "image", "developments", "in_progress")
def get_in_progress(self, obj: SubCategory):
user = self.context["request"].user
subcategory_tasks = obj.gametask_set.all()
// rest of the logic
All I want to achieve is to return only tasks, which are related to TaskLevel model as master_task. I was trying using
subcategory_tasks = obj.gametask_set.all().prefetch_related("sub_levels")
but the amount of queries was the same. Could somebody give my any hint how to solve this?
Related
I need to get value of basket in 'title' not in 'id'.
How can I do this? How can I get a value of 'title' from 'Position' model in another 'Client' model using ManyToManyField. It automatically transmits ID and the 'title' is required
I have tried many ways but... It must be easy, but i search info 2 days
class Position(models.Model):
title = models.CharField(max_length=150, verbose_name='Title')
slug = models.SlugField(max_length=100, unique=True, db_index=True, verbose_name='URL')
description = models.CharField(max_length=500, verbose_name='Describe')
photo = models.ImageField(upload_to="photos/%Y/%m/", verbose_name='Photo', null=True)
price = models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Price')
date_create = models.DateTimeField(auto_now_add=True, verbose_name='Date create')
date_update = models.DateTimeField(auto_now=True, verbose_name='Date update')
is_published = models.BooleanField(default=True, verbose_name='Is published')
in_stock = models.BooleanField(default=True, verbose_name='In stock')
class Client(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
basket = models.ManyToManyField('Position', default=None, blank=True, related_name='basket')
def __str__(self):
return f'{self.user.username}, id-{self.user.id}'
class ClientSerializer(serializers.ModelSerializer):
class Meta:
model = Client
fields = "__all__"
class ClientViewSet(viewsets.ModelViewSet):
serializer_class = ClientSerializer
permission_classes = (IsOwnerOrReadOnly,)
def get_queryset(self):
pk = self.kwargs.get('pk')
# need a list of objects, not an one
return Client.objects.filter(pk=pk)
result:
{
"id": 1,
"user": 1,
"basket": [
1
]
}
need something like this - "basket":['monitor','keyboard']
You can use the PositionSerializer to get the title of each Position object in the Client's basket ManyToManyField.
class PositionSerializer(serializers.ModelSerializer):
class Meta:
model = Position
fields = ('title',)
class ClientSerializer(serializers.ModelSerializer):
basket = PositionSerializer(many=True, read_only=True)
class Meta:
model = Client
fields = "__all__"
I have 3 models:
class Artist(Timestamps):
name = models.CharField('Name', max_length=255, blank=True)
...
class Festival(Timestamps):
name = models.CharField(max_length=255, blank=True)
...
class Event(Timestamps):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE, null=True)
festival = models.ForeignKey(Festival, on_delete=models.CASCADE, null=True)
Now I wan't all the id's from the festivals an artist is playing. I have a serializer like this:
class ArtistFestivalSerializer(serializers.ModelSerializer):
class Meta:
model = Artist
fields = ('id', 'name', 'event_set')
But this only gives me the id's of the event. Any ideas how to get trough the Event to the Festival?
Thanks in advance
EDIT - the view is:
class FestivalArtists(generics.ListAPIView):
serializer_class = ArtistFestivalSerializer
def get_queryset(self):
queryset = Artist.objects.prefetch_related('event_set').filter(event__isnull=False).distinct().order_by('name')
return queryset
I think you need to add the custom field for that.
class ArtistFestivalSerializer(serializers.ModelSerializer):
festival_ids = serializers.SerializerMethodField(read_only = True)
class Meta:
model = Artist
fields = ('id', 'name', 'event_set', 'festival_ids')
def get_festival_ids(self, obj):
return list(Event.objects.filter(artist = obj).values_list('festival_id').distinct())
I have 3 models which are related to each other via ManytoMany relation like this:
class DemandEvents(models.Model):
date = models.DateTimeField(blank=True, null=True)
quantity = models.IntegerField(default=0)
class DemandFlows(models.Model):
events = models.ManyToManyField(DemandEvents)
flow = models.ForeignKey(Flow, on_delete=models.CASCADE)
kit = models.ForeignKey(Kit, on_delete=models.CASCADE)
monthly_quantity = models.IntegerField(default=0)
class Demand(models.Model):
demand_flows = models.ManyToManyField(DemandFlows)
delivery_month = models.DateTimeField(blank=True, null=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
I am trying to create the serializers for this but keep getting confused how to handle the multi-level nesting
Serializer.py
class DemandEventsSerializer(serializers.ModelSerializer):
class Meta:
model = DemandEvents
fields = "__all__"
class DemandFlowsSerializer(serializers.ModelSerializer):
class Meta:
model = DemandFlows
fields = "__all__"
class DemandSerializer(serializers.ModelSerializer):
demand_flows = DemandFlowsSerializer(many=True)
class Meta:
model = Demand
fields = "__all__"
def create(self, validated_data):
items_objects = validated_data.pop('form_list', None)
prdcts = []
for item in items_objects:
i = DemandFlows.objects.create(**item)
prdcts.append(i)
instance = Demand.objects.create(**validated_data)
instance.demand_flows.set(prdcts)
return instance
How do I add events data to this DemandFlows?
I am trying to add Value into InstantInvestment Model in Django REST Framework which is working. but, only want to show the shipping that is specifically for the login user in. which means, the present situation is giving all the shipping not for this user.
models.py
class Shipping(models.Model):
investor = models.ForeignKey(User, related_name='shipping', on_delete=models.CASCADE)
beneficiary = models.CharField("Beneficiary Name", max_length=150)
bank = models.ForeignKey(Bank, related_name="bank", on_delete=models.CASCADE)
account = models.CharField(max_length=10)
address = models.TextField("Shipping Adresss")
created_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.beneficiary
class Meta:
verbose_name = 'Shipping'
verbose_name_plural = 'Shippings'
class InstantInvestment(models.Model):
investor = models.ForeignKey(User, related_name='instantivestment', on_delete=models.CASCADE)
ref_code = models.CharField(max_length=200, blank=True, null=True)
investment = models.FloatField("Investment in dollar")
rate = models.FloatField("Exchange Rate")
transferable = models.FloatField("Money Transferable")
conversion = models.FloatField("Rate in Naira")
product = models.ForeignKey(Product, related_name='instant_product', on_delete=models.CASCADE)
shipping = models.ForeignKey(Shipping, related_name='shipping', on_delete=models.CASCADE)
done = models.BooleanField("Completed Transaction", default=False)
created_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'{self.investor.get_full_name()} - Transaction Code: {self.ref_code}'
class Meta:
verbose_name = 'InstantInvestment'
verbose_name_plural = 'InstantInvestments'
serializers.py
class ShippingSerializer(serializers.ModelSerializer):
class Meta:
model = Shipping
fields = ('beneficiary', 'bank', 'account', 'address')
class QucikPaymentSerializer(serializers.ModelSerializer):
class Meta:
model = InstantInvestment
fields = ('url', 'id','investment', 'rate', 'transferable', 'conversion', 'product', 'shipping')
views.py
class QuickPaymentView(viewsets.ModelViewSet):
queryset = InstantInvestment.objects.all()
serializer_class = QucikPaymentSerializer
permission_classes = [ permissions.IsAuthenticated ]
def get_queryset(self):
return InstantInvestment.objects.filter(investor=self.request.user, done=False)
def perform_create(self, serializer):
serializer.save(investor=self.request.user)
Remove the query set attribute in your viewset class
class QuickPaymentView(viewsets.ModelViewSet):
serializer_class = QucikPaymentSerializer
permission_classes = [ permissions.IsAuthenticated ]
def get_queryset(self):
return InstantInvestment.objects.filter(investor=self.request.user, done=False)
def perform_create(self, serializer):
serializer.save(investor=self.request.user)
to make it work you need to specify the basename key word argument when you register your viewset class with router.
router.register(r'quickpayment/' , QuickPaymentView , basename='InstantInvestment')
If you want do so you need to write a html separately. I think that you showed in your question is rest frameworks ui to test the api. That UI can't determine the User before you send the request.
I wrote the following code:
class PredictionSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Prediction
fields = ["id", "market"]
depth = 1
class FixtureSerializer(serializers.HyperlinkedModelSerializer):
predictions = PredictionSerializer()
class Meta:
model = Fixture
fields = ["sofascore_id", "home", "away", "league", "round", "date", "predictions"]
depth = 1
class FixtureViewSet(viewsets.ReadOnlyModelViewSet):
"""
API endpoint that allows fixture to be viewed or edited.
"""
serializer_class = FixtureSerializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [django_filters.rest_framework.DjangoFilterBackend]
filterset_fields = ("home", "away", "sofascore_id", "statistics")
def get_queryset(self):
date = self.request.query_params.get('date')
queryset = Fixture.objects.all().order_by('-date')
if(date):
queryset = Fixture.objects.filter(date__date=date).order_by('date')
return queryset
Corresponding with the following models:
class Market(models.Model):
name = models.CharField(max_length=200)
class Fixture(models.Model):
sofascore_id = models.CharField(max_length=200)
home = models.ForeignKey(Team, on_delete=models.CASCADE, related_name="home")
away = models.ForeignKey(Team, on_delete=models.CASCADE, related_name="away")
league = models.ForeignKey(League, on_delete=models.CASCADE, blank=True)
round = models.CharField(max_length=200, default=None, blank=True, null=True)
date = models.DateTimeField()
statistics = models.ForeignKey(Statistics, on_delete=models.CASCADE, default=None, blank=True, null=True)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return u'{0} - {1}'.format(self.home.name, self.away.name)
class Prediction(models.Model):
market = models.ForeignKey(Market, on_delete=models.CASCADE, blank=True)
fixture = models.ForeignKey(to=Fixture, on_delete=models.CASCADE, related_name="predictions", null=True, blank=True)
When I make an request to /fixtures, the 'predictions' dictionary is always empty, but when I run some test code with the following statement:
f = Fixture.objects.get(sofascore_id=match).predictions.all()
I get the the following as return value:
<QuerySet [<Prediction: Prediction object (23)>, <Prediction: Prediction object (24)>, <Prediction: Prediction object (25)>, <Prediction: Prediction object (26)>, <Prediction: Prediction object (27)>, <Prediction: Prediction object (28)>]>
What is the issue here and why am I unable to retrieve my predictions using the written code?
You need to specify the attribute many inside your serializer:
class FixtureSerializer(serializers.HyperlinkedModelSerializer):
predictions = PredictionSerializer(many=True, read_only=True)
class Meta:
model = Fixture
fields = ["sofascore_id", "home", "away", "league", "round", "date", "predictions"]
depth = 1