NOT NULL constraint failed for ForeignKey(null=True) - python

I have two models, namely Applicant and LoanRequest. Whenever an Applicant instance is created, a signal is sent to a function that makes an API call. The data from the call, along with the primary key of the instance that sent the signal, is saved to as a LoanRequest.
When I save the LoanRequest, however, it gives the following error:
django.db.utils.IntegrityError: NOT NULL constraint failed: queues_loanrequest.dealer_id_id
Here's my code:
class Applicant(models.Model):
app_id = models.CharField(max_length=100)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
date_posted = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.first_name + " " + self.last_name
class LoanRequest(models.Model):
loan_request_id = models.CharField(max_length=100)
app_id = models.ForeignKey(Applicant, on_delete=models.CASCADE)
FICO_score = models.CharField(max_length=100)
income_risk_score = models.CharField(max_length=100)
DTI = models.CharField(max_length=100)
date_requested = models.DateTimeField(default=timezone.now)
loan_request_status = models.CharField(max_length=100,blank=True)
dealer_id = models.ForeignKey(Dealer, on_delete=models.CASCADE,blank=True)
def credit_check(sender, instance, **kwargs):
credit_json = get_credit(instance.pk) #credit information for applicant
credit_json = json.loads(credit_json)
new_request = LoanRequest.objects.create(app_id=instance, FICO_score=credit_json["ficco-score"],
income_risk_score=credit_json["income-risk-score"],
DTI=credit_json["DTI"])
Very new to Django, would greatly appreciate help!

LoanRequest has a field
dealer_id = models.ForeignKey(Dealer, on_delete=models.CASCADE,blank=True)
Because dealer_id doesn't have null=True, creating a LoanRequest instance without supplying a dealer_id will raise the database error you've got.
You need to either supply a dealer_id in the instantiation of the LoanRequest, which should be a Dealer instance, or else change your LoanRequest model so that the dealer_id field has null=True.
Please see comment above re: using the suffix _id on a Django model foreign key - it's nearly always incorrect to do so.

Specifying blank=True without null=True is not very useful for a ForeignKey.
Use this instead:
dealer_id = models.ForeignKey(Dealer, on_delete=models.CASCADE, blank=True, null=True)
This would make the field optional. Otherwise, you would have to specify the Dealer every time you create a LoanRequest.

Related

'NoneType' object has no attribute 'customer_id'

I have two models in an app called customer. The models are Customer and Account. The logic is one customer can have many accounts. So the auto generated default 'id' column in Customer is Foreign Key in Account. Account also has an auto generated default 'id' column. I have created a function for an account_id field in Account which will be generated on a simple algorithm. customer_id and id from Account will be concatenated as 'customer_id'_'id', (for eg. 1_1). The function will first check the current customer_id of the Account instance created and then check which is the last id for that customer_id. For newly added account, it will capture the id part from account_id (i.e. the part after underscore) and increment it by 1. Then concatenation happens for the same customer_id and id. Following is the code-:
models.py
from asyncio.windows_events import NULL
from django.db import models
from django.db.models.signals import pre_save
from django.contrib.auth.models import AbstractBaseUser
from .utils import set_account_id
class Customer(AbstractBaseUser):
name = models.CharField(max_length=50)
phone = models.BigIntegerField(null=True)
email = models.EmailField(max_length=100, null=True)
org_name = models.CharField(max_length=100, null = True)
org_logo = models.ImageField(upload_to='logos', blank=True)
subscription_start_date = models.DateField()
subscription_end_date = models.DateField()
password = models.CharField(max_length=50, blank=True, null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'email']
def __str__(self):
return self.name
class Account(AbstractBaseUser):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
account_id = models.CharField(max_length=100, default=None, blank=True, null=True)
name = models.CharField(max_length=50)
phone = models.BigIntegerField(null=True)
email = models.EmailField(max_length=100, null=True)
password = models.CharField(max_length=50, blank=True, null=True)
account_type = models.CharField(max_length=50, choices=[
("survey", "SURVEY"),
("sme", "SME"),
("residents", "RESIDENTS")
])
account_subscription_date = models.DateField(null=True)
account_expiry_date = models.DateField(null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'email']
def __str__(self):
return self.name
def pre_save_set_account_id(sender, instance, *args, **kwargs):
if not instance.account_id:
instance.account_id = set_account_id(instance) #Error here
print(instance.account_id)
pre_save.connect(pre_save_set_account_id, sender=Account)
utils.py
def set_account_id(instance):
Klass = instance.__class__
fk = 'customer_id'
obj = Klass.objects.first()
field_object = Klass._meta.get_field(fk)
fk_value = field_object.value_from_object(obj) #Error here
last_account = Klass.objects.filter(customer_id=fk_value).all().order_by('id').last()
accounts_pk = last_account.id
new_account_int = accounts_pk + 1
new_account_id = fk_value + '_' + new_account_int
return new_account_id
Now when I have entered one record in customer and trying to enter a record in account through the admin panel. When I am filling out the form for account in admin panel, I am leaving the account_id as blank. After clicking on Save, I am getting the following error-:
AttributeError at /admin/customer/account/add/
'NoneType' object has no attribute 'customer_id'
I have commented "Error here" on the specific lines at which the the error was pointed out by Django debugger. I am new to Django and have tried a lot but couldn't resolve the error. Please help.
Hey i don't know why you need this account_id as db field in first place? If you need it to perform filter, I suggest to use post_save signal like:
def post_save_set_account_id(sender, instance, *args, **kwargs):
if instance.account_id is None:
instance.account_id = f'{instance.customer.id}_{instance.id}'
instance.save()
But if you don't need to build sql query based on account_id field i suggest use #property in Account model:
#property
def account_id(self):
return f'{self.id}_{self.account.id}'
then you cen use it as model field for example:
account = Account.objects.get(pk=1)
account.account_id
prints for example:
1_1

How can I set foreign key from post request in Django

I have this models
class Driver(models.Model):
first_name = models.CharField(max_length=250)
last_name = models.CharField(max_length=250)
created_at = models.DateTimeField(default=NOW)
updated_at = models.DateTimeField(default=NOW)
def __str__(self):
return self.first_name
class Vehicle(models.Model):
driver_id = models.ForeignKey(Driver,on_delete=SET_NULL,unique=True,null=True, blank=True)
make = models.CharField(max_length=150)
model = models.CharField(max_length=150)
plate_number = models.CharField(max_length=10,validators = [validate_plate_numberLATIN,validate_plate_numberCYRYLLIC], unique=True)
created_at = models.DateTimeField(default=NOW)
updated_at = models.DateTimeField(default=NOW)
def __str__(self):
return self.make
I try to set foreign key in my post request into Vehicle model
#method_decorator(csrf_exempt, name='dispatch')
def post(self,request,*args, **kwargs):
body = json.loads(request.body.decode("utf-8"))
newCar = Vehicle.objects.create(driver_id=body['driver_id'],make=body['make'],model=body['model'],plate_number=body['plate_number'])
data = json.loads(serializers.serialize('json',[newCar]))
return JsonResponse({'success':data})
And get this error
ValueError: Cannot assign "1": "Vehicle.driver_id" must be a "Driver" instance.
How to get rid off this error? How I can create an instance of Driver and 'post' an id?
You can do it in 2 ways
If you need the driver instance in somewhere in the code you can use this
driver_instance = Driver.objects.get(pk=body['driver_id'])
Vehicle.objects.create(driver_id=driver_instance,..)
Vehicle.objects.create(driver_id_id=body['driver_id'], ...)
The raw value of a ForeignKey can be accessed by appending "_id" to the field name, this can also be used to create an instance using the raw value
Vehicle.objects.create(driver_id_id=body['driver_id'], ...)

Django: Integrity error not null for ForeignKey id field

I have a model which contains ForeignKeys to a number of other models and find, for some reason, I am able to save one of these models absolutely fine, but another I receive a fault message saying:
IntegrityError: NOT NULL constraint failed: app_eofsr.flight_id
See below for my models.py:
# models.py
class Aircraft(models.Model):
esn = models.IntegerField()
acid = models.CharField(max_length=8)
engpos = models.IntegerField()
operator = models.CharField(max_length=5, default='---')
fleet = models.ForeignKey(Fleet, blank=True)
slug = models.SlugField(default=None, editable=False, max_length=50, unique=True)
class EoFSR(models.Model):
datetime_eofsr = models.DateTimeField(default=None)
flight_number = models.CharField(max_length=10)
city_from = models.CharField(max_length=4)
city_to = models.CharField(max_length=4)
and these both feed into this model:
# models.py
class Flight(models.Model):
flight_number = models.CharField(max_length=10)
city_from = models.CharField(max_length=4, default=None)
city_to = models.CharField(max_length=4, default=None)
datetime_start = models.DateTimeField(default=None)
aircraft = models.ForeignKey(Aircraft, on_delete=models.CASCADE)
eofsr = models.ForeignKey(EoFSR, on_delete=models.CASCADE)
The odd thing being, I can save an Aircraft record no problem at all, but cannot save an EoFSR record and receive the NOT NULL constraint error message. I've done the usual deleting of the migrations and even tried deleting the db.sqlite3, but still no luck! Any suggestions?
Try to set null=True in models You have ForeignKey() like:
aircraft = models.ForeignKey(Aircraft, null=True, on_delete=models.CASCADE)
, then makemigrations and migrate

Field 'id' expected a number but got <Listing: Ps4 Pro>

It's my first time creating a Django website with models, and in my first attempt to insert data into my table I'm getting this error.
My models are as follows:
class User(AbstractUser):
pass
#https://docs.djangoproject.com/en/3.1/topics/auth/default/
class Listing(models.Model):
listingID = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="listID")
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, related_name="myListing", null=True)
watchers = models.ManyToManyField(User, blank=True, related_name="watchlist")
title = models.CharField(max_length=30)
description = models.TextField()
creation_date = models.DateField(auto_now=True)
img_url = models.URLField()
active = models.BooleanField(default=True)
def __str__(self):
return f"{self.title}"
class Bid(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.SET_NULL, related_name="bidsMadeOnMe", null=True, blank=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, related_name="myBids", null=True)
price = models.FloatField()
creation_date = models.DateField(auto_now=True, null=True)
def __str__(self):
return f"Bid={self.price}"
and the view that handles the form submission is this one:
#login_required
def create_listing(request):
if request.method == "POST":
user = User.objects.get(username=request.user.username)
l = Listing(created_by=user,
title=request.POST["title"],
description=request.POST["desc"],
# https://stackoverflow.com/questions/12176585/handling-dates-over-request-get
creation_date=models.DateTimeField(auto_now_add=True),
img_url=request.POST["image_url"]
)
l.save()
b = Bid(l,
user,
request.POST["initial_bid"],
models.DateTimeField(auto_now_add=True)
)
b.save()
return render(request, "auctions/index.html")
I know the problem is the way I'm adding the data but I can't fix it. Can someone give me some light?
Your problem (well, several actually) is this:
b = Bid(l, user, request.POST["initial_bid"], models.DateTimeField(auto_now_add=True))
You're constructing a model instance by positional arguments instead of keyword arguments. This can be done, but then the invisible "id" column that has been added to the Bid model, is the first argument.
In Django we never construct models like that, but always use keyword arguments, so we're not depending on field order:
b = Bid(listing=l, user=user, ...))
Once you're solved that, your next problem is the date field.
Don't assign fields to model instances. Fields are class declarations, they don't belong on instances. Fields describe on a class (= a Model), what kind data to expect. On the instance, you assign that data.
In this case, your definition for the field is wrong on the model and on the instance you shouldn't even assign it - it will be automatically filled.
Overall, it feels like you haven't gone through Django's tutorial or did not fully understand the concepts. I suggest you go through it.

Django ORM - updating specific instance with a user-ForeignKey

I have the following model setup:
class Model1(models.Model):
val1_1 = models.CharField(max_length=25, blank=True)
val1_2 = models.CharField(max_length=25, blank=True)
user = models.ForeignKey('users.User', on_delete=models.PROTECT, related_name='model1')
class Model2(models.Model):
val2_1 = models.BinaryField()
model1_link = models.ForeignKey(Case, on_delete=models.CASCADE, related_name='model2')
class Model3(models.Model):
id = models.BigAutoField(primary_key=True)
model2_link = models.ForeignKey(Model2, on_delete=models.CASCADE, related_name='model3')
val3_1 = models.CharField(max_length=50)
class Model4(models.Model):
id = models.BigAutoField(primary_key=True)
model3_link = models.ForeignKey(Model3, on_delete=models.CASCADE, related_name='model4', null=True, default=None)
pred = models.CharField(max_length=50)
# These fields are NOT FILLED IN during creation of an instance, and are instead updated later on with a separate query
disputed_on = models.DateTimeField(blank=True, null=True)
suggested_by = models.ForeignKey('users.User', on_delete=models.PROTECT, related_name='submitted_disputes', blank=True, null=True)
At times, I will want to access Model4's specific instance, to actually fill in a value in fields disputed_on & suggested_by, by traversing all the way from Model1. I do that currently as such:
query = Model1.objects.filter(id=some_chosen_id).get().model2.last().model3.filter(val3_1=some_chosen_value).get().model4.last()
The output of that query is a single model instance, not a QuerySet.
Next, I calculate new values I want to insert:
dispute_date = datetime.now(tz.tzutc())
if request.user.is_authenticated:
disputer = request.user
else:
# Assume admin (first entry)
disputer = User.objects.get(pk=1)
And I save new values by doing the following:
query.disputed_on = dispute_date
query.suggested_by = disputer
query.save()
Now, the strangest thing happens - my postgres DB gives me an error stating, the following:
postgres_1 | 2020-03-30 11:45:31.700 AEDT [4169] ERROR: duplicate key value violates unique constraint "users_user_username_key"
Now, the way I read it, calling prediction.save() also results in DB trying to update table of users. But I do not call for that anywhere in the code!
Any ideas why is that happening?
That problem seems to be gone when I modify my query to stay as a QuerySet, and use .update() method instead...

Categories

Resources