Problem on calling save() for post in django rest framework - django

Calling save() on a serializer is returning below error:
Original exception was:
Traceback (most recent call last):
File "C:\Users\aditya\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\rest_framework\serializers.py", line 940, in create
instance = ModelClass.objects.create(**validated_data)
File "C:\Users\aditya\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\aditya\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\query.py", line 417, in create
obj.save(force_insert=True, using=self.db)
TypeError: save() got an unexpected keyword argument 'force_insert'
views.py
def post(self,request):
if request.method=='POST':
serializer = invoiceSerializers(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
model.py
class invoice(models.Model):
customer = models.CharField(max_length=256, blank=False)
date = models.DateField(default=now)
invoice_number = models.IntegerField(editable=False,default=1)
total_quantity = models.DecimalField(max_digits=10, decimal_places=2)
total_amount = models.DecimalField(max_digits=10, decimal_places=2)
total_tax = models.DecimalField(max_digits=10, decimal_places=2)
def save(self):
if self._state.adding:
last_invoice=invoice.objects.all().aggregate(largest=models.Max('invoice_number'))['largest']
if last_invoice is not None:
self.invoice_number=last_invoice+1
super(invoice,self).save()
I am not able to understand why this is happening and how to fix this. Any help is appreciated.

The save() method of Model accepts few keyword arguments such as force_insert,using etc. But, you are not accepting those arguments in your override methods.
So change your save() method as
class invoice(models.Model):
.....
.....
.....
# your code
def save(self, *args, **kwargs):
.....
.....
.....
# your code
super(invoice, self).save(*args, **kwargs)

Related

how can i create Db table using ForiegnKey relationship in DRF

Halo i'm working on creating multiple DB table using foreignKey but i'm having some error hoping anyone can help out, below is my code & the error msg
###models.py file
class SchoolVideo(models.Model):
school = models.ForeignKey(
Profile, on_delete=models.CASCADE, related_name='school_video')
intro_video = models.FileField(
upload_to='assets/videos', blank=True, null=True)
###serializer file
class VideoSerializer(serializers.ModelSerializer):
class Meta:
model = SchoolVideo
fields = ('intro_video',)
def create(self, validated_data, *args, **kwargs):
if 'user' in validated_data:
user = validated_data.pop('user')
else:
user = Profile.objects.create(**validated_data)
school_video = SchoolVideo.objects.update_or_create(
user=user, defaults=validated_data
)
return school_video
###API VIEW
class SchoolVideoAPi(generics.CreateAPIView):
serializer_class = VideoSerializer
queryset = SchoolVideo.objects.all()
permission_class = [permissions.IsAuthenticated]
parser_classes = (MultiPartParser, FormParser)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(
data=request.data, instance=request.user.profile.school_video
)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(
serializer.data,
message='Video successfully Uploaded',
status=status.HTTPS_201_CREATED,
headers=headers,
)
def perform_create(self, serializer):
print(self.request.user.profile)
serializer.save(user=self.request.user.profile)
this is the traceback/err message i'm getting
##err traceback
response = handler(request, *args, **kwargs)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/rest_framework/generics.py", line 190, in post
return self.create(request, *args, **kwargs)
File "/home/olaneat/Desktop/files/project/django/schMrk/sch-market/schoolDetail/apiviews.py", line 117, in create
self.perform_create(serializer)
File "/home/olaneat/Desktop/files/project/django/schMrk/sch-market/schoolDetail/apiviews.py", line 128, in perform_create
serializer.save(user=self.request.user.profile)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/rest_framework/serializers.py", line 205, in save
self.instance = self.create(validated_data)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/rest_framework/serializers.py", line 939, in create
instance = ModelClass._default_manager.create(**validated_data)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/django/db/models/query.py", line 445, in create
obj = self.model(**kwargs)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/django/db/models/base.py", line 483, in __init__
_setattr(self, field.name, rel_obj)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 215, in __set__
raise ValueError(
ValueError: Cannot assign "<CustomUser: abc#xyz.com>": "SchoolVideo.school" must be a "Profile" instance.
[][1
can anyone help out
The error is caused by this line:
instance=request.user.profile.school_video
As the error says, you are passing school_video as an instance, but it is failing because it is a RelatedManager. Just filter out which school_video you need to fix this.
For example:
instance=request.user.profile.school_video.first()
or
instance=request.user.profile.school_video.filter(<your filters).first()
Just making sure your queryset returns only one object.
Also next time, please try to avoid adding images for code and errors and just put them as text in the question.

save() prohibited to prevent data loss due to unsaved related object 'log'

I am new to django.. I cannot understand what is this error. Can someone help me solve this issue?
Traceback (most recent call last):
File "C:\Error logger\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Error logger\venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Error logger\errorLogger\log\views.py", line 130, in add_solution
s.save()
File "C:\Error logger\errorLogger\log\models.py", line 41, in save
super().save(*args, **kwargs)
File "C:\Error logger\venv\lib\site-packages\django\db\models\base.py", line 682, in save
self._prepare_related_fields_for_save(operation_name='save')
File "C:\Error logger\venv\lib\site-packages\django\db\models\base.py", line 932, in _prepare_related_fields_for_save
raise ValueError(
Exception Type: ValueError at /add-solution/4/my-name-is-anirudh
Exception Value: save() prohibited to prevent data loss due to unsaved related object 'log'.
Also can someone explain what does the below do? I found that this is needed for slug urls.. But I don't understand what is super().save()
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.solution)
super().save(*args, **kwargs)
Also what is the error that I am getting?
models.py
class Solutions(models.Model):
log = models.ForeignKey(
Log, on_delete=models.CASCADE, blank=True, null=True)
solution = models.TextField(null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=50, null=False, blank=True)
image = models.ImageField(
upload_to='images', blank=True)
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.solution)
super().save(*args, **kwargs)
class Meta:
verbose_name = ("Solution")
verbose_name_plural = ("Solutions")
def __str__(self):
return f" {self.solution} "
views.py
def add_solution(request, id, solution):
log = Log()
if request.method == 'POST':
form = SolutionForm(request.POST, request.FILES)
if form.is_valid():
sol = form.cleaned_data['solution']
image = request.FILES.get('image')
s = Solutions()
s.solution = sol
s.image = image
s.log = log
s.save()
message = messages.add_message(request, 25,
'Solution added successfully')
return HttpResponseRedirect(f'/solution/{id}/{solution}')
else:
form = SolutionForm()
message = ''
try:
solution = Solutions.objects.filter(id=id).first()
print(solution)
except Solutions.DoesNotExist:
solution = ''
context = {
'form': form,
'message': message,
'solution': solution
}
return render(request, 'add_solution.html', context=context)
Thanks
You need to save the log first, so add
s.log.save()
Before
s.save()

Error when serializing foreign key object with django-rest-framework-gis to geojson

I am trying to serialize into geojson a model with a foreign key that has a geometry field. I am using the django-rest-framework-gis. I am using django 2.2
I'm stuck on this and none of the other related answers on Stack Overflow work for me. e.g. I have tried versions of this:
How can I flatten a foreignkey object with django-rest-framework-(gis)
Set serializer geo_field as PointField from another model - Django
The problem is I get this error:
Expected a Response, HttpResponse or HttpStreamingResponse to be returned from the view, but received a <class 'statements.models.Response'>
Models:
from django.contrib.gis.db import models
from django.contrib.gis.geos import Point
class Hexgrid_10km2(models.Model):
lng = models.FloatField()
lat = models.FloatField()
polygon = models.MultiPolygonField(srid=4326)
centroid = models.PointField(default=Point(0,0), srid=4326)
def __str__(self):
return f'lng: { self.lng } lat: {self.lat }'
class Response(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
statement = models.ForeignKey(Statement, on_delete=models.CASCADE)
hexgrid_10km2 = models.ForeignKey(Hexgrid_10km2, on_delete=models.CASCADE, null=True, blank=True)
#property
def polygon(self):
return self.hexgrid_10km2.polygon
Views
class ResponseHeatmapAPIView(APIView): #ReadOnly
def get(self, request, pk):
final = Response.objects.all()
serializer = ResponseHeatmapSerializer(final, many=True)
return Response(serializer.data)
Serializers
class ResponseHeatmapSerializer(GeoFeatureModelSerializer):
""" A class to serialize hex polygons as GeoJSON compatible data """
hexgrid_10km2 = GeometrySerializerMethodField()
def get_hexgrid_10km2(self, obj):
return obj.hexgrid_10km2.polygon
class Meta:
model = Response
geo_field = 'hexgrid_10km2'
id_field = False
fields = ('id',)
Traceback
OrderedDict([('type', 'FeatureCollection'), ('features', [OrderedDict([('id', 2), ('type', 'Feature'), ('geometry', GeoJsonDict([('type', 'MultiPolygon'), ('coordinates', [[[[0.52353663711945, 50.8631481850499], [0.538799411254891, 50.86870974483], [0.554062185390241, 50.8631481850499], [0.554062185390241, 50.852023074998], [0.548895002474644, 50.85013962], [0.540831980000019, 50.85013962], [0.53199000192362, 50.8489417564374], [0.52353663711945, 50.852023074998], [0.52353663711945, 50.8631481850499]]]])])), ('properties', OrderedDict([('response_date', '2020-04-15T21:04:04.599597Z'), ('agree', 1), ('hasLocation', False), ('location', GeoJsonDict([('type', 'Point'), ('coordinates', [0.550660257722784, 50.851541821108924])])), ('latitude', 50.851541821108924), ('longitude', 0.5506602577227836), ('locationAccuracy', 0.0), ('user', 1), ('statement', 1)]))])])])
Internal Server Error: /statements/api/heatmap/1
Traceback (most recent call last):
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\django\views\generic\base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\rest_framework\views.py", line 507, in dispatch
self.response = self.finalize_response(request, response, *args, **kwargs)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\rest_framework\views.py", line 419, in finalize_response
assert isinstance(response, HttpResponseBase), (
AssertionError: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<class 'statements.models.Response'>`
[15/Apr/2020 21:55:04] "GET /statements/api/heatmap/1 HTTP/1.1" 500 89414
Serializer is waiting for data from you. I got the same error when I tried your view with a simple modeling. I think there is something wrong with the definition. can you try the presentation:
def get(self, request):
final = Response.objects.all()
serializer = ResponseHeatmapSerializer(data=final, many=True)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
EDITED:
Please excuse me because of my sleeplessness.
The BIG problem here is the name of the table: Response. You have to change the name; somehow it conflicts with the 'Response' that the RestAPI uses.
Change Response(model.Model)'s name to different name.
python manage.py makemigrations
python manage.py migrate
and the view is ready to run (I changed the model name to 'Strawberry':
class ResponseHeatmapList(APIView):
def get(self, request):
final = Strawberry.objects.all()
serializer = ResponseHeatmapSerializer(final, many=True)
return Response(serializer.data)
class ResponseHeatmapDetail(APIView):
def get_object(self, pk):
try:
return Strawberry.objects.get(pk=pk)
except Strawberry.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
final = self.get_object(pk)
serializer = ResponseHeatmapSerializer(final)
return Response(serializer.data)

'invalid_choice' in field foreing key django

I have a problem with a foreing key field that I initialize with a queryset, the form is displayed but at the time of sending data the error 'in to_python raise ValidationError (self.error_messages [' invalid_choice '], code =' invalid_choice ')' appears' .
I know there is a way to invalidate the 'to_python' method but I still can not get it to work. I would appreciate any help.
My view:
class PlanesCreate(generic.CreateView):
model= Plan_Estudios
template_name= 'ControlEscolar/Administracion/planes/planes_form.html'
form_class= PlanForm
success_url = reverse_lazy('ControlEscolar:planes_filtro')
def get_form_kwargs(self):
kwargs = super(PlanesCreate, self).get_form_kwargs()
kwargs.update({'programa': self.request.session['programa']})
return kwargs
My form:
class PlanForm(forms.ModelForm):
class Meta:
model = Plan_Estudios
fields = "__all__"
widgets = {
'nombreplan': forms.TextInput(attrs={'class':'form-control'}),
'programa': forms.Select(attrs={'class':'form-control'}),
}
def __init__(self, *args, **kwargs):
p=kwargs.pop('programa', None)
super(PlanForm, self).__init__(*args, **kwargs)
query=Programa_Academico.objects.filter(pk=p)
self.fields['programa'].queryset=query #Inicialize field with query
My model:
class Plan_Estudios(models.Model):
nombreplan= models.CharField(max_length=30)
programa= models.ForeignKey(Programa_Academico, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.nombreplan
class Programa_Academico(models.Model):
nombreP= models.CharField(max_length=50)
siglas= models.CharField(max_length=10)
def __str__(self):
return self.siglas
Error:
File "C:\Users\Envs\py1\lib\site-packages\django\forms\forms.py" in is_valid
185. return self.is_bound and not self.errors
File "C:\Users\Envs\py1\lib\site-packages\django\forms\forms.py" in errors
180. self.full_clean()
File "C:\Users\Envs\py1\lib\site-packages\django\forms\forms.py" in full_clean
381. self._clean_fields()
File "C:\Users\Envs\py1\lib\site-packages\django\forms\forms.py" in _clean_fields
399. value = field.clean(value)
File "C:\Users\Envs\py1\lib\site-packages\django\forms\fields.py" in clean
147. value = self.to_python(value)
File "C:\Users\Envs\py1\lib\site-packages\django\forms\models.py" in to_python
1252.
raise ValidationError(self.error_messages['invalid_choice'],
code='invalid_choice')
Exception Type: KeyError at /ControlEscolar/planes/crear
Exception Value: 'invalid_choice'

Django error creating object with many to many field

There are a few questions already mentioning this error but I couldn't find an answer in any of them.
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/rest_framework/serializers.py", line 214, in save
self.instance = self.create(validated_data)
File "/home/joao/Code/projects/courty/courty-django/apps/matching/serializers.py", line 19, in create
return MatchFinder.objects.create(**validated_data)
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/query.py", line 392, in create
obj = self.model(**kwargs)
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/base.py", line 568, in __init__
_setattr(self, prop, kwargs[prop])
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 536, in __set__
manager = self.__get__(instance)
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 513, in __get__
return self.related_manager_cls(instance)
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 830, in __init__
(instance, self.pk_field_names[self.source_field_name]))
ValueError: "<MatchFinder: MatchFinder object>" needs to have a value for field "id" before this many-to-many relationship can be used.
Model
class MatchFinder(models.Model):
player = models.ForeignKey(Player)
start_datetime = models.DateTimeField(null=False)
venues = models.ManyToManyField(Venue, help_text='Pitches preferred by this player', blank=True)
View
class MatchFinderView(views.APIView):
def post(self, request, format=None):
serializer = MatchFinderSerialzer(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)
Serializer
class MatchFinderSerialzer(BaseModelSerializer):
class Meta:
model = MatchFinder
fields = ('start_datetime', 'venues')
def create(self, validated_data):
return MatchFinder.objects.create(**validated_data)
Request
c = Client()
data = {
'start_datetime': now,
}
response = c.post('/matches/findmatch/', data)
Passing a list of 2 Venue objects in the venues on the post request results in the same error.
There are multiple issues,
Firstly, 'player' is a non nullable field - so you need to add it in the fields.
Secondly, For nested relationships you need to explicitly specify how the child relationships should be saved. I have modified the Serializer accordingly,
class MatchFinderSerialzer(BaseModelSerializer):
class Meta:
model = MatchFinder
fields = ('player', 'start_datetime', 'venues')
def create(self, validated_data):
venues_data = validated_data.pop('venues')
match_finder = MatchFinder.objects.create(**validated_data)
for venue_data in venues_data:
Venue.objects.create(match_finder=match_finder, **venue_data)
return match_finder
Also make sure you provide 'player id' in your post request.