Django Rest Framework - Import CSV(" No file was submitted ") - django-rest-framework

I am trying to upload CSV file in Django Rest Framework using the serializer.
Below have provides the image which contains code for Model, View, and Serializer and the console output when I try to submit the CSV file.
Before validating a serializer when I check with print(serializer.initial_data) there is a file inside the serializer, but as soon as the serializer is validating it says no file was submitted.
models.py
class InventoryFile(models.Model):
shop = models.ForeignKey(Shop,on_delete=models.CASCADE)
shop_inventory = models.FileField(upload_to='inventory/')
serializers.py
class InventoryFile_Serializer(serializers.ModelSerializer):
class Meta:
model = InventoryFile
fields = ('shop_inventory',)
views.py
class InvertoryUpload(APIView):
serializer_class = InventoryFile_Serializer
parser_classes = [ MultiPartParser,FormParser ]
def post(self,request):
try:
serializer = InventoryFile_Serializer(data=request.data)
print(serializer.initial_data)
if serializer.is_valid():
print(serializer.data)
return Response("Done")
else:
print(serializer.errors)
return Response("Not Done")
except Exception as e:
return Response(str(e))
Output
System check identified no issues (0 silenced).
January 30, 2019 - 11:22:06
Django version 2.1, using settings 'hoplet.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
<QueryDict: {'inventory': [<InMemoryUploadedFile: MOCK_DATA_2.csv (application/vnd.ms-excel)>]}>
{'shop_inventory': [ErrorDetail(string='No file was submitted.', code='required')]}
[30/Jan/2019 11:22:18] "POST /uploadinv HTTP/1.1" 200 10

The key name of the file in request is inventory and the key name that the serializer is looking for is shop_inventory. They should be the same. Change one of them and it should work.

Please try in this way
urls.py
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^upload_file', InvertoryUpload.as_view())
]
models.py
class InventoryFile(models.Model):
shop = models.ForeignKey(Shop,on_delete=models.CASCADE)
shop_inventory = models.FileField(upload_to='inventory/')
views.py
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.generics import CreateAPIView
class InvertoryUpload(CreateAPIView):
serializer_class = InventoryFile_Serializer
parser_classes = [ MultiPartParser, FormParser ]
serializers.py
class InventoryFile_Serializer(serializers.ModelSerializer):
class Meta:
model = InventoryFile
fields = ('shop_inventory','shop')

Related

Incorrect view name for nested hyperlinks using drf-nested-routers

I am attempting to use drf-nested-routers to create a simple nested Django REST API given the following models:
# models.py
class Podcast(models.Model):
title = models.CharField(max_length=125)
class Episode(models.Model):
podcast = models.ForeignKey(Podcast, on_delete=models.CASCADE)
title = models.CharField(max_length=125)
Based on the readme domains/nameservers example, I have the following routers defined, expecting a URL structure like:
/podcasts[/{podcast_pk}[/episodes[/{episode_pk}]]]
# urls.py
router = routers.DefaultRouter()
router.register(r'podcasts', PodcastViewSet)
episode_router = routers.NestedDefaultRouter(
router, r'podcasts', lookup='podcast'
)
episode_router.register(
r'episodes', EpisodeViewSet, basename='podcast-episodes'
)
# serializers.py
class PodcastSerializer(HyperlinkedModelSerializer):
episodes = HyperlinkedIdentityField(
view_name='podcast-episodes-list',
lookup_url_kwarg='podcast_pk'
)
class Meta:
model = Podcast
fields = '__all__'
class EpisodeSerializer(NestedHyperlinkedModelSerializer):
parent_lookup_kwargs = {
'podcast_pk': 'podcast__pk',
}
class Meta:
model = Episode
fields = '__all__'
# exclude = ('url',) # works without reference to self
# views.py
class PodcastViewSet(viewsets.ModelViewSet):
queryset = Podcast.objects.all()
serializer_class = PodcastSerializer
class EpisodeViewSet(viewsets.ModelViewSet):
serializer_class = EpisodeSerializer
def get_queryset(self):
return Episode.objects.filter(
podcast=self.kwargs['podcast_pk'],
)
Accessing /podcasts/1/episodes/, when url is included, raises the following error:
Exception Type: ImproperlyConfigured at /podcasts/1/episodes/
Exception Value: Could not resolve URL for hyperlinked
relationship using view name "episode-detail". You may
have failed to include the related model in your API,
or incorrectly configured the `lookup_field` attribute
on this field.
Why does it not identify the correct view name, or is there something else obvious I am missing
In my case using 'id' instead of 'pk' is solved my problem.
parent_lookup_kwargs = {
'podcast_pk': 'podcast_id',
}

Record exists or not in DB? Django Api generic Views

I want to write a class based API view to check if the record exists in DB or not then return True else False by using rest_framework. How could I create CBV to check it? Please help me with this context.
here is my serializer class
class EmployeeSerializer(ModelSerializer):
class Meta:
model = Employee
fields = '__all__'
here is my url
path('employee/<name>/<code>/',views.EmployeeExist.as_view(),name = 'employee_exits')
Here is how you can create simple view:
from rest_framework import status, response
from rest_framework import generics
class EmployeeExistView(generics.GenericAPIView):
serializer_class = None
def get(self, request, *args, **kwargs):
employee = Employee.objects.filter(id=kwargs.get('id'))
if employee.exists():
return response.Response(status=status.HTTP_200_OK)
return response.Response(status=status.HTTP_404_NOT_FOUND)

DRF docs - getting serializers dynamically

I have a viewset which uses different serializers for different HTTP methods (and possibly even for different users). DRF docs says this:
To be compatible with this behaviour methods (such as get_serializer or
get_serializer_class etc.) which inspect self.request or, particularly,
self.request.user may need to be adjusted to handle this case.
Can anyone provide me an example of the "adjustment to handle this case"?
Say I have a viewset which is using serializer A for get method for admins, serializer B for get method for all other users and serializer C for all other methods. How to specify this so that the documentation understands this? I am using the builtin one.
My urls.py:
router = DefaultRouter()
router.register('test', SampleViewset, base_name="test")
urlpatterns = [
path('admin/', admin.site.urls),
path('docs/', include_docs_urls(title='My API title', public=True)),
path('', include(router.urls)),
]
Minimal example
models.py
class SampleModel(models.Model):
name = models.CharField(max_length=120)
age = models.IntegerField()
address = models.CharField(max_length=100)
serializers.py
class SampleSerializer(serializers.ModelSerializer):
class Meta:
fields = '__all__'
model = SampleModel
class SampleSerializerCreate(serializers.ModelSerializer):
age = serializers.IntegerField(max_value=20)
class Meta:
fields = '__all__'
model = SampleModel
views.py
class SampleViewset(ModelViewSet):
serializer_class = SampleSerializer
queryset = SampleModel.objects.all()
def get_serializer_class(self):
if self.action=='create':
return SampleSerializerCreate
return SampleSerializer
Here I used a logic that, while creation of SampleModel, the age attribute should not exceed a max_value of 20.
Update-1
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'sample', SampleViewset)
urlpatterns = [
path('docs/', include_docs_urls(title='My API title', public=True, patterns=router.urls)),
] + router.urls

Sending tags via HTTP Post to Django web api endpoint

I am trying to send tags to my web application, using Django Rest Framework and Django Taggit. I tried to adapt the approach from here, but no luck so far. Here is my try:
models.py:
class Tool(models.Model):
name = models.CharField(max_length=100)
tags = TaggableManager(blank=True)
created = models.DateTimeField(auto_now_add=True)
def get_tags_display(self):
return self.tags.names()
serializers.py:
class ToolSerializer(TaggitSerializer, serializers.ModelSerializer):
name = serializers.CharField(max_length=100)
tags = serializers.Field(source='get_tags_display')
class Meta:
model = Tool
fields = ('tool_id', 'name', 'tags')
views.py:
class ToolList(generics.ListCreateAPIView):
queryset = Tool.objects.all()
serializer_class = ToolSerializer
def perform_create(self, serializer):
if 'tags' in self.request.data:
self.objects.add(*self.request.data['tags'])
return super(ToolList, self).perform_create(self, serializer)
using httpie:
http --form POST http://127.0.0.1:8000/tools/ name="Hammer" tags:='["new", "heavy"]'
Am I going in the right direction?

Django REST Framework: integer fields default value not showing up in browseable API form

Using django 1.6 and rest framework 2.3.13
In model class:
class A(models.Model):
some_name = models.PositiveSmallIntegerField(default=15)
In serilizer:
class ASerializer(ModelSerializer):
class Meta:
model = A
fields = ( 'some_name' )
In view:
class AViewSet(viewsets.ModelViewSet):
queryset = A.objects.all()
serializer_class = ASerializer
But in the api form, it's showing as 0, any idea?
This problem can be solved by adding
if obj is None and self.default is not None:
return self.default
to rest_framework/fields.py
Original pull request:
https://github.com/tomchristie/django-rest-framework/pull/1248/files

Resources