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
Related
I have an app called map. Within map, I have the following models being specificed:
class Checkin(models.Model):
time = models.DateTimeField()
class Pin(models.Model):
name = models.CharField(max_length=64)
latitude = models.FloatField()
longitude = models.FloatField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
place_id = models.TextField(default=None, null=True)
address = models.TextField(default=None, null=True, blank=True)
checkins = models.ForeignKey(Checkin, on_delete=models.CASCADE, default=None, null=True)
class Meta:
unique_together = ["name", "latitude", "longitude"]
The migrations work fine. However, when I try to access the class Pin via the admin panel, I get this error message:
psycopg2.errors.UndefinedColumn: column map_pin.checkins_id does not exist
LINE 1: ...r_id", "map_pin"."place_id", "map_pin"."address", "map_pin"....
If I try to access the class Pin via Pin.objects.all() I also receive the same error.
I've setup a relationship using django's ForeignKey against 2 unmanaged tables like so:
class Product(BaseModel):
publish_name = models.CharField(unique=True, max_length=40)
# this works:
associated_country = models.ForeignKey('geonames.Countryinfo', models.DO_NOTHING, db_column='published_country', blank=True, null=True)
# this doesn't:
associated_continent = models.ForeignKey('geonames.Continentcodes', on_delete=models.DO_NOTHING, db_column='published_continent' blank=True, null=True)
class Meta:
managed = True
db_table = 'product'
class Continentcodes(models.Model):
code = models.CharField(max_length=2, primary_key=True, unique=True)
name = models.TextField(blank=True, null=True)
geoname_id = models.ForeignKey('Geoname', models.DO_NOTHING, blank=True, null=True, unique=True)
class Meta:
managed = False
db_table = 'geoname_continentcodes'
class Countryinfo(models.Model):
iso_alpha2 = models.CharField(primary_key=True, max_length=2)
country = models.TextField(blank=True, null=True)
geoname = models.ForeignKey('Geoname', models.DO_NOTHING, blank=True, null=True)
neighbours = models.TextField(blank=True, null=True)
class Meta:
ordering = ['country']
managed = False
db_table = 'geoname_countryinfo'
verbose_name_plural = 'Countries'
When I go to edit an entry in the django admin page for 'Products' I see this:
InvalidCursorName at /admin/product/6/change/ cursor
"_django_curs_140162796078848_sync_5" does not exist
The above exception (column geoname_continentcodes.geoname_id_id does
not exist LINE 1: ...ntcodes"."code", "geoname_continentcodes"."name",
"geoname_c...
^ HINT: Perhaps you meant to reference the column
"geoname_continentcodes.geoname_id"
It looks like it's trying to reference geoname_continentcodes.geoname_id_id for some reason. I have tried adding to='code' in the ForeignKey relationship, but it doesn't seem to effect anything.
Additionally, the associated_country relationship seems to work just fine if I comment out the associated_continent field. The associated_continent is the column that is giving some problem.
Here is some more context about what the table looks like in the database:
Removing the '_id' as the suffix is the fix. In this case geoname_id changed to geoname fixes this. Why? I have no idea. Django is doing something behind the scenes that is not clear to me. Here is the updated model:
class Continentcodes(models.Model):
code = models.CharField(max_length=2, primary_key=True, unique=True)
name = models.TextField(blank=True, null=True)
# remove '_id' as the suffix here
geoname = models.ForeignKey('Geoname', models.DO_NOTHING, blank=True, null=True, unique=True)
class Meta:
managed = False
db_table = 'geoname_continentcodes'
Django adds _id to the end to differentiate between the object and the id column in the table, geoname_id will return the table id where as geoname will return the object.
at the moment I try to get recipes from my API. I have a Database with two tables one is with recipes and their ids but without the ingredients, the other table contains the ingredients and also the recipe id. Now I cant find a way that the API "combines" those. Maybe its because I added in my ingredient model to the recipe id the related name, but I had to do this because otherwise, this error occurred:
ERRORS:
recipes.Ingredients.recipeid: (fields.E303) Reverse query name for 'Ingredients.recipeid' clashes with field name 'Recipe.ingredients'.
HINT: Rename field 'Recipe.ingredients', or add/change a related_name argument to the definition for field 'Ingredients.recipeid'.
Models
from django.db import models
class Ingredients(models.Model):
ingredientid = models.AutoField(db_column='IngredientID', primary_key=True, blank=True)
recipeid = models.ForeignKey('Recipe', models.DO_NOTHING, db_column='recipeid', blank=True, null=True, related_name='+')
amount = models.CharField(blank=True, null=True, max_length=100)
unit = models.CharField(blank=True, null=True, max_length=100)
unit2 = models.CharField(blank=True, null=True, max_length=100)
ingredient = models.CharField(db_column='Ingredient', blank=True, null=True, max_length=255)
class Meta:
managed = True
db_table = 'Ingredients'
class Recipe(models.Model):
recipeid = models.AutoField(db_column='RecipeID', primary_key=True, blank=True) # Field name made lowercase.
title = models.CharField(db_column='Title', blank=True, null=True, max_length=255) # Field name made lowercase.
preperation = models.TextField(db_column='Preperation', blank=True, null=True) # Field name made lowercase.
images = models.CharField(db_column='Images', blank=True, null=True, max_length=255) # Field name made lowercase.
#ingredients = models.ManyToManyField(Ingredients)
ingredients = models.ManyToManyField(Ingredients, related_name='recipes')
class Meta:
managed = True
db_table = 'Recipes'
When there is no issue it has to be in the serializer or in the view.
Serializer
class IngredientsSerializer(serializers.ModelSerializer):
# ingredients = serializers.CharField(source='ingredients__ingredients')
class Meta:
model = Ingredients
fields = ['ingredient','recipeid']
class FullRecipeSerializer(serializers.ModelSerializer):
ingredients = IngredientsSerializer(many=True)
class Meta:
model = Recipe
fields = ['title','ingredients']
View
class FullRecipesView(generics.ListCreateAPIView):
serializer_class = FullRecipeSerializer
permission_classes = [
permissions.AllowAny
]
queryset = Recipe.objects.all()
This is at the moment my output
But I want e.g. the recipe with id 0 and all the ingredients which have also recipe id 0.
I really hope that you can help me. Thank you so much!
From the doc of ForeignKey.related_name,
If you’d prefer Django not to create a backwards relation, set related_name to '+' or end it with '+'.
So, change the related_name of Ingredients.recipeid field to
class Ingredients(models.Model):
# rest of the fields
recipeid = models.ForeignKey(
'Recipe',
models.DO_NOTHING,
db_column='recipeid',
blank=True,
null=True,
related_name="ingredients_ref" # Changed the related name
)
Then, migrate the database using python manage.py makemigrations and python manage.py migrate
Then, update your FullRecipeSerializer class as,
class FullRecipeSerializer(serializers.ModelSerializer):
ingredients_forward = IngredientsSerializer(many=True, source="ingredients")
ingredients_backward = IngredientsSerializer(many=True, source="ingredients_ref")
class Meta:
model = Recipe
fields = ['title', 'ingredients_forward', 'ingredients_backward']
Note that, here I have added two fields named ingredients_forward and ingredients_backward because there existing two types of relationships between Recipe and Ingredients and I am not sure which one you are seeking.
I need to log the transaction of the item movement in a warehouse. I've 3 tables as shown in the below image. However Django response error:
ERRORS:
chemstore.ItemTransaction: (models.E007) Field 'outbin' has column name 'bin_code_id' that is used by another field.
which is complaining of multiple uses of the same foreign key. Is my table design problem? or is it not allowed under Django? How can I achieve this under Django? thankyou
DB design
[Models]
class BinLocation(models.Model):
bin_code = models.CharField(max_length=10, unique=True)
desc = models.CharField(max_length=50)
def __str__(self):
return f"{self.bin_code}"
class Meta:
indexes = [models.Index(fields=['bin_code'])]
class ItemMaster(models.Model):
item_code = models.CharField(max_length=20, unique=True)
desc = models.CharField(max_length=50)
long_desc = models.CharField(max_length=150, blank=True)
helper_qty = models.DecimalField(max_digits=10, decimal_places=4)
unit = models.CharField(max_length=10, blank=False)
def __str__(self):
return f"{self.item_code}"
class Meta:
verbose_name = "Item"
verbose_name_plural = "Items"
indexes = [models.Index(fields=['item_code'])]
class ItemTransaction(models.Model):
trace_code = models.CharField(max_length=20, unique=False)
item_code = models.ForeignKey(
ItemMaster, related_name='trans', on_delete=models.CASCADE, null=False)
datetime = models.DateTimeField(auto_now=False, auto_now_add=False)
qty = models.DecimalField(max_digits=10, decimal_places=4)
unit = models.CharField(max_length=10, blank=False)
action = models.CharField(
max_length=1, choices=ACTION, blank=False, null=False)
in_bin = models.ForeignKey(
BinLocation, related_name='in_logs', db_column='bin_code_id', on_delete=models.CASCADE, null=False)
out_bin = models.ForeignKey(
BinLocation, related_name='out_logs', db_column='bin_code_id', on_delete=models.CASCADE, null=False)
remarks = models.TextField(blank=True)
def __str__(self):
return f"{self.trace_code} {self.datetime} {self.item_code} {dict(ACTION)[self.action]} {self.qty} {self.unit} {self.in_bin} {self.out_bin}"
you have same db_column in two fields so change it
in_bin = models.ForeignKey(
BinLocation, related_name='in_logs', db_column='bin_code_id', on_delete=models.CASCADE, null=False)
out_bin = models.ForeignKey(
BinLocation, related_name='out_logs', db_column='other_bin_code', on_delete=models.CASCADE, null=False) /*change db_column whatever you want but it should be unique*/
If are linked to the same model name, You should use different related_name for each foreign_key filed . here is the exemple :
address1 = models.ForeignKey(Address, verbose_name=_("Address1"),related_name="Address1", null=True, blank=True,on_delete=models.SET_NULL)
address2 = models.ForeignKey(Address, verbose_name=_("Address2"),related_name="Address2", null=True, blank=True,on_delete=models.SET_NULL)
thank you for everyone helped. According to Aleksei and Tabaane, it is my DB design issue (broken the RDBMS rule) rather than Django issue. I searched online and find something similar: ONE-TO-MANY DB design pattern
In my case, I should store in bin and out bin as separated transaction instead of both in and out in a single transaction. This is my solution. thankyou.
p.s. alternative solution: I keep in bin and out bin as single transaction, but I don't use foreign key for bins, query both in bin and out bin for the bin selection by client application.
I've got a question. I want to delete the record in 'through' model, while editing Competition model in Django Admin. It is about editing m2m field 'competition_field'. Example: Competition with fields('Height', 'Width), and I will remove 'width' from m2m, and nothing will change in model 'FieldValues' I have tried everything I know, but without some succes.
This is my models.py
class Fields(models.Model):
field_name = models.CharField(max_length=100, unique=True)
class Competitions(models.Model):
competition_title = models.CharField(max_length=100, unique=True)
competition_field = models.ManyToManyField(Fields)
class Applications(models.Model):
application_applicant = models.ForeignKey(Applicant, on_delete=models.CASCADE)
application_competition = models.ForeignKey(Competitions, on_delete=models.CASCADE,)
application_value = models.ManyToManyField(Fields, through='FieldsValues')
class FieldsValues(models.Model):
catch_fields = models.ForeignKey(Fields, on_delete=models.CASCADE)
application = models.ForeignKey(Applications, on_delete=models.CASCADE)
value = models.TextField(null=True, default=0)