Django Post request for many to many field ValueError - django-models

I am working on a post request in which the user chooses from a list of tags and makes combinations of tags. The combination of tags should then be posted. Nothing should get changed in the Tag table.
These are the models:
models.py
class Tag(models.Model):
name = models.CharField(max_length=256)
language = models.CharField(max_length=256)
objects = models.Manager()
def __str__(self):
"""Return a human readable representation of the model instance."""
return self.name or ''
#property
def tags(self):
tags = self.tagging.values('tag')
return tags.values('tag_id', 'tag__name', 'tag__language')
class Combination(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True)
gameround = models.ForeignKey(Gameround, on_delete=models.CASCADE, null=True)
resource = models.ForeignKey(Resource, on_delete=models.CASCADE, null=True)
tag_id = models.ManyToManyField(Tag, null=True)
created = models.DateTimeField(editable=False)
score = models.PositiveIntegerField(default=0)
objects = models.Manager()
def __str__(self):
return str(self.tag_id) or ''
This is the serializer for Combination.
serializers.py
class CombinationSerializer(serializers.ModelSerializer):
tag_id = TagWithIdSerializer(many=True, required=False, write_only=False)
resource_id = serializers.PrimaryKeyRelatedField(queryset=Resource.objects.all(),
required=True,
source='resource',
write_only=False)
gameround_id = serializers.PrimaryKeyRelatedField(queryset=Gameround.objects.all(),
required=False,
source='gameround',
write_only=False)
user_id = serializers.PrimaryKeyRelatedField(queryset=CustomUser.objects.all(),
required=False,
source='user',
write_only=False)
class Meta:
model = Combination
depth = 1
fields = ('id', 'user_id', 'gameround_id', 'resource_id', 'tag_id', 'created', 'score')
def create(self, validated_data):
user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
score = 0
tag_data = validated_data.pop('tag_id', None)
combination = Combination(
user=user,
gameround=validated_data.get("gameround"),
resource=validated_data.get("resource"),
created=datetime.now(),
score=score
)
combination.save()
for tag_object in tag_data[0]:
combination.tag_id.add(tag_object)
return combination
def to_representation(self, instance):
rep = super().to_representation(instance)
rep['tag_id'] = TagWithIdSerializer(instance.tag_id.all(), many=True).data
return rep
I have tried posting the following JSON object to the database:
{
"gameround_id": 2015685170,
"resource_id": 327888,
"tag_id": [{"id": 2014077506, "name": "corwn","language": "en"}]
}
I am getting a ValueError: Field 'id' expected a number but got 'name'.
How can I fix this issue?

you need to provide tag id for each tag not all tag data,
Try like this
{
"gameround_id": 2015685170,
"resource_id": 327888,
"tag_id": [2014077506,2014077507]
}

Related

TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use technicians.set() instead

I keep getting this very same type error even though I am using set. Can someone maybe point out what I'm doing wrong in my api endpoint?
views.py
#require_http_methods(["GET", "POST"])
def api_requerimientos(request):
if request.method == "GET":
requerimientos = FormularioCliente.objects.all()
return JsonResponse(
{"requerimientos": requerimientos},
encoder=FormularioClienteEncoder,
)
elif request.method == "POST":
print("POST REQUEST HIT")
try:
content = json.loads(request.body)
except json.JSONDecodeError:
return HttpResponseBadRequest("Invalid JSON in request body")
requerimiento = FormularioCliente(**content) # Create a new FormularioCliente object
if "technicians" in content and isinstance(content["technicians"], list):
try:
technicians_id_list = content["technicians"]
technicians = Technician.objects.filter(employee_number__in=technicians_id_list)
requerimiento.technicians.set(technicians)
requerimiento.save()
print('requerimiento:', requerimiento)
except Technician.DoesNotExist:
pass
requerimiento.save() # Save the object to the database
models.py
class FormularioCliente(models.Model):
empresa = models.CharField(max_length=21, null=True, unique=True)
titulo = models.CharField(max_length=66)
descripcion = models.CharField(max_length=66)
enlace = models.URLField(null=True)
tipo = models.CharField(max_length=17, choices=TIPO_REQUIRIMIENTO, default="tecnologia")
date = models.DateField(null=True, auto_now_add=True)
time = models.TimeField(null=True, auto_now_add=True)
entrega = models.DateField(null=True)
finished = models.CharField(max_length=19, choices=TIPO_FINALIZACION, default="Abierto")
technicians = models.ManyToManyField(Technician, blank=True)
special_hours = models.SmallIntegerField(default=0)
regular_hours = models.PositiveSmallIntegerField(default=1)
total_hours = models.SmallIntegerField(default=1)
importancia = models.PositiveSmallIntegerField(default=1)
file = models.FileField(upload_to='files', blank=True)
updated = models.DateField(auto_now=True)
def __str__(self):
return f'{self.titulo}: {self.descripcion} # {self.date}'
def technicians_as_json(self):
return list(self.technicians.all().values())
class Technician(models.Model):
name = models.TextField()
employee_number = models.SmallIntegerField(unique=True, primary_key=True)
def __str__(self):
return self.name + " - " + str(self.employee_number)
encoders.py
class TechnicianEncoder(ModelEncoder):
model = Technician
properties = ["name", "employee_number"]
class FormularioClienteEncoder(ModelEncoder):
model = FormularioCliente
properties = [
"id",
"empresa",
"titulo",
"descripcion",
# "user",
"enlace",
# "tipo",
# "File",
"tipo",
"date",
"time",
"entrega",
"finished",
"technicians", # <-- Add this
"special_hours",
"regular_hours",
"total_hours",
"importancia",
"updated",
]
encoders = {"technicians": TechnicianEncoder()}
I also tried to loop through technicians queryset and add it to the instance one by one as well via the add() method but that also didn't work.
I even tried this:
techs = list(requerimiento.technicians.filter(employee_number__in=technicians_id_list).all())
requerimiento.technicians.set(techs)
None of it worked

I can't Create Second Video in the Django-Rest-Framework

I'm using the Django and React to create YouTube clone.
And when the user is creating second video, it giving the bad request error:
<QueryDict: {'title': ['Edit Test56'], 'description': ['is It working1643'], 'user': ['3'], 'image': [<TemporaryUploadedFile: slackphot.png (image/png)>], 'video': [<TemporaryUploadedFile: video-for-fatube.mp4 (video/mp4)>]}>
Bad Request: /api/admin/create/
When I tried to make post request in postman, it gave me
views.py Views of the api.
class CreateVideo(APIView):
#permissions_classes = [IsAuthenticated]
parser_classes = [MultiPartParser, FormParser]
def post(self, request, format=None):
print(request.data)
serializer = VideoSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializer.py Video Serailzier.
class VideoSerializer(serializers.ModelSerializer):
user_name = CharField(source="user.user_name", read_only=True)
class Meta:
model = Video
fields = ["id", "title", "image", "video", "description", "date_added", "is_active", "user", "user_name", "likes"]
models.py Model of the Video
class Video(models.Model):
title = models.CharField(max_length=50)
image = models.ImageField(_("Image"), upload_to=upload_to, default="videos/default.jpg")
video = models.FileField(_("Video"), upload_to=upload_to, default="videos/default.mp4")
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="user_channel"
)
description = models.CharField(max_length=255)
likes = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='video_post', null=True, blank=True)
date_added = models.DateTimeField(default=timezone.now)
is_active = models.BooleanField(default=True)
If you want to look at the whole project, here is github: https://github.com/PHILLyaHI/diplom-work
You are using One2One Field, that's why it's causing an error, use foreign key in User column
class Video(models.Model):
title = models.CharField(max_length=50)
image = models.ImageField(_("Image"), upload_to=upload_to, default="videos/default.jpg")
video = models.FileField(_("Video"), upload_to=upload_to, default="videos/default.mp4")
user = models.ForiegnKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="user_channel"
)
description = models.CharField(max_length=255)
likes = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='video_post', null=True, blank=True)
date_added = models.DateTimeField(default=timezone.now)
is_active = models.BooleanField(default=True)

Update Successfully but Data not update in db. Django rest framework

I'm working on my final year project, and I need some help to understand what is actually happening, The problem is that: I hit the Update request through postman which gives the successful message for updating the data. but when I check my Database there is no updated data. I also did the debugging but there was no exception by which I can understand the problem Anyone can please help me?
I'm using
PgAdmin for my database.
Django==4.0.2
djangorestframework==3.13.1
djangorestframework-jwt==1.11.0
djangorestframework-simplejwt==5.0.0
psycopg2==2.9.3**.
My Models:
class Company(Base):
company_name = models.CharField(max_length=255, db_column='Company_Name')
company_email = models.EmailField(unique=True, max_length=255, db_column='company_email')
company_manager_name = models.CharField(max_length=255, db_column='Manager_Name')
company_address = models.CharField(max_length=255, db_column='Company_address')
about_company = models.TextField()
company_website = models.URLField(max_length=200)
is_active = models.BooleanField(default=True, db_column='IsActive', help_text='I will use this for enable/disable '
'a specific record')
class Meta:
db_table: 'Company'
def __str__(self):
return self.company_name
def save(self, *args, **kwargs):
try:
if not self.pk:
self.company_email = self.company_email.replace(" ", "").lower()
super().save()
except Exception:
raise
class Base(models.Model):
"""Following fields are abstract and will be use in All over the project Any time Anywhere"""
create_by = models.BigIntegerField(db_column='CreatedBy', null=True, blank=True, default=0)
create_on = models.DateTimeField(db_column='CreatedOn', auto_now_add=True)
modified_by = models.BigIntegerField(db_column='ModifiedBy', null=True, blank=True, default=0)
modified_on = models.DateTimeField(db_column='ModifiedOn', auto_now=True)
deleted_by = models.BigIntegerField(db_column='DeletedBy', null=True, blank=True, default=0)
deleted_on = models.DateTimeField(db_column='DeletedOn', auto_now=True)
status = models.BigIntegerField(db_column='Status', default=0, help_text='I will use this field for making'
'the status like pending approved and '
'for some other purpose by Default it is '
'Zero which has no meaning', )
class Meta:
abstract: True
serializer.py:
class CompanyUpdateSerializer(serializers.ModelSerializer):
company_name = serializers.CharField(required=True, allow_null=False, allow_blank=False)
company_email = serializers.CharField(required=True, allow_null=False, allow_blank=False)
company_manager_name = serializers.CharField(required=True, allow_null=False, allow_blank=False)
company_address = serializers.CharField(required=True, allow_null=False, allow_blank=False)
about_company = serializers.CharField(required=True, allow_null=False, allow_blank=False)
company_website = serializers.URLField(allow_blank=False, allow_null=False)
class Meta:
model = Company
fields = ['id', 'company_name', 'company_email', 'company_manager_name', 'company_address', 'about_company',
'company_website']
def update(self, instance, validated_data):
try:
instance.company_name = validated_data.get('company_name', instance.company_name)
instance.company_email = validated_data.get('company_email', instance.company_email)
instance.company_manager_name = validated_data.get('company_manager_name', instance.company_manager_name)
instance.company_address = validated_data.get('company_address', instance.company_address)
instance.about_company = validated_data.get('about_company', instance.about_company)
instance.company_website = validated_data.get('company_website', instance.company_website)
instance.save()
return instance
except Exception as e:
raise e
Views.py
def put(self, request, pk=None):
try:
id1 = pk
saved_company = Company.objects.get(pk=id1)
data = request.data
serializer = CompanyUpdateSerializer(instance=saved_company, data=data)
if serializer.is_valid():
serializer.save()
return self.send_response(success=True, code=f'200', status_code=status.HTTP_200_OK,
description='Company is updated')
return self.send_response(code=f'422', status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
description=serializer.errors)
except ObjectDoesNotExist:
return self.send_response(code='422', status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
description="No Company matches the given query.")
except IntegrityError:
return self.send_response(code=f'422', status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
description="Email Already Exist")
except Company.DoesNotExist:
return self.send_response(code=f'422', status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
description="Company Model doesn't exists")
except FieldError:
return self.send_response(code=f'500', description="Cannot resolve keyword given in 'order_by' into field")
except Exception as e:
return self.send_response(code=f'500', description=e)
The problem comes from Company.save() method.
You overrode it as
class Company(Base):
...
def save(self, *args, **kwargs):
try:
if not self.pk:
self.company_email = self.company_email.replace(" ", "").lower()
super().save()
except Exception:
raise
Notice the call of super().save() inside the self.pk is None if statement block.
This will make the actual save method to be called only when the pk is None, meaning that only when a new instance is created, not when an instance is updated.
Moving the super().save() call to be outside the if statement should handle both creating and updating.
class Company(Base):
...
def save(self, *args, **kwargs):
try:
if not self.pk:
self.company_email = self.company_email.replace(" ", "").lower()
super().save(*args, **kwargs)
except Exception:
raise

__str__ returned non-string (type Category). when I add post from admin

After I added user and date_added in the Photo models, when I add post from admin its throws me an error saying: str returned non-string (type Category), when I click on the addpost link in the home template its throw another error: 'tuple' object has no attribute 'name'. how can I solve that ?
the models.py:
from django.db import models
from cloudinary.models import CloudinaryField
from django.contrib.auth.models import User
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=100, null=False, blank=False)
def __str__(self):
return self.name
class Photo(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True,
blank=True)
image = CloudinaryField('image')
description = models.TextField(null=True)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.category
the view.py file:
def home(request):
category = request.GET.get('category')
if category == None:
photos = Photo.objects.all()
else:
photos = Photo.objects.filter(category__name=category)
categories = Category.objects.all()
context = {'categories': categories, 'photos': photos}
return render(request, 'home.html', {'categories': categories, 'photos': photos} )
def viewPhoto(request, pk):
photo = Photo.objects.get(id=pk)
return render(request, 'photo.html', {'phpto': photo})
class PostCreativeView(LoginRequiredMixin, CreateView):
model = Photo, Category
fields = ['description', 'image', 'category', 'name']
template_name = 'post_create.html'
def form_valid(self, form):
form.instance.user = self.request.user
return super (PostCreativeView, self).form_valid(form)
Well it has to do with your category name and model you added into post create view.py and so you
have do something like this:
views.py
class PostCreativeView(LoginRequiredMixin, CreateView):
model = Photo
fields = ['description', 'image', 'category']
template_name = 'post_create.html'
def form_valid(self, form):
form.instance.user = self.request.user
return super (PostCreativeView, self).form_valid(form)
#.......
# Models.py
class Photo(models.Model):
#>>>...
def __str__(self):
return str(self.category)
You should return the str(…) of the category, so:
class Photo(models.Model):
# …
def __str__(self):
return str(self.category)

POST request to update data fields - AngularJS, Django

I have two models:
class Lecture(models.Model):
lecture_no = models.IntegerField(null=True)
title = models.CharField(max_length=128, unique=True, null=True)
youtubeLink = models.CharField(max_length=128, unique=True, null=True)
course = models.ForeignKey(Course, null=True)
keywords = models.TextField(max_length=300, null=True)
#Could add Next Rerun Date & Time
def __str__(self):
return self.title
class Notes(models.Model):
notes = models.TextField(null=True)
lecture = models.ForeignKey(Lecture, null=True, related_name='lecture')
def __str__(self):
return self.notes
These serializers:
class NotesSerializer(serializers.ModelSerializer):
lecture = LectureSerializer(read_only=True, many=True)
class Meta:
model = Notes
fields = ('id', 'notes', 'lecture')
class KeywordSerializer(serializers.ModelSerializer):
lecture = LectureSerializer(read_only=True, many=True)
class Meta:
model = Keyword
fields = ('id', 'notes', 'lecture')
and these views:
class LectureViewSet(viewsets.ModelViewSet):
serializer_class = LectureSerializer
def get_queryset(self):
course_id = self.request.query_params.get('course',False)
if course_id:
lectures = Lecture.objects.filter(course=course_id)
else:
lectures = Lecture.objects.all()
return lectures
class NotesViewSet(viewsets.ModelViewSet):
queryset = Notes.objects.all()
serializer_class = NotesSerializer
and I'm trying to make it so that I can update the "notes" field for a specific lecture. Currently I'm using a POST http request:
saveNotes: function(notes, lecture_id, callback) {
$http({
method: 'POST',
url: apiRoute + 'notes/',
data: {
"notes": notes,
"lecture_id": lecture_id
}
}).success(callback);
}
But this just adds a new row to the database every time. How do you update fields instead?
Thanks

Resources