Django Admin ManyToMany error - mysql

I'm using the the built in django admin site to save instances of a model that has a ManyToMany field. If I save, not update, a model in the admin site without setting a value for the ManyToMany field it saves fine. I can also come back and set the ManyToMany field after saving the model and that works. However, if I try to save a new instance of my model, Exercise, that has the ManyToMany field, Exercise.muscles, set I get the following error:
(1452, 'Cannot add or update a child row: a foreign key constraint fails
(vitality.projectvitality_exercise_muscles, CONSTRAINT exercise_id_refs_exercise_id_a5d4ddd6 FOREIGN KEY (exercise_id) REFERENCES projectvitality_exercise (exercise_id))')
My mysql tables are set to INNODB.
My models are as follows:
class Muscle(models.Model):
def format(self):
return "name:{0}:".format(self.name)
def __unicode__(self):
return unicode(self.name)
muscle_id = UUIDField(primary_key = True)
name = models.CharField(max_length=30, blank=False, default="")
medical = models.CharField(max_length=150, blank=True, default="")
description = models.TextField(blank=True, default="")
class Exercise(models.Model):
def format(self):
return "name:{0}".format(self.name)
def __unicode__(self):
return unicode(self.name)
ISOLATION_TYPE = "isolation"
COMPOUND_TYPE = "compound"
FULL_BODY_TYPE = "full"
EXERCISE_TYPES = (
(ISOLATION_TYPE, "Isolation"),
(COMPOUND_TYPE, "Compound"),
(FULL_BODY_TYPE, "Full Body")
)
UPPER_BODY_GROUP = "upper"
LOWER_BODY_GROUP = "lower"
GROUP_CHOICES = (
(UPPER_BODY_GROUP, "Upper Body"),
(LOWER_BODY_GROUP, "Lower Body")
)
exercise_id = UUIDField(primary_key=True)
name = models.CharField(max_length=30, default="", blank=False)
description = models.TextField(blank=True, default="")
group = models.CharField(max_length=255,
choices=GROUP_CHOICES,
blank=False,
default=UPPER_BODY_GROUP)
exercise_type = models.CharField(max_length=255,
choices=EXERCISE_TYPES,
blank=False,
default=ISOLATION_TYPE)
muscles = models.ManyToManyField('Muscle', blank=True, null=True)
class Meta:
verbose_name = "Exercise"
verbose_name_plural = "Exercises"

After several days of debugging I found the issue. In my code I use UUIDField, from django-extensions library, as a primary key. When saving a new instance of Exercise model it is able to generate, set and save the primary key. However, when saving a new instance of Exercise that has the ManyToMany field set, UUIDField isn't generated in time. This leads to the Django admin attempting to insert a null/empty primary key, the UUIDField in Exercise model, into the join table which triggers the Foreign Key constraint failure.

Related

Django - Foreign key constraint fails on delete with through model

I am working on a REST api using Django Rest and one endpoint involves deleting a Contact model, which can have multiple Addresses associated with it via ContactAddress through model.
The Contact model looks like this:
class Contact(AuditModel):
contact_id = models.AutoField(primary_key=True)
address = models.ManyToManyField('Address', through='ContactAddress')
name_first = models.CharField(max_length=100)
name_last = models.CharField(max_length=100)
ContactAddress looks like this:
class ContactAddress(models.Model):
contact = models.ForeignKey('Contact', on_delete=models.CASCADE)
address = models.ForeignKey('Address', on_delete=models.CASCADE)
is_billing = models.BooleanField(null=True, default=False)
is_shipping = models.BooleanField(null=True, default=False)
And the Address model looks like this:
class Address(AuditModel):
address_id = models.AutoField(primary_key=True)
postcode = models.CharField(max_length=30, blank=True, null=True)
region = models.CharField(max_length=100, blank=True, null=True)
street_line_1 = models.CharField(max_length=500, blank=True, null=True)
street_line_2 = models.CharField(max_length=500, blank=True, null=True)
street_line_3 = models.CharField(max_length=500, blank=True, null=True)
And when trying to delete the contact like so with contact.delete() I get the following MySQL error:
django.db.utils.IntegrityError: (1451, 'Cannot delete or update a parent row: a foreign key constraint fails (`mnghub`.`contact_addresses`, CONSTRAINT `contact_addresses_contact_id_cadc11a0_fk_contacts_contact_id` FOREIGN KEY (`contact_id`) REFERENCES `contacts` (`contact_id`))')
I get this error despite the contact having no addresses associated with it. I assume the constraint is because the relationship is many-to-many, but I want to be able to delete related models if they are only related with one object

How to export text value instead of foreign key id from mysql table to excel in django

Good day everyone! I'am new to django and i want to learn a lot in this excellent framework. I want to learn in django-import-export application and I have trouble in exporting data from mysql table. Django-import-export application export foreign key id rather than the foreign key I specified in to_field.
Below is my model
from django.db import models
class Rank(models.Model):
RankCode = models.CharField(max_length=20, null=False, blank=False, unique=True)
RankDesc = models.CharField(max_length=60, null=False, blank=False)
OrderNo = models.IntegerField(null=True, blank=True)
def __str__(self):
return "%s" % self.RankCode
class Status(models.Model):
StatusCode = models.CharField(max_length=60, null=False, blank=False, unique=True)
class Meta:
verbose_name_plural = 'Status'
def __str__(self):
return "%s" % self.StatusCode
class Student(models.Model):
Rank = models.ForeignKey(Rank, to_field='RankCode', on_delete=models.CASCADE)
Name = models.CharField(max_length=200, null=False, blank=False, unique=True)
Status = models.ForeignKey(Status, to_field='StatusCode', on_delete=models.CASCADE)
Age = models.IntegerField(null=True, blank=True)
def __str__(self):
return "%s" % self.Rank
If I export Student model to excel, I want the output to be the value of specified foreign key in to_field and not the id.
Thanks in advance to those who can contribute.

How to keep original ID using UUID as primary key in Django RF project?

I'd like to use two different primary keys in my DRF database app. By default Django "create" id as PK but when I'm trying to define new field in model (uuid = models.UUIDField (primary_key=True, default=uuid.uuid4, editable=False), default id field is not defined (in DB exist only uuid).
How can I initialize both of them?
I can mention that I didn't define id field in my model because it is (or should be - as I suppose) adding by DRF.
class Store(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4,
editable=False)
name = models.CharField(max_length=100, blank=False)
url = models.URLField(max_length=300, blank=False)
country = models.CharField(max_length=100, blank=True)
Primary key
In the relational model of databases, a primary key is a specific choice of a minimal set of attributes (columns) that uniquely specify a tuple (row) in a relation (table).
So, you can either use default primary key id or uuid (your choice).
If you want both then use unique=True instead.
class Store(models.Model):
uuid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=100, blank=False)
url = models.URLField(max_length=300, blank=False)
country = models.CharField(max_length=100, blank=True)
For your case you can change your model as
from django.db.models.fields import AutoField
from django.db.models.fields import checks
from django import models
class AutoFieldNonPrimary(AutoField):
def _check_primary_key(self):
if self.primary_key:
return [
checks.Error(
"AutoFieldNonPrimary must not set primary_key=True.",
obj=self,
id="fields.E100",
)
]
else:
return []
class Store(models.Model):
id = models.AutoFieldNonPrimary(unique=True)
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=100, blank=False)
url = models.URLField(max_length=300, blank=False)
country = models.CharField(max_length=100, blank=True)

How to create a table with non-unique id and have it as foreign key in another table?

I have the following tables in models.py:
class Part(models.Model):
partno = models.CharField(max_length=50, unique=True)
partdesc = models.CharField(max_length=50, default=None, blank=True, null=True)
class Price(models.Model):
part = models.ForeignKey(Part, on_delete=models.CASCADE, null=True)
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
qty = models.IntegerField(default=1)
price = models.DecimalField(max_digits=9, decimal_places=2)
currency = models.ForeignKey(Currency, on_delete=models.CASCADE)
datestart = models.DateTimeField(auto_now_add=True, blank=False, null=False)
class Meta:
unique_together = (('supplier', 'part'),)
This is properly working. The problem is I have many part numbers which are their replacements. For example part 1001-01, 1001-02, 1001-03 are all the same part. Still, I have all of them in my Part table.
I need to match them in another table, so I don't need to enter price for each of them separately. There must be a unique key representing all of these three items.
Question: How do I setup a "part number match table" and have a foreign key to this table in my Price table?
(Rest is optional to read which are my opinions/problems so far, might help though)
1: I tried to setup the table like this:
class PartMatch(models.Model):
id = models.IntegerField(primary_key=True, unique=False, null=False, db_index=True)
part = models.ForeignKey(Part, unique=False, on_delete=models.CASCADE)
I don't get an error while migrating but when I try to use the same id for PK, it doesn't allow me.
2: I left the pk alone and tried to setup another field to match parts:
class PartMatch(models.Model):
part = models.ForeignKey(Part, on_delete=models.CASCADE)
partmatchid = models.IntegerField(null=True, unique=False, db_index=True)
I don't get any error while migrating but when I try to use partmatchid as a foreign key in my Price table like this:
partmatch = models.ForeignKey(PartMatch, to_field="partmatchid",
db_column="partmatchid",
on_delete=models.CASCADE)
I get an error saying foreign key must be unique while migrating.
Well in this case I am out of solutions. I wonder how you guys handle this?
Your Part model can have a foreign key to PartMatch, not the other way around.
Your model can be Part *<-->1 PartMatch and PartMatch 1<-->1 Price
For example:
class Price(models.Model):
price = models.DecimalField(max_digits=9, decimal_places=2)
class PartMatch(models.Model):
price = models.OneToOneField(Price, primary_key=True)
class Part(models.Model):
partno = models.CharField(max_length=50, unique=True)
partMatch = models.ForeignKey(PartMatch)
If you want to get all parts with some price, some_price.partmatch.part_set.all() will do the job.

Foreign key field is not being created in the database

I'm trying to associate Comment with User models, but somehow the field is not being created in the database. When I try to access the page, the following error is shown:
(1054, "Unknown column 'user_comments.user_id' in 'field list'")
These are in the models.py:
class User(models.Model):
username = models.CharField(max_length=128)
password = models.CharField(max_length=128)
first_name = models.CharField(max_length=128)
last_name = models.CharField(max_length=128)
email = models.CharField(max_length=128)
date_joined = models.DateField(auto_now_add=True)
class Meta:
db_table = 'auth_user'
ordering = ('date_joined',)
class Comment(models.Model):
user = models.ForeignKey('auth.User', related_name='comments', on_delete=models.CASCADE)
content = models.CharField(max_length=256)
date_created = models.DateField(auto_now_add=True)
class Meta:
db_table = 'user_comments'
ordering = ('date_created',)
def __str__(self):
return self.content
def save(self, *args, **kwargs):
content = self.content
super(Comment, self).save(*args, **kwargs)
If I name the user variable to user_id, an error saying user_id_id wasn't found will show upon creating a new Comment in the admin panel.
** Update **
I dropped the whole database and I removed the db_table options, and thus user_id has been created. But now, upon creation of a new Comment, the following:
IntegrityError at /admin/api/comment/add/
(1452, 'Cannot add or update a child row: a foreign key constraint fails (`softwarestore`.`api_comment`, CONSTRAINT `api_comment_user_id_14315666_fk_api_user_id` FOREIGN KEY (`user_id`) REFERENCES `api_user` (`id`))')
Have you tried simply replacing following:
user = models.ForeignKey('auth.User', related_name='comments', on_delete=models.CASCADE)
with
user = models.ForeignKey(User, related_name='comments', on_delete=models.CASCADE)
and run makemigrations?