I am working on an e-commerce project, and I want to add products from the front end. The files in my product app in Django is as follows
models.py:
from django.db import models
from django.forms import CharField
from PIL import Image
from io import BytesIO
from django.core.files import File
# Create your models here.
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='product', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
slug = models.SlugField()
description = models.TextField(blank=True, null=True)
price = models.DecimalField(decimal_places=6, max_digits=6)
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 create_thumbnail(self, image, size = (300,200)):
img = Image.open(image)
img.convert('RGB')
img.thumbnail(size)
thumb_io = BytesIO()
img.save(thumb_io, 'JPEG')
thumbnail = File(thumb_io, name=image.name)
return thumbnail
def get_image(self):
if self.image:
return f'http://localhost:8000' + self.image.url
else:
return ''
def get_thumbnail(self):
if self.thumbnail:
return f'http://localhost:8000' + self.thumbnail.url
else:
if self.image:
self.thumbnail = self.create_thumbnail(self.image)
self.save()
return f'http://localhost:8000' + self.thumbnail.url
else:
return ''
def get_absolute_url(self):
return f'/{self.slug}/'
views.py:
from sys import excepthook
from unicodedata import category
from django.http import Http404
from django.shortcuts import render
from .serializers import ProductSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Product
from rest_framework import status
# Create your views here.
class LastestProduct(APIView):
def get(self, request, format=None):
products = Product.objects.all()[0:4]
serializer = ProductSerializer(products, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
class Productclass LastestProduct(APIView):
def get(self, request, format=None):
products = Product.objects.all()[0:4]
serializer = ProductSerializer(products, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
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.DoesNotExits:
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, status=status.HTTP_200_OK)(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category__slug = category_slug).get(slug=product_slug)
except Product.DoesNotExits:
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, status=status.HTTP_200_OK)
serializers.py:
from dataclasses import fields
from pyexpat import model
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = [
'id',
'name',
'category',
'get_absolute_url',
'description',
'price',
'get_image',
'get_thumbnail',
]
It works fine when it comes to fetching data (products I created in the Django admin) but how to send a JSON request that also contains the images as well as the text data like name, description etc. Currently, I can create a product by sending a POST request but the cannot send an image to the endpoint
Actually, you don't. If you want to send a file, you'd better send it as a multipart/formdata not json.
In DRF, this requires you change the default parser of your view.
See: https://www.django-rest-framework.org/api-guide/parsers/#multipartparser
But, if you really need to use a json format, I guess you could transform your file into a str representation (in the front - check base64 encoding) then send it in a json and finally transform the str representation into a file in the back. However, I would not advise you to do this as it makes the process more cumbersome
Related
I am making API with Django.
Crawled data is saved well in DB, but I have a problem with making API.
views.py
from django.shortcuts import render
from rest_framework.response import Response
from .models import ReviewData
from .models import BuildingData
from rest_framework.views import APIView
from .serializers import ReviewSerializer
from .serializers import BuildingSerializer
from django.shortcuts import render, get_object_or_404
class BuildingInfoAPI(APIView):
def get(request):
queryset = BuildingData.objects.all()
serializer = BuildingSerializer(queryset, many=True)
return Response(serializer.data)
class ReviewListAPI(APIView):
def get(request):
queryset = ReviewData.objects.all()
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
urls.py
from django.contrib import admin
from django.urls import path
from crawling_data.views import ReviewListAPI
from crawling_data.views import BuildingInfoAPI
urlpatterns = [
path('admin/', admin.site.urls),
path('api/buildingdata/', BuildingInfoAPI.as_view()),
path('api/buildingdata/<slug:slug>/', ReviewListAPI.as_view())
]
serializers.py
from rest_framework import serializers
from .models import ReviewData
from .models import BuildingData
class BuildingSerializer(serializers.ModelSerializer) :
class Meta :
model = BuildingData
fields = '__all__'
class ReviewSerializer(serializers.ModelSerializer) :
class Meta :
model = ReviewData
fields = '__all__'
models.py
from django.db import models
import uuid
# Create your models here.
from django.utils.text import slugify
def generate_unique_slug(klass, field):
origin_slug = slugify(field, allow_unicode=True)
unique_slug = origin_slug
numb = 1
while klass.objects.filter(slug=unique_slug).exists():
unique_slug = '%s-%d' % (origin_slug, numb)
numb += 1
return unique_slug
class BuildingData(models.Model):
building_name = models.CharField(max_length=50, unique=True)
slug = models.SlugField(max_length=50, unique=True, allow_unicode=True, default=uuid.uuid1)
building_loc = models.CharField(max_length=50)
building_call = models.CharField(max_length=20)
building_time = models.CharField(max_length=50)
def save(self, *args, **kwargs):
if self.slug: # edit
if slugify(self.building_name, allow_unicode=True) != self.slug:
self.slug = generate_unique_slug(BuildingData, self.building_name)
else: # create
self.slug = generate_unique_slug(BuildingData, self.building_name)
super(BuildingData, self).save(*args, **kwargs)
'''
def save(self, *args, **kwargs):
self.slug = slugify(self.building_name, allow_unicode=True)
try:
return super().save(*args, **kwargs)
except:
print(f"the repeated slug is: `{self.slug}`")
raise
'''
class ReviewData(models.Model):
#building = models.ForeignKey(BuildingData, related_name='reviews', on_delete=models.CASCADE, null=False, blank=False)
building_name = models.CharField(max_length=50)
review_content = models.TextField()
star_num = models.FloatField()
I think there's no problem with models.
But I can't find which makes get() error.
And I think error from(api/buildingdata/) prevents making slug url(api/buildingdata//) pages. (It says page not found when I enter slug url)
Is there any problem with my code?
add self parameter to your get method like this:def get(self,request) or just use generic views more clear and DRY.
I would like to upload multiple images using the Django model field(ImageField).
I created a model and was able to upload multiple images on the admin side like so https://imgur.com/BzVDPC5
I got the idea here (https://github.com/raszidzie/Multiple-Images-Django-Tutorial) in the Post(admin.py)
admin.py
from django.contrib import admin
from .models import School,SchoolImage
class SchoolImageAdmin(admin.StackedInline):
model = SchoolImage
#admin.register(School)
class SchoolAdmin(admin.ModelAdmin):
list_display=('school_name','school_type',"school_country")
search_fields=('school_name','school_type',"school_country")
list_filter=('school_name','school_type','school_gender')
inlines = [SchoolImageAdmin]
class Meta:
model =School
#admin.register(SchoolImage)
class SchoolImageAdmin(admin.ModelAdmin):
pass
I created the SchoolImage Model to handle multiple images in admin.py
models.py
from django.db import models
from django_countries.fields import CountryField
from partial_date import PartialDateField
class School(models.Model):
school_name = models.CharField(max_length = 30)
school_country = CountryField()
school_city = models.CharField(max_length= 30,default= None)
school_population = models.IntegerField()
school_description = models.TextField(max_length = 300)
year_build = PartialDateField()
total_branches = models.IntegerField()
school_fees = models.IntegerField()
school_images = models.FileField()
def __str__(self):
return self.school_name
class SchoolImage(models.Model):
schoolImages = models.ImageField()
school = models.ForeignKey(School, on_delete=models.CASCADE)
def __str__(self):
return self.school.school_name
not sure how to make it work in the veiws
here is my views code
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from .models import School
from .serializers import *
#api_view(['GET','POST'])
def school_list(request):
if request.method == 'GET':
data = School.objects.all()
serializer = SchoolSerializer(data, context={'request': request},many = True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = SchoolSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response( status=status.HTTP_201_CREATED)
return Response(serializer.errors,status=status.HTTP_404_NOT_FOUND)
How do I make it work in my views??
When attempting to get a value for field Name on serializer AppointmentSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the Response instance.
Original exception text was: 'Response' object has no attribute 'Name'.
Here is my models.py
class Doctor(models.Model):
DoctorName = models.CharField(max_length=25)
def __str__(self):
return self.DoctorName
class Appointment(models.Model):
Name = models.CharField(max_length=25)
Phone = models.CharField(max_length=12)
Email = models.EmailField()
Date = models.DateTimeField(auto_now=False)
Comments = models.TextField(max_length=60)
Doctor= models.ForeignKey(Doctor,on_delete=models.CASCADE)
def __str__(self):
return self.Name
serializer.py
from rest_framework import serializers
from .models import Appointment
class AppointmentSerializer(serializers.ModelSerializer):
class Meta:
model = Appointment
fields = ['Name','Phone','Email','Date','Comments','Doctor']
views.py
class AppointmentDetailView(APIView):
def get_object(self,id):
try:
return Appointment.objects.get(id=id)
except Appointment.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
def get(self, request, id=None):
appointment = self.get_object(id)
serializer = AppointmentSerializer(appointment)
return Response(serializer.data)
def put(self, request, id=None):
appointment = self.get_object(id)
serializer = AppointmentSerializer(appointment, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=200)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, id=None):
appointment = self.get_object(id)
appointment.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
urls.py
urlpatterns = [
path('detail/<int:id>/', AppointmentDetailView.as_view())
]
from rest_framework import serializers
from .models import Appointment
class AppointmentSerializer(serializers.ModelSerializer):
# You need to add your fields exclusively like that:
Name = serializers.CharField() # maybe_some_attributes ex: required, allow_null etc.
Phone = serializers.CharField()
.
.
class Meta:
model = Appointment
fields = ['Name','Phone','Email','Date','Comments','Doctor']
here is my models.py
from __future__ import unicode_literals
from django.db import models
class User(models.Model):
name = models.CharField(max_length=200)
company_name = models.ForeignKey('Company',on_delete=models.CASCADE,related_name='user')
def __str__(self):
return self.name
class Company(models.Model):
name = models.CharField(max_length=200)
phone_number = models.IntegerField(null=True,blank=True)
def __str__(self):
return self.name
class Catalog(models.Model):
name = models.CharField(max_length=200)
no_of_pcs = models.IntegerField(null=True,blank=True)
per_piece_price = models.DecimalField(null=True,blank=True,max_digits=10,decimal_places=2)
company_name = models.ForeignKey(Company,on_delete=models.CASCADE,related_name='catalog')
def __str__(self):
return self.name
Here is my serializers.py
from rest_framework import serializers
from .models import *
from django.db.models import Sum,Count
class CatalogSerializerPost(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(required=False, allow_blank=True, max_length=100)
no_of_pcs = serializers.IntegerField()
per_piece_price = serializers.IntegerField()
def create(self, validated_data):
return Catalog.objects.create(**validated_data)
class CatalogSerializer(serializers.ModelSerializer):
total_pieces = serializers.SerializerMethodField()
total_price = serializers.SerializerMethodField()
class Meta:
model = Catalog
fields = ('name','no_of_pcs','per_piece_price','company_name','total_pieces','total_price')
depth = 1
def get_total_pieces(self, obj):
totalpieces = Catalog.objects.aggregate(total_pieces=Count('no_of_pcs'))
return totalpieces["total_pieces"]
def get_total_price(self, obj):
totalprice = Catalog.objects.aggregate(total_price=Sum('per_piece_price'))
return totalprice["total_price"]
here is my views.py
from __future__ import unicode_literals
from django.http import HttpResponse
from .models import *
import json
from django.http import JsonResponse, HttpResponse
from .serializers import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework import viewsets, generics
from rest_framework.decorators import api_view
#api_view(['GET', 'POST'])
def CatalogView(request):
if request.method == 'GET':
catalogs = Catalog.objects.select_related('company_name')
serializer = CatalogSerializer(catalogs, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = CatalogSerializerPost(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Here is my urls.py
from django.conf.urls import url, include
from django.contrib import admin
from api.views import CatalogView
from api import views
from rest_framework.urlpatterns import format_suffix_patterns
from rest_framework import routers
router = routers.DefaultRouter()
# router.register('catalogs',views.CatalogView,'catalog')
router.register('companies',views.CompanyView)
router.register('users',views.UserView)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include(router.urls)),
url(r'catalog/', CatalogView),
]
Here i am not able to post data THRIUGH JSON DATA..
Please refer the screenshot for the error..
Thanks..
here is the screen shot for error
please check this issue.
Here i am not able to post data THROUGH JSON DATA..
showing id field is required.
there are few problems with your Serializer and View both, and also the data that you are passing, Change your serializer to this
class CatalogSerializerPost(serializers.Serializer):
name = serializers.CharField(required=False, allow_blank=True, max_length=100)
no_of_pcs = serializers.IntegerField()
per_piece_price = serializers.IntegerField()
company_name_id = serializers.IntegerField() # add this field as you have a company field in the Catalog Model. and you are passing company id in the JSON.
def create(self, validated_data):
return Catalog.objects.create(**validated_data)
and pass
"company_name_id" :3 in your json
You need to mark id field as read only:
class CatalogSerializerPost(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
Also it could be more simple to use ModelSerializer.
I'm working on a web app using the Django rest framework tutorial. I'm trying to load JSON data on my project site using the dev server. However, every time I go to the address, it returns a HTTP 500 error with an AttributeError that says: 'module' object has no attribute 'PersonsList'.
I followed the entire tutorial, edited the urls and views py files a bunch of times, yet I keep getting the same error. Any suggestions of how to fix this?
Here's my code.
urls.py
from django.conf.urls import patterns, url
from pros import views
urlpatterns = patterns ('',
url(r'^pros/$', views.PersonsList.as_view(), name='PersonsList')
)
models.py
from django.db import models
# Create a "Persons" class to add new input field datatypes
class Persons(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
class Meta:
ordering = ('created',)
serializers.py
from django.forms import widgets
from rest_framework import serializers
from persons.models import Persons, LANGUAGE_CHOICES, STYLE_CHOICES
class PersonsSerializer(serializers.Serializer):
pk = serializers.IntegerField(read_only=True)
title = serializers.CharField(required=False, allow_blank=True, max_length=100)
code = serializers.CharField(style={'base_template': 'textarea.html'})
linenos = serializers.BooleanField(required=False)
language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')
def create(self, validated_data):
"""
Create and return a new 'Persons' instance, given the validated data.
"""
return Persons.objects.create(**validated_data)
def update(self, instance, validated_data):
"""
Update and return an existing 'Persons' instance, given the validated data.
"""
instance.title = validated_data.get('title', instance.title)
instance.code = validated_data.get('code', instance.code)
instance.linenos = validated_data.get('linenos', instance.linenos)
instance.language = validated_data.get('language', instance.language)
instance.style = validated_data.get('style', instance.style)
instance.save()
return instance
views.py
from pros.models import Persons
from pros.serializers import PersonsSerializer
from django.http import Http404
from django.http import HttpResponse
from rest_framework.views import APIView
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from rest_framework import mixins
from rest_framework import generics
class PersonsList (mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Persons.objects.all()
serializer_class = PersonsSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
class PersonsDetail (mixins.RetrieveModleMixin,
mixins. UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Persons.objects.all()
serializer_class = PersonsSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
#api_view(['GET', 'POST'])
def persons_list(request):
def persons_list(request, format=None):
"""List all persons, or create a new person
"""
if request.method == 'GET':
persons = Persons.objects.all()
serializer = PersonsSerializer(persons, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = PersonsSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
directorystructure.txt