How to retrieve multiple slugs as url parameters with Django REST Framework DRF RetrieveAPIView? - django-rest-framework

I am new to DRF. I am very interested in application of generic views. I want to rewrite the following code with generic DRF view RetrieveAPIView:
views.py
class ProductDetail(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category__slug=category_slug).get(slug=product_slug)
except Product.DoesNotExist:
raise Http404
def get(self, request, category_slug, product_slug, format=None):
product = self.get_object(category_slug, product_slug)
serializer = ProductSerializer(product)
return Response(serializer.data)
urls.py
urlpatterns = [
path('products/<slug:category_slug>/<slug:product_slug>/',
ProductDetail.as_view())
]
models.py
class Category(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField()
class Meta:
ordering = ('name',)
def __str__(self):
return self.name
def get_absolute_url(self):
return f'/{self.slug}/'
class Product(models.Model):
category = models.ForeignKey(
Category, related_name='products', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
slug = models.SlugField()
description = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
image = models.ImageField(upload_to='uploads/', blank=True, null=True)
thumbnail = models.ImageField(upload_to='uploads/', blank=True, null=True)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-date_added',)
def __str__(self):
return self.name
def get_absolute_url(self):
return f'{self.category.slug}/{self.slug}/'
How can I use RetrieveAPIView instead of above APIView?
I tried to add a custom mixin, did not help:
class MultipleFieldLookupMixin:
def get_object(self):
queryset = self.get_queryset() # Get the base queryset
queryset = self.filter_queryset(queryset) # Apply any filter backends
multi_filter = {field: self.kwargs[field] for field in self.lookup_fields}
obj = get_object_or_404(queryset, **multi_filter) # Lookup the object
self.check_object_permissions(self.request, obj)
return obj
class ProductDetail(MultipleFieldLookupMixin, RetrieveAPIView):
queryset = Product.objects.filter(category__slug=category_slug).get(slug=product_slug)
serializer = ProductSerializer
lookup_fields = ['category_slug', 'product_slug']
Does not work.

Related

Searching is not working in django rest_framework

Searching is not working in the django rest framework. searching for the approved status of leave applied by a particular employee. But the filtering/ searching/ sorting is properly working in the admin user. but not in the employee side.
Views.py
class LeaveList(APIView):
authentication_classes = [SessionAuthentication, BasicAuthentication, TokenAuthentication]
permission_classes = [IsAuthenticated]
filter_backends = [DjangoFilterBackend,SearchFilter,OrderingFilter]
ordering_fields = ['apply_date','number_of_days','status']
search_fields = ['status']
filter_fields = ['status']
def get(self, request, format=None):
employee = request.user
filter_backends = [DjangoFilterBackend,SearchFilter,OrderingFilter]
search_fields = ['status']
queryset = LeaveApplicationModel.objects.filter(employee_id=employee.id)
serializer_class = LeaveApplicationsListSerializer(queryset, many=True)
return Response(data=serializer_class.data)
Serializers.py
class LeaveApplicationsListSerializer(serializers.ModelSerializer):
class Meta:
model = LeaveApplicationModel
exclude = ['id', 'employee']
postman request
postman request
expecting
You're not using the search_filters anywhere. GenericAPIView or any class that subclasses it, e.g. ListAPIView, will use it automatically. It's in the docs.
If I were you, I'd rather subclass ListAPIView and set the relevant available attributes correctly. You can overwrite get_queryset to filter for the employee:
class LeaveList(ListAPIView):
authentication_classes = [SessionAuthentication, BasicAuthentication, TokenAuthentication]
permission_classes = [IsAuthenticated]
filter_backends = [DjangoFilterBackend,SearchFilter,OrderingFilter]
ordering_fields = ['apply_date','number_of_days','status']
search_fields = ['status']
filter_fields = ['status']
serializer_class = LeaveApplicationsListSerializer
def get_queryset(self):
employee = self.request.user
return LeaveApplicationModel.objects.filter(employee_id=employee.id)

Django Form Form to fill multiple models at once

I have a few models that are all coming together in the Thema model. But I need a form to fill them all at once from the thema form. My problem is that when I create a form from the model it just creates a selection of for example tags that already exist in the database. But I need to create new ones in the form as well at the same time.
I want the user to fill in stuff in the Thema, upload a file to the file Model, create or select tags in the tags model and select or create into the Categories model.
The Problem is how can I bring all of them together in one Form? Also the Thema Model uses a related field to the Bilder model but I can´t upload new pics in the Thema form which are then stored in the Bilder Model.
This is the model.py
from django.db import models
from django.urls import reverse
from datetime import datetime
class Category(models.Model):
name = models.CharField(max_length=250, help_text='Kategorie', blank=True)
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.name
class Link(models.Model):
alias = models.CharField(max_length=250, help_text='Linkalias', blank=True)
link = models.URLField(("Links zum Thema"), max_length=128, db_index=True, unique=True, blank=True)
def __str__(self):
return self.alias
class File(models.Model):
name = models.CharField(max_length=250, help_text='Dateiname', blank=True)
upload = models.FileField(upload_to ='uploads/', null=True, blank=False)
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(max_length=250, help_text='tagname', blank=True)
def __str__(self):
return self.name
class Thema(models.Model):
publication_date = models.DateField(verbose_name="Date the Post was published.", default=datetime.now)
title = models.CharField(max_length=70, help_text="The title of the Post")
text = models.TextField(max_length=5000,default='text 1')
text2 = models.TextField(max_length=5000,default='text 2')
text3 = models.TextField(max_length=5000,default='text 3')
# Relation Fields
category = models.ForeignKey(Category, on_delete=models.CASCADE)
links = models.ManyToManyField(Link)
files = models.ManyToManyField(File)
tags = models.ManyToManyField(Tag)
def get_absolute_url(self):
return reverse('thema-detail', kwargs={'pk' : self.pk})
def __str__(self):
return self.title
class Bilder(models.Model):
name = models.CharField(max_length=250, help_text='Bildname', blank=True)
beschreibung = models.CharField(max_length=400, help_text='Kurzbschreibung', blank=True)
thema = models.ForeignKey(Thema, on_delete=models.CASCADE, related_name='bilder', null=True)
image = models.ImageField(null=True, blank=True, upload_to='images/')
class Meta:
verbose_name_plural = "Bilder"
def __str__(self):
return self.name
and this is my attempt to create the form:
from django import forms
from django.forms import formset_factory
from .models import Thema, Bilder, Category, Link, File, Tag
from django.forms import formset_factory
class BilderForm(forms.ModelForm):
class Meta:
model = Bilder
fields = ['name', 'beschreibung', 'image']
BilderFormSet = formset_factory(BilderForm, extra=1)
class ThemaForm(forms.ModelForm):
bilder_formset = BilderFormSet()
class Meta:
model = Thema
fields = ['publication_date', 'title', 'text', 'text2', 'text3', 'category', 'links', 'files', 'tags']
def __init__(self, *args, **kwargs):
self.bilder_formset = kwargs.pop('bilder_formset', None)
super().__init__(*args, **kwargs)

Filter in Django Rest Framework

I'm new in DRF: ¿Can I create a filter in a function in Django Rest Framework, not created it in a Class, for use in a view? I'm trying a filter for search by: document and document_type.
Ty
My code:
#model
class Account(models.Model):
'''Modelo para la gestión de cuentas'''
document_type = models.CharField('Tipo documento', null=True, max_length=20, choices=DOCUMENT_TYPE)
document = models.CharField('Documento',null=True, max_length=18)
first_name = models.CharField('Nombres / razón social',null=True, max_length=100)
last_name = models.CharField('Apellidos', null=True, max_length=100)
phone = models.CharField('Teléfono fijo', max_length=7, null=True, blank=True)
cellphone = models.CharField('Celular', max_length=10, null=True, blank=True)
email = models.EmailField('Correo', max_length=100, null=True, blank=True )
address = models.CharField('Dirección', max_length=70, null=True, blank=True)
gender = models.CharField('Genero',null=True, max_length=1, choices=GENDER_TYPE)
affiliate_type = models.CharField('Tipo de afiliado',null=True, max_length=12, choices=AFFILIATE_TYPE)```
#view
```class AccountList(APIView):
"""
List all accounts, or create a new account....
"""
def get(self, request, format=None):
account = Account.objects.all()
serializer = AccountSerializer(account, many=True)
filter_class = AccountFilter
filter_backends = [filters.SearchFilter]
return Response({'data':serializer.data},status=status.HTTP_200_OK)
def post(self, request, format=None):
serializer = AccountSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({'Message':'Registro creado exitosamente'}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)```
#filter
class AccountFilter(django_filters.rest_framework.FilterSet):
class Meta:
model = Account
fields = {
'document': ['exact'],
'document_type': ['exact']
}
ordering_fields = ('document')
You can use self.filter_queryset(queryset) to filter queryset using filter class.
class AccountList(APIView):
def get(self, request, format=None):
self.filter_class = AccountFilter
self.filter_backends = [filters.SearchFilter]
account_qs = Account.objects.all()
account = self.filter_queryset(account_qs)
serializer = AccountSerializer(account, many=True)
return Response({'data':serializer.data},status=status.HTTP_200_OK)

Why my delete method is not working properly?

I have troubles with my code in deleting a specific loan_id(primary key). My post method works good but my delete method doesn´t. Here's my code:
views.py:
class SolicitudPrestamoViewSet(viewsets.mixins.CreateModelMixin,viewsets.mixins.DestroyModelMixin,viewsets.GenericViewSet):
permission_classes = [IsAdminUser]
serializer_class = SucursalSerializer
queryset = Prestamo.objects.all()
lookup_field = 'loan_id'
def get(self, request, format=None,):
serializer = SucursalSerializer()
return Response(serializer.data)
def delete(self, request, loan_id, format=None):
object = self.get_object(loan_id)
object.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
models.py:
class Prestamo(models.Model):
loan_id = models.AutoField(primary_key=True)
loan_type = models.CharField(max_length=20,
choices = [('PERSONAL', 'PERSONAL'), ('HIPOTECARIO', 'HIPOTECARIO'), ('PRENDARIO', 'PRENDARIO')])
loan_date = models.DateField()
loan_total = models.IntegerField()
customer_id = models.IntegerField()
class Meta:
db_table = 'prestamo'
In viewset you should use destroy method to handle DELETE requests:
class SolicitudPrestamoViewSet(viewsets.mixins.CreateModelMixin,viewsets.mixins.DestroyModelMixin,viewsets.GenericViewSet):
permission_classes = [IsAdminUser]
serializer_class = SucursalSerializer
queryset = Prestamo.objects.all()
lookup_field = 'loan_id'
def destroy(self, request, loan_id):
object = self.get_object(loan_id)
object.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

I am trying to save picture to PictureAPIView

MODELS.py
class MyPicture(models.Model):
picture = models.ImageField(upload_to=join_path('pictures'))
SERIALIZERS.PY
class MyPictureSerializer(serializers.ModelSerializer):
picture = serializers.ImageField(required=True, use_url=True)
class Meta:
model = MyPicture
fields = ['id', 'picture']
VIEWS.PY
class MyPictureAPI(APIView):
parser_classes = (FormParser, FileUploadParser)
def post(self, request):
print(request.FILES)
serializer = MyPictureSerializer(data=request.FILES)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
if I print(request.FILES) ,
it is {'file': <InMemoryUploadedFile: cloud_vazifa_01.png (multipart/form-data; boundary=--------------------------563292059865884360215980)>}
here key is 'file' but i have saved it to model and serializer as 'picture'
so serilizer is invalid
help me to save picture to models
enter image description here
I think you need to use the FileField, not ImageField.
class MyPictureSerializer(serializers.ModelSerializer):
picture = serializers.FileField(
max_length = 10000000,
allow_empty_file = False
use_url = False,
)
class Meta:
model = MyPicture
fields = ['id', 'picture']
def create(self, validated_data):
image = validated_data.pop('picture')
return MyPicture.objects.create(picture = image)
In MyPictureAPI,
class MyPictureAPI(APIView):
def post(self, request):
serializer = MyPictureSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)

Resources