File uploader is not showing in Swagger Django Rest-Framwork - python

I have created Rest API using Django rest-framework, when I am trying to test in with Swagger, it is not supporting FileField. in place of file uploader, it is showing text field.
Here What I did -
models.py
class Document(models.Model):
IS_DELETED = (
(True, True),
(False, False),
)
project = models.ForeignKey(Project, null=False, blank=False, on_delete=models.CASCADE)
document_file = models.FileField(upload_to=PROJECT_DOC_PATH, null=False, blank=False)
is_deleted = models.BooleanField(choices=IS_DELETED, default=False)
created_by = models.CharField(max_length=500, null=True, blank=True)
created_on = models.DateTimeField(null=False, blank=False, default=timezone.now)
updated_by = models.CharField(max_length=500, null=True, blank=True)
updated_on = models.DateTimeField(null=True, blank=True)
serializers.py
class DocumentSerializer(serializers.ModelSerializer):
class Meta:
model = DocumentTbl
fields = ('project','document_file')
views.py
#method_decorator(csrf_exempt, name='dispatch')
class Document(generics.CreateAPIView):
renderer_classes = (JSONRenderer,)
parser_classes = (FormParser, MultiPartParser,)
permission_classes = (permissions.AllowAny, IsAuthenticated)
serializer_class = DocumentSerializer
def post(self, request):
try:
serializer = DocumentSerializer(data=request.data)
if serializer.is_valid():
serializer.create(serializer.validated_data)
return Response({
messages.RESULT: messages.SUCCESS,
messages.MESSAGE: messages.SUCCESSFULLY_DATA_SAVE,
}, status=status.HTTP_200_OK)
else:
return Response({
messages.RESULT: messages.FAIL,
messages.RESPONSE_DATA: serializer.errors,
messages.MESSAGE: messages.INVALID_DATA,
}, status=status.HTTP_400_BAD_REQUEST)
except Exception as ex:
return Response({
messages.RESULT: messages.FAIL,
messages.MESSAGE: messages.SERVER_ERROR + ', due to {}'.format(str(ex)),
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
urls.py
urlpatterns = [
path('document/', Document.as_view(),name='document'),
]
req.txt
Python==3.x
Django==2.2.5
django-cors-headers==3.1.0
django-rest-swagger==2.2.0
djangorestframework==3.10.3
djangorestframework-simplejwt==4.3.0
I have tried Django REST Framework + Django REST Swagger + ImageField but didn't solve my issue.
Output

This is a known issue at Django-Rest-Swagger
you can refer to below url:
https://github.com/marcgibbons/django-rest-swagger/issues/647
the rootcause is Core api doesn't have a File type yet, it is marked as # LATER: File
see https://github.com/core-api/python-coreschema/blob/master/coreschema/schemas.py#L24

Related

ValueError: Field 'id' expected a number but got string in Django Rest Framework

In DRF I am facing an issue, whenever I do a POST request on the endpoint, on the field "name" which is a text field I get an exception "Field 'id' expected a number but got 'TITLE'", but when I change the value of "name" to an integer the request is successful I don't understand it becauses name is TextField in model and why its mixing Id and Name field with each other. I have deleted the migration files from the Project and DB and re-run the Migrations, but still facing this issue.
Following is my code:
models.py
class Project(models.Model):
admin = models.ForeignKey(User, on_delete=models.CASCADE, related_name='project_crated_by')
name = models.TextField(max_length=225, blank=False, null=False)
project_members = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='members', null=True, blank=True)
created_on = models.DateField(default=timezone.now)
tags = ArrayField(models.CharField(max_length=225, default=''), blank=True)
def __str__(self):
return self.name
objects = models.Manager()
views.py
class ProjectView(viewsets.ViewSet):
def create(self, request):
project_name_exist = Project.verify_project_name(request.data['admin'], request.data['name'])
if project_name_exist:
return Response({'message': 'You already have a project with this name',
'status': status.HTTP_200_OK})
serialized_project = ProjectSerializer(data=request.data)
if serialized_project.is_valid():
serialized_project.save()
return Response({'message': 'Project Created Successfully', 'status': status.HTTP_201_CREATED})
else:
return Response({'error': serialized_project.errors, 'status': status.HTTP_400_BAD_REQUEST})
serializer.py
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = '__all__'
A more generic and non-DIY solution is to use UniqueTogetherValidator on your serializer and let Django sort it out.
from rest_framework.validators import UniqueTogetherValidator
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = '__all__'
validators = [
UniqueTogetherValidator(
queryset=Project.objects.all(),
fields=['admin', 'name'],
message='You already have a project with this name'
)
]
And/or add it to the model for enforcing it on the database.
class Project(models.Model):
admin = models.ForeignKey(User, on_delete=models.CASCADE, related_name='project_crated_by')
name = models.TextField(max_length=225, blank=False, null=False)
project_members = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='members', null=True, blank=True)
created_on = models.DateField(default=timezone.now)
tags = ArrayField(models.CharField(max_length=225, default=''), blank=True)
def __str__(self):
return self.name
objects = models.Manager()
class Meta:
unique_together = ("admin", "name")

How to deserialize nested serializers with Django Rest Framework

i have in models.py
class Variants(Model):
class Meta:
db_table = 'variants'
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255, blank=False, null=False)
client = models.ForeignKey(Client, on_delete=models.CASCADE, null=False, blank=False)
created_at = models.DateField(auto_created=True, default=now, blank=True)
updated_at = models.DateField(auto_now=True, null=True, blank=True)
and
class VariantOptions(Model):
class Meta:
db_table = 'variant_options'
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255, blank=False, null=False)
variant = models.ForeignKey(Variants, on_delete=models.CASCADE, null=False, blank=False)
created_at = models.DateField(auto_created=True, default=now, blank=True)
updated_at = models.DateField(auto_now=True, null=True, blank=True)
and in serializers.py
class VariantOptionsSerializer(serializers.ModelSerializer):
class Meta:
model = models.VariantOptions
fields = ['name']
class VariantsSerializer(serializers.ModelSerializer):
options = VariantOptionsSerializer(many=True)
class Meta:
model = models.Variants
fields = ['name','client','options']
def create(self, validated_data):
options_data = validated_data.pop('options')
variant = models.Variants.objects.create(**validated_data)
for option_data in options_data:
models.VariantOptions.objects.create(variant=variant, **option_data)
return variant
and my view
class VariantsCreate(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = serializers.VariantsSerializer
def post(self, request, format=None):
serializer = serializers.VariantsSerializer(data=request.data)
if serializer.is_valid():
saved = serializer.save()
return Response(serializer.data) ==> serializer.data gives error
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
i have this error
Got AttributeError when attempting to get a value for field options on serializer VariantsSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the Variants instance.
Original exception text was: 'Variants' object has no attribute 'options'.
but the data has already been validated by the call to is_valid()
why return Response(serializer.data) gives error ?
Try to change
variant = models.ForeignKey(Variants, on_delete=models.CASCADE, null=False, blank=False)
with
variant = models.ForeignKey(Variants, related_name='options', on_delete=models.CASCADE, null=False, blank=False)

Django DRF serializer on PrimaryKeyRelatedField

Question about PrimaryKeyRelatedField serialization in Django DRF version 3.4.7.
models
class UserModel(AbstractEmailUser):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.email)
class Conversation(models.Model):
admin = models.ForeignKey('UserModel', db_index=True, related_name='admin_user')
patient = models.ForeignKey('UserModel', db_index=True)
subject = models.CharField(max_length=255, db_index=True)
user_reply = models.BooleanField(default=False)
admin_seen = models.BooleanField(default=False)
expire = models.DateTimeField()
conversation_type = models.ForeignKey('ConversationType', db_index=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.admin)
class ConversationMessages(models.Model):
text = models.TextField(db_index=True)
conversation = models.ForeignKey('Conversation', db_index=True, related_name='msg_conv')
user = models.ForeignKey('UserModel', db_index=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.user)
class ConversationFiles(models.Model):
message = models.ForeignKey('ConversationMessages', db_index=True, related_name='message')
file = models.FileField(upload_to='conversations', db_index=True)
def __str__(self):
return str(self.user)
Every model has related field for Rest Framework.
Logic is create conversation, then take ID from conversation and save message model.
serialize's
class MessagesSerializer(serializers.ModelSerializer):
text = serializers.CharField(required=False)
conversation = serializers.PrimaryKeyRelatedField(queryset=Conversation.objects.all(), required=False)
user = serializers.PrimaryKeyRelatedField(queryset=UserModel.objects.all(), required=False)
class Meta:
model = ConversationMessages
class ConversationSerializer(serializers.ModelSerializer):
admin = serializers.PrimaryKeyRelatedField(queryset=UserModel.objects.all(), required=False)
msg_conv = MessagesSerializer()
class Meta:
model = Conversation
def create(self, validated_data):
msg_conv = validated_data.pop('msg_conv', None)
admin_user = Conversation.objects.create(**validated_data)
ConversationMessages.objects.create(conversation_id=Conversation.objects.get(id=admin_user.id).id, **msg_conv)
return admin_user
Serializer is problem on POST method. Everything works great POST object create data in database, but problem is when serializer save object i get this message: 'RelatedManager' object has no attribute 'conversation'.
View
class ConversationView(APIView):
authentication_classes = (JSONWebTokenAuthentication,)
#parser_classes((FormParser, MultiPartParser, FileUploadParser))
def post(self, request):
admin = request.user.id
data = request.data
my_time = datetime.datetime.strptime('07/05/15', '%m/%d/%y')
my_time = my_time.replace(hour=23, minute=59)
data['admin'] = admin
data['expire'] = my_time
data['msg_conv']['user'] = admin
serializer = ConversationSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(data={'success': True, 'user': serializer.data}, status=status.HTTP_200_OK)
else:
return Response(data={'success': False, 'msg': serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
POST json
{
"subject":"aloha",
"conversation_type":1,
"patient":3,
"msg_conv":{
"text":"ovo je neki teks"
}
}
Can't figure out how to return data from serializer to view.
Django version : 1.10.2
Python: 3.4.3
The issue is there:
class ConversationSerializer(serializers.ModelSerializer):
msg_conv = MessagesSerializer()
By doing this, you are saying that Conversation has a FK to Message. Therefore DRF tries to do the mapping and fails because it's the oposit.
You just need to add the many=True argument to let DRF knows this is a reversed FK.

Django: TokenAuthentication and AbstractBaseUser Errors

I am using Django 1.8.4 and Django rest framework 3.2.3. Because I want override "username" field I had to use "AbstractBaseUser"
The used model is:
class Users(AbstractBaseUser):
username = models.EmailField(max_length=75, null=False, blank=False, unique=True)
first_name = models.CharField(max_length=50, null=True, blank=True)
last_name = models.CharField(max_length=70, null=True, blank=True)
tel_number = models.IntegerField(null=True, blank=True)
address = models.CharField(max_length=250, null=True, blank=True)
user_image = models.ImageField(upload_to='user_avatar', blank=True, null=True)
date_time = models.DateTimeField(auto_now=True, null=True, blank=True)
activated = models.BooleanField(default=False)
def __unicode__(self):
return self.username
class Meta:
ordering = ['-id']
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['tel_number']
Now I want create new user with new token:
if request.method == 'POST':
serializer = UserSerializer(data=request.data)
data = {}
if serializer.is_valid():
user = serializer.save()
token, created = Token.objects.get_or_create(user=user)
data['token'] = token
data = serializer.data
return Response(data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
and my serializer is :
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = ('id', 'username', 'password', 'first_name', 'last_name', 'tel_number', 'address', 'user_image')
But I get this error on "Create Token Lines":
Cannot query "a#gmail.com": Must be "User" instance.
You are not passing the user instance to Token.
Can you try this:
In routers.py
from rest_framework import routers
from .viewsets import UserSeralizerViewSets
router = routers.DefaultRouter()
router.register(r'users', UserSeralizerViewSets)
In urls.py
from .routers import router
urlpatterns = [
url(r'^', include(router.urls)),
]
In viewsets.py
class UserSeralizerViewSets(viewsets.ModelViewSet):
serializer_class = UserSeralizer
queryset = Users.objects.all()
def create(self, request, *args, **kwargs):
data = {}
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
token, created = Token.objects.get_or_create(user=user)
data['token'] = token.key
return Response(data, status=status.HTTP_201_CREATED)
The answer of seenu s is well but i use this line in settings.py and worked .
AUTH_USER_MODEL = 'users.Users'
Users.Users is (myappname.mymodelname)
I find this on Django doc.

methods in django admin

I have two models, Client and PaymentOptions.
class Client(models.Model):
name = models.CharField(max_length=50, null=True, unique=False)
contact = models.CharField(max_length=50, null=True, unique=False)
address = models.CharField(max_length=300, null=True, unique=False)
class ClientPaymentOption(models.Model):
name = models.CharField(max_length=30, null=True, unique=False, choices=CARD_TYPE)
action = models.CharField(max_length=30, null=True, unique=False, choices=CLIENT_PAYMENT_OPTION)
percent = models.FloatField(max_length=10, null=True, unique=False)
fixamount = models.FloatField(max_length=20, null=True, unique=False)
itemcharged = models.CharField(max_length=10, null=True, unique=False)
In my admin.py, I just want to have when I create a new Client, it will also create it's ClientPaymentOption.
I have this in my admin.py:
admin.site.disable_action('delete_selected')
class ClientAdmin(admin.ModelAdmin):
#display list
list_display = ('name','b_type','banner','logo',
'contact','address','account_type',
'status','currency','color','user',
)
#display fields
fields = ('name','b_type','banner','logo','contact',
'address','account_type','status',
'currency','color','user',
)
pass
admin.site.register(Client, ClientAdmin)
I have done this in my views.py,
client = Client.objects.create( .... )
ClientPaymentOption.objects.create( ...., client=client )
but i dont have any idea to do this in django admin.
do anyone have an idea about my situation? thanks in advance ...
You can override standard django-admin change_view and add ClientPaymentOption.objects.create( ...., client=client )
there.
A short example from django docs:
class MyModelAdmin(admin.ModelAdmin):
# A template for a very customized change view:
change_form_template = 'admin/myapp/extras/openstreetmap_change_form.html'
def get_osm_info(self):
# ...
pass
def change_view(self, request, object_id, extra_context=None):
extra_context = extra_context or {}
extra_context['osm_data'] = self.get_osm_info()
return super(MyModelAdmin, self).change_view(request, object_id,
extra_context=extra_context)

Categories

Resources