0

I have a model called Properties as shown below. I'm trying to save a given property in my DB with the current logged in user from a form in my dashboard. My user model is a custom user model AUTH_USER_MODEL = 'Landlords.Profile' At first i had no created_by and all was well. But then when i introduced it, made the necessary migrations, when i try to submit data from the form i now get this error.

django.db.utils.IntegrityError: null value in column "created_by_id" of relation "Properties_rentalproperties" violates not-null constraint
DETAIL:  Failing row contains (1, Prime Apartments, Apartment, Kileleshwa, Nairobi, 10, 2021-11-07, 2021-11-07, null).

How to assign my logged in user to a the property created In Django Rest framework? Most solutions on SO are geared towards class-based API views. How can i do this with function-based API views? Is there something i'm missing or doing wrong?

My Model

from django.db import models
from django.conf import settings

class RentalProperties(models.Model):
    property_name = models.CharField(max_length=255)
    property_type = models.CharField(choices=TYPE, max_length=255)
    property_location = models.CharField(max_length=255)
    county = models.CharField(choices=COUNTY, max_length=255)
    number_of_units = models.IntegerField()
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default='')
    date_created = models.DateField(auto_now_add=True)
    last_modified = models.DateField(auto_now=True)

    def __str__(self):
        return self.property_name

    class Meta:
        verbose_name_plural = "Properties"

My serializer

from apps.Properties.models import RentalProperties
from rest_framework import serializers

class PropertiesSerializers(serializers.ModelSerializer):
    class Meta:
        model = RentalProperties
        fields = ('id', 'property_name', 'property_type', 'property_location', 'county', 'number_of_units', 'created_by', 'date_created', 'last_modified')

My API view

@login_required(login_url='Login' )
def AllProperties(request):
    return render(request, 'Dashboard - Properties.html')

@api_view(['POST'])
def AddPropertyAPI(request):
    serializer = PropertiesSerializers(data=request.data)
    if serializer.is_valid(raise_exception=True):
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
        
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
CoderS
  • 143
  • 1
  • 8

1 Answers1

2

I think that the problem is that you are trying to save RentalProperties model with created_by=null. If it is intended then allow created_by to be null by modifying your model:

created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, default=None)

UPDATE:

You should probably update request.data with the user sending this request, try sth like this:

@api_view(['POST'])
def AddPropertyAPI(request):
    request_data = dict(request.data)
    request_data["created_by"] = request.user if request.user.is_authenticated else None
    serializer = PropertiesSerializers(data=request_data)
    if serializer.is_valid(raise_exception=True):
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
        
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Kecz
  • 90
  • 7
  • 1
    i don't want `created_by` to be null. I want it to be associated with the current logged in user. I want to achieve something like this, for example `created_by_id = 1` representing `user ID 1` if he is logged in. `null=True` marks the column of the logged in as `null`. That's not my intention. – CoderS Nov 07 '21 at 20:17
  • Check my UPDATE. – Kecz Nov 07 '21 at 20:38
  • i'm getting this error `POST http://127.0.0.1:8000/api/properties/add/ 400 (Bad Request)` – CoderS Nov 07 '21 at 21:15
  • Can you provide errors returned in this 400? – Kecz Nov 08 '21 at 10:36
  • `Bad Request: /api/properties/add/ [09/Nov/2021 13:49:30] "POST /api/properties/add/ HTTP/1.1" 400 325` that's the error from the django server. `POST http://127.0.0.1:8000/api/properties/add/ 400 (Bad Request)` this is from the console – CoderS Nov 09 '21 at 10:51
  • And what is in 'body' of the request? – Kecz Nov 09 '21 at 19:54
  • could you kindly elaborate what you mean by 'body' of the request? – CoderS Nov 11 '21 at 09:12
  • Check this: https://stackoverflow.com/questions/22034144/what-does-it-mean-http-request-body – Kecz Nov 11 '21 at 12:31
  • i tried using postman to get a better response in the body. I placed the following in the body `{ "property_name": "New Apartments", "property_type": "Apartment", "property_location": "Lavington", "county": "Nairobi", "number_of_units": 10 }` and i got the following reponse `{"created_by":["Incorrect type. Expected pk value, received AnonymousUser."]}` The `created_by` attribute is getting an `AnonymousUser` instead of `1` which is the id of the logged in user. – CoderS Nov 11 '21 at 17:08
  • Ok, nice info. So the 400 error code occurs when the user, who is not logged in, tries to use this endpoint. The question is if you are using any authentication like token authentication? Because it is required to extract info about logged in user. In Postman authorization can be set by adding "Authorization" ket to headers with the proper value. Check what response you get after adding authorization to Postman. I have also updated the UPDATE above so that the endpoint should work for anonymous user but 'created_by' will be set to None (check if you allow 'created_by' to be None in your model) – Kecz Nov 11 '21 at 22:08
  • i'm not using any form of JWT or Token authentication. I'm just logging into my dashboard using a login form which creates a session ID for the user. I think the solution lies in how to enable the API to capture the session ID of the user so that it can identify which user is logged in. Coz as of now, the API seems to think the current logged in user is not logged in and that's why is claiming the user is anonymous. I have tried your `update` and `created_by` is set to null which isn't what i want. Would this help `'rest_framework.authentication.SessionAuthentication'`? – CoderS Nov 12 '21 at 09:58
  • Maybe it will help. You probably have to properly configure authentication for your django-project. Check this documentation: https://docs.djangoproject.com/en/3.2/topics/auth/. Especially check parts about logging user in and extracting his id from the request: https://docs.djangoproject.com/en/3.2/topics/auth/default/#authentication-in-web-requests (and below) – Kecz Nov 12 '21 at 10:54
  • 1
    i have found my solution [here](https://blog.logrocket.com/use-django-rest-framework-to-build-a-blog/). I think i will just have to get used to class-based views & API generic views. It's now working perfectly. – CoderS Nov 12 '21 at 12:11