Trying to do a fairly simple project where I can upload multiple images to my server with just a few other fields. I tried to follow this post but wasn't able to get anywhere on it. I know I am going to need to break my models into two with 'PostImage' having a ForeignKey that relates to Post. And I know I will need to modify the serializer in order to allow an array of image files. Any help would be greatly appreciated.
models.py:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length = 100)
content = models.TextField()
image = models.ImageField(upload_to='post_images')
def __str__(self):
return self.title
serializers.py:
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
views.py:
from django.shortcuts import render
# Create your views here.
from .serializers import PostSerializer
from .models import Post
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.response import Response
from rest_framework import status
# Create your views here.
class PostView(APIView):
parser_classes = (MultiPartParser, FormParser)
def get(self, request, *args, **kwargs):
posts = Post.objects.all()
serializer = PostSerializer(posts, many=True)
return Response(serializer.data)
def post(self, request, *args, **kwargs):
posts_serializer = PostSerializer(data=request.data)
if posts_serializer.is_valid():
posts_serializer.save()
return Response(posts_serializer.data, status=status.HTTP_201_CREATED)
else:
print('error', posts_serializer.errors)
return Response(posts_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
You need to have the ForeignKey relation with the Post Model. You can do like this:
models.py
from django.db import models
class Media(models.Model):
detail = models.CharField(max_length=200, default='', null=True, blank=True)
user = models.ForeignKey(to=MyUser, related_name='user_media')
type = models.CharField(max_length=20, choices=Constant.model.MEDIA_TYPE, default='other')
media = models.FileField(max_length=10000, upload_to=upload_media_file, blank=True, null=True)
class Post(models.Model):
title = models.CharField(max_length = 100)
content = models.TextField()
media = models.ForeignKey(Media, related_name='posts')
def __str__(self):
return self.title
serializer.py
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
media = serializers.ListField(write_only=True,
child=serializers.FileField(max_length=10000000,
allow_empty_file=True,
use_url=False)
class Meta:
model = Post
fields = '__all__'
def is_valid(self, raise_exception=False):
if len(data.getlist('media')) > 5:
raise 'some error'
Related
[enter image description here][1]I don't know what is causing this error but i couldn't find any solution for this. i checked everything and everything seems to be fine but i don't know why this error is occuring.
Views.py
from django.contrib.auth import get_user_model
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import CreateView,FormView
from . import forms
# Create your views here.
def signup(request):
if request.method =='POST':
user_create_form = forms.UserCreateForm(data=request.POST)
user_profile_form = forms.UserProfileInfoForm(data=request.POST)
if user_create_form.is_valid() and user_profile_form.is_valid():
user = user_create_form.save()
user.save()
profile = user_profile_form.save(commit=False)
profile.user = user
if 'profile_pic' in request.FILES:
profile.profile_pic = request.FILES['profile_pic']
profile.save()
else:
print(user_create_form.errors,user_profile_form.errors)
else:
user_create_form = forms.UserCreateForm()
user_profile_form = forms.UserProfileInfoForm()
return render(request,'accounts/signup.html',{'user_create_form':user_create_form,
'user_profile_form':user_profile_form})
Models.py
from django.db import models
from django.contrib import auth
# Create your models here.
class User(auth.models.User,auth.models.PermissionsMixin):
def __str__(self):
return "#{}".format(self.username)
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
Contact_number = models.IntegerField(blank=True)
joined_at = models.DateTimeField(auto_now=True)
profile_pic = models.ImageField(upload_to='profiles',blank=True)
def __str__(self):
return self.user.username + ' Profile'
Forms.py
from django.contrib.auth import get_user_model # this gets the model that is in the application
from django import forms
from django.contrib.auth.forms import UserCreationForm
from . import models
class UserCreateForm(UserCreationForm):
class Meta():
fields = ('username','email','password1','password2',)
model = get_user_model()
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.fields['username'].label = 'Display Name' # to set up a custom label for the field
self.fields['email'].label = "Email Address"
class UserProfileInfoForm(forms.ModelForm):
class Meta():
model = models.UserProfileInfo
fields = ('Contact_number','profile_pic')
I am getting this error no matter what i do, i tried referencing other similar questions but couldn't find any solution for this error. pls help me out on this one.
Thanks in Advance !
image of the error
[1]: https://i.stack.imgur.com/HOcmf.png
You can overwrite save() method in your model to return a model instance after saving an object, for example:
class YourModel(models.Model):
name = models.CharField(max_length=20)
def save(self, *args, **kwargs):
super(YourModel, self).save(*args, **kwargs)
return self
your_model_saved_instance = YourModel(name='example').save()
Then you will receive an instance from the user class instead of the form class
user = user.save()
I am new to mobile app development and I am trying to make my first app with react-native and Django rest-framework as the backend. When I try to run the server and access any model through the django-rest-framework I get
"TypeError: 'type' object is not iterable." I have tried to look up a way to solve it but every way I found online did not help.
Here is my code:
models.py
from django.db import models
from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator, MinValueValidator
class Movie(models.Model):
title = models.CharField(max_length=32)
description = models.TextField()
def no_of_ratings(self):
ratings = Rating.objects.filter(movie=self)
return len(ratings)
def avg_rating(self):
sum = 0
ratings = Rating.objects.filter(movie=self)
for rating in ratings:
sum += rating.stars
if len(ratings) > 0:
return sum / len(ratings)
else:
return 0
class Rating(models.Model):
movie = models.ForeignKey(Movie, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
stars = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(5)])
class Meta:
unique_together = (('user', 'movie'))
index_together = (('user', 'movie'))
serializers.py
from rest_framework import serializer
from .models import Movie, Rating
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields =('id', 'title', 'description', 'no_of_ratings', 'avg_rating')
class RatingSerializer(serializers.ModelSerializer):
class Meta:
model = Rating
fields =('id', 'stars', 'user', 'movie')
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields =('id', 'username', 'password')
extra_kwargs = {'password': {'write_only': True, 'required': True}}
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
Token.objects.create(user=user)
return user
views.py
from django.shortcuts import render
from rest_framework import viewsets, status
from .serializers import MovieSerializer, RatingSerializer, UserSerializer
from .models import Movie, Rating
from rest_framework.response import Response
from rest_framework.decorators import action
from django.contrib.auth.models import User
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.permissions import IsAuthenticatedOrReadOnly, BasePermission
# Create your views here.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
class MovieViewSet(viewsets.ModelViewSet):
queryset = Movie.objects.all()
serializer_class = MovieSerializer
authentication_classes = (TokenAuthentication)
permission_classes = (IsAuthenticated)
#action(detail=True, methods=['POST'])
def rate_movie(self, request, pk=None):
if 'stars' in request.data:
movie = Movie.objects.get(id=pk)
stars = request.data['stars']
user = request.user
try:
rating = Rating.objects.get(user=user.id, movie=movie.id)
rating.stars = stars
rating.save()
serializer = RatingSerializer(rating, mamy=False)
Rating.objects.create(user=user, movie=movie, stars=stars)
response = {'message': 'Rating Updated', 'result': serializer.data}
except:
rating = Rating.objects.create(user=user, movie=movie, stars=stars)
serializer = RatingSerializer(rating, mamy=False)
response = {'message': 'Rating created', 'result': serializer.data}
return Response(response, status=status.HTTP_200_OK)
else:
response = {'message': 'you need to provide stars'}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
class RatingViewSet(viewsets.ModelViewSet):
queryset = Rating.objects.all()
serializer_class = RatingSerializer
authentication_classes = (TokenAuthentication)
permission_classes = (AllowAny)
def update(self, request, *args, **kwargs):
response = {'message': 'You cant update rating like that'}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
def create(self, request, *args, **kwargs):
response = {'message': 'You cant create rating like that'}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
How can I fix this error?
authentication_classes and permission_classes must be tuple or list. When you put single class in parantheses, it will not behave with it as tuple but just one, so cannot iterate over it.
Change them as below in all your viewsets (Put an extra comma after them to show python that these parantheses demonstrate tuple):
#...
authentication_classes = (TokenAuthentication,)
permission_classes = (AllowAny,)
#...
I've been stumped by this for a couple of hours now, and have read through a bunch of documentation and different tutorials, but I still do not know what I'm doing wrong.
I'm trying to make a POST request to create a Comment (my model, views, etc. defined below) and make an association with the User that is making the POST request, but I keep getting the error {"user":["This field is required."]}
I thought that adding
def perform_create(self, serializer):
serializer.save(user=self.request.user)
to my viewset would make this easy, but that doesn't appear to be working...
My models.py looks like:
import uuid
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth import get_user_model
from django.db import models
User = get_user_model()
class Comment(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
text = models.TextField(blank=False, null=False)
created = models.DateTimeField(auto_now_add=True)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.CharField(max_length=256)
content_object = GenericForeignKey('content_type', 'object_id')
serializer.py
from rest_framework import serializers
from .models import Comment
from organization.serializers import UserSerializer
from django.contrib.auth import get_user_model
User = get_user_model()
class CommentSerializer(serializers.ModelSerializer):
id = serializers.CharField(read_only=True, required=False)
user = UserSerializer(required=True)
text = serializers.CharField(required=True)
created = serializers.DateTimeField(read_only=True)
object_id = serializers.CharField(required=False)
class Meta:
model = Comment
fields = ('id', 'user', 'text', 'created', 'object_id')
read_only_fields = ('id', 'created')
views.py
from rest_framework import viewsets
from rest_framework import permissions
from .models import Comment
from .serializers import CommentSerializer
class CommentViewSet(viewsets.ModelViewSet):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return self.queryset.filter(object_id=self.kwargs['object_id'])
def perform_create(self, serializer):
serializer.save(user=self.request.user)
urls.py
from django.urls import include, path
from rest_framework import routers
from .views import CommentViewSet
router = routers.DefaultRouter()
router.register(r'(?P<content_type>[\w\-]+)/(?P<object_id>[\w\-]+)', CommentViewSet)
urlpatterns = [
path('', include(router.urls)),
]
Serializer validation works before perform_create, change user field to read only and it works as expected.
class CommentSerializer(serializers.ModelSerializer):
id = serializers.CharField(read_only=True, required=False)
user = UserSerializer(read_only=True)
text = serializers.CharField(required=True)
created = serializers.DateTimeField(read_only=True)
object_id = serializers.CharField(required=False)
class Meta:
model = Comment
fields = ('id', 'user', 'text', 'created', 'object_id')
read_only_fields = ('id', 'created')
Ok - I got this working by overriding the create method of CommentViewSet and simplifying my CommentSerializer
serializer.py
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ('id', 'user', 'text', 'created', 'edited', 'object_id', 'content_type')
read_only_fields = ('id', 'created')
views.py
from rest_framework import viewsets
from rest_framework import permissions
from rest_framework import status
from rest_framework.response import Response
from django.contrib.contenttypes.models import ContentType
from .models import Comment
from .serializers import CommentSerializer
class CommentViewSet(viewsets.ModelViewSet):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return self.queryset.filter(object_id=self.kwargs['object_id'])
def create(self, request, **kwargs):
"""
Overrides the standard create method so that we can set User,
object_id and content_type based on requesting user and kwargs
passed in URL
"""
comment_data = self.request.data
# change request data so that it's mutable, otherwise this will raise
# a "This QueryDict instance is immutable." error
comment_data._mutable = True
# set the requesting user ID for the User ForeignKey
comment_data['user'] = self.request.user.id
comment_data['object_id'] = self.kwargs['object_id']
# pass kwarg from URL to `model` to get the corresponding object
content_type = ContentType.objects.get( model=self.kwargs['content_type'] )
# pass the ID from the ContentType object to `content_type`, expected
# by serializer
comment_data['content_type'] = content_type.id
serializer = CommentSerializer(data=comment_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)
I'm developing a backend with the django rest api. I have the same problem with my advertise model except for my user model. My choice linked to positiveintegerfielder is not displayed in restframework for post method.I'm doing an action like in serializer.py, whose photo I shared to display. When I do this, it is not displayed in restframework and I cannot use the post method.
Thank you very much in advance
serializer.py##
from user.models import User
from rest_auth.serializers import *
class ChoicesSerializerField(serializers.SerializerMethodField):
def __init__(self, choices, **kwargs):
self._choices = choices
super(ChoicesSerializerField, self).__init__(**kwargs)
def to_representation(self, value):
# sample: 'get_XXXX_display'
method_name = 'get_{field_name}_display'.format(field_name=self.field_name)
# retrieve instance method
method = getattr(value, method_name)
# finally use instance method to return result of get_XXXX_display()
return method()
def to_internal_value(self, data):
return getattr(self._choices, data)
class UserSerializer(serializers.ModelSerializer):
gender = ChoicesSerializerField(choices=User.gender)
class Meta:
model = User
fields = ('gender',)
view.py##
from rest_framework.viewsets import ModelViewSet
from user.serializer import UserSerializer
from .models import *
from rest_framework import permissions
from rest_framework.generics import CreateAPIView, ListAPIView, GenericAPIView, get_object_or_404
class CreateUserView(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
User model##
from django.contrib.auth.models import AbstractUser
from django.core.validators import RegexValidator
from django.db import models
from user.choices.choice import MartialStatusChoices,
EducationalStatusChoices, ProfessionChoices, GenderChoices
class Interest(models.Model):
name = models.CharField(max_length=50, null=True, blank=True )
def __str__(self):
return self.name
class User(AbstractUser):
birthday = models.DateField(null=True)
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$')
phone_number = models.CharField(validators=[phone_regex],
max_length=17, blank=True)
gender =
models.PositiveIntegerField(null=True,choices=GenderChoices.CHOICES)
martial_status = models.PositiveIntegerField(null=True,
choices=MartialStatusChoices.CHOICES)
educational_status = models.PositiveIntegerField(null=True,
choices=EducationalStatusChoices.CHOICES)
profession = models.PositiveIntegerField(null=True,
choices=ProfessionChoices.CHOICES)
interests = models.ManyToManyField(to=Interest,null=True,
blank=True)
class Meta:
verbose_name= "User"
You should try serializers.ChoiceField.
from user.choices.choice import GenderChoices
class UserSerializer(serializers.ModelSerializer):
gender = serializers.ChoiceField(choices=GenderChoices.CHOICES)
class Meta:
model = User
fields = ('gender',)
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
class UserView(APIView):
permission_classes = (permissions.AllowAny,) # remove this if you're using authentication
def get(self, request):
serializer = UserSerializer(instance=request.user)
serializer.is_valid(raise_exception=True)
return Response(serializer.data)
def post(self, request):
serializer = UserSerializer(instance=request.user, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response()
Literaly like title say...check the picture. When i try to make new Post it says i made it but it wont show up on admin page nor in detail.html.
http://prntscr.com/n0pfrv
here is my code for post model
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField(help_text="A short label, generally used in URLs.",default='', max_length=100)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
ordering = ['-date_posted']
def save(self):
slug = self.title
def get_absolute_url(self):
return reverse('detail', kwargs={'slug':self.slug})
def __str__(self):
return self.title
admin.py
from django.contrib import admin
from .models import Post
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'slug', 'date_posted', 'author']
list_filter = ['title', 'date_posted']
prepopulated_fields = { 'slug': ('title',)}
admin.site.register(Post, PostAdmin)
views.py in app called blog were i have model Post also
from django.contrib import messages
from . models import Post
from django.core.mail import send_mail
from django.views.generic import DeleteView, ListView
def index_view(request):
return render(request, 'blog/index_view.html')
def blog_view(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/blog_view.html', context)
class PostDetailView(DeleteView):
model = Post
template_name = 'blog/detail.html'
context_object_name = 'post'
If you need any other of my code im gonna post it
You don't actually save the data in your save(self) method:
def save(self):
slug = self.title
super(Post, self).save(*args, **kwargs)
You should call the real save method as mentioned in the docs:
Overriding predefined model methods