Django autofixture generating test data with foreign key - django

I have using django-autofixture to generate some random data for my database instance. My model is as follows:
class DummyModel(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=150, blank=True)
time_points = models.PositiveIntegerField()
more_text = models.CharField(max_length=100, blank=True)
image_type = models.ForeignKey(ImageTypeModel, null=False, blank=False,
default='')
class Meta:
db_table = "dummy"
So, I have a foreign key which should always be present and it cannot be NULL. I also have created instances for this ImageTypeModel using the fixtures functionality in Django. I deleted everything and migrated fresh and verified that the ImageTypeModel database table exists and is populated. The ImageTypeModel is defined as:
class ImageTypeModel(models.Model):
name = models.CharField(max_length=100)
dims = models.IntegerField()
class Meta:
db_table = "imagetypes"
def __str__(self):
return self.name
def __unicode__(self):
return self.name
Now I attempt to create some random data using the command:
python manage.py loadtestdata myapp.DummyModel:30
However, this returns me this error:
django.db.utils.IntegrityError: NOT NULL constraint failed: dummy.image_type_id
I am at a loss as to why it should be and have tried deleting/replicating the project to a fresh location but no go.

Related

Why on_delete of Django Rest Framework not work as expected on Image and File Fields?

When I delete the parent table using Django rest due to on_delete it deletes the child table also (due to foreign key) but the Image and File content of the child table not deleted.
I want to delete those images and Files also..!
How to do that..?
My tables
1:Group
2:Posts
One To Many Relation
I delete the Group table as follows:
GroupsModel.objects.filter(id=py_data.get('group_id')).delete()
GroupsModel :
class GroupsModel(models.Model):
group_name = models.CharField(max_length=20, unique=True)
group_description = models.CharField(max_length=50)
group_joining_link = models.CharField(max_length=50, default='', unique=True)
user_id = models.ManyToManyField(UserModel, through='UserModelGroupsModel', related_name='u_g')
class Meta:
db_table = 'groups'
GroupPostsModel:
class GroupPostsModel(models.Model):
post_text = models.CharField(max_length=1000)
post_type = models.CharField(max_length=20)
image = models.ImageField(blank=True, null=True, upload_to='post_images/')
document = models.FileField(blank=True,null=True, upload_to='post_documents/')
likes = models.IntegerField(default=0)
time_stamp = models.DateTimeField(auto_now=True)
group = models.ForeignKey(GroupsModel, on_delete=models.CASCADE)
user = models.ForeignKey(UserModel, on_delete=models.CASCADE)
class Meta:
db_table = 'group_posts'
I want to delete image and document file also automatically.
When an instance is removed referred files are not deleted, since the ImageField/FileField is only a reference to the files. You can override the delete method of your model:
import os
class GroupPostsModel(models.Model):
post_text = models.CharField(max_length=1000)
post_type = models.CharField(max_length=20)
image = models.ImageField(blank=True, null=True, upload_to='post_images/')
document = models.FileField(blank=True,null=True, upload_to='post_documents/')
likes = models.IntegerField(default=0)
time_stamp = models.DateTimeField(auto_now=True)
group = models.ForeignKey(GroupsModel, on_delete=models.CASCADE)
user = models.ForeignKey(UserModel, on_delete=models.CASCADE)
def delete(self):
if self.image:
if os.path.isfile(self.image.path):
os.remove(self.image.path)
if self.document:
if os.path.isfile(self.document.path):
os.remove(self.document.path)
super().delete()
class Meta:
db_table = 'group_posts'
The delete method will not be called in the queryset you wrote, you need to delete each instance individually:
for instance in GroupsModel.objects.filter(id=py_data.get('group_id')):
instance.delete()
on_delete=models.CASCADE on a ForeignKey is something written and managed on the database schema. It is not Django that delete the child model on delete, but your database (MySQL, Postgres, ...) that automaticaly detect a failure on ForeignKey and perform a Cascade action (like a contraint).
models.ImageField and models.FileField are (at database level) just a CharField with the location on the file system of your file. The database cannot remove a file, so you cannot delegate this action to the database.
If you want automatic removal of file on Model .delete(), you have multiple possible strategy :
Periodic check that for each file, a model exists (if not, remove the file)
Overwrite the .delete() method of GroupPostsModel (but it will only work if you call .delete() on an instance of the model, not on a queryset, like on your exemple)
Add the removal feature on the delete endpoint.

Multiple default values specified for column "id" of table in Django 2.1.1

So I keep getting this error saying that there's multiple specified ID values for the device table, but I don't have a clue where I've specified any kind of default ID. I've tried setting a field as primary_key=True but that didn't solve the problem either.
EDIT: Traceback
class Campus(models.Model):
name = models.CharField(max_length=20)
address = models.CharField(max_length=40)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "Campuses"
class Teacher(models.Model):
name = models.CharField(max_length=20)
phone = models.CharField(max_length=11)
department = models.CharField(max_length=20)
campus = models.OneToOneField(Campus, on_delete=models.CASCADE, default="Not Assigned")
#devices = self.Device.objects.all()
def __str__(self):
return self.name
class Device(models.Model):
inUse = 'IU'
inStock = 'IS'
inMaintenance = 'IM'
damaged = 'DM'
statusChoices = (
(inUse, 'In Use'),
(inStock, 'In Stock'),
(inMaintenance, 'In Maintenance'),
(damaged, 'Damaged'),
)
name = models.CharField(max_length=20)
brand = models.CharField(max_length=20)
status = models.CharField(max_length=2, choices=statusChoices, default=inStock)
#user = models.ForeignKey(Teacher, on_delete=models.CASCADE, default=0)
def __str__(self):
return self.name
After navigating to my PostgreSQL instance I deleted all Django-related data and remade migrations and things are in working order again.
For future users: I recommend deleting your past migrations table in your database.

How to fetch translation record in django

I am new in django framework.I have 3 tables in mysql database. I want to fetch data from main table with translation table and images table.
My model.py
class Country(models.Model):
#id = models.IntegerField(primary_key=True)
iso_code = models.CharField(max_length=2, unique=True)
slug = models.CharField(max_length=255, unique=True)
is_featured = models.IntegerField(max_length=1)
class Meta:
db_table = 'rh_countries'
class CountryTranslation(models.Model):
country_id = models.ForeignKey(Country, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
description = models.TextField(blank=True, null=True)
locale = models.CharField(max_length=2)
class Meta:
db_table = 'rh_countries_translations'
class CountryImage(models.Model):
country_id = models.ForeignKey(Country, on_delete=models.CASCADE)
image = models.CharField(max_length=255)
is_main = models.IntegerField(max_length=1)
class Meta:
db_table = 'rh_country_images'
Now I want to fetch all country with translation record by locale and associated image.
Please give a solution if anyone know.
You can do this by using a filtering, and annotate:
from django.db.models import F
Country.objects.filter(
countrytranslation__locale=mylocale
).annotate(
name=F('countrytranslation__name')
)
This will result in a QuerySet with all Countrys (that have a Translation for the given mylocale). These Countrys will have an extra attribute .name that is the translated name of the Country.
So given the translations exist, then for mylocale='en', this will result in a QuerySet, with Country(name='Germany', iso_code='de'), and for mylocale='de', it will result in Country(name='Deutschland', iso_code='de') (here this is a bit an ad hoc format, to demonstrate how it works).
Note: ForeignKeys typically do not end with _id. Django will automatically add an _id suffix to the database column. The foreign key itself is on the Python/Django level represented as a lazy loaded attribute.

I am working with Django, During inserting data into database i caught such error

I'm working with django, during inserting data into tables the error is generates as given below...
Error:
int() argument must be a string, a bytes-like object or a number, not 'Tbl_rule_category', How can we solve such error?
view.py
dataToRuleCtgry = Tbl_rule_category(category=category, created_by="XYZ",created_date=datetime.date.today())
dataToRuleCtgry.save()
dataToRule = Tbl_rule(rule_name=rule_name, closure=closure,category_id=Tbl_rule_category.objects.latest('category_id'), created_by="XYZ",created_date=datetime.date.today(), updated_by="XYZ", updated_date=datetime.date.today(), rule_type=rule_type, fk_tbl_rule_tbl_rule_category_id=Tbl_rule_category.objects.latest('category_id'))
dataToRule.save()
models.py
class Tbl_rule_category(models.Model):
category_id = models.AutoField(primary_key=True)
category = models.CharField(max_length=50)
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
def __str__(self):
pass # return self.category, self.created_by
class Tbl_rule(models.Model):
rule_id = models.AutoField(primary_key=True)
rule_name = models.CharField(max_length=50)
closure = models.CharField(max_length=50)
category_id = models.IntegerField()
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
updated_by = models.CharField(max_length=50)
updated_date = models.DateField(auto_now=True)
rule_type = models.CharField(max_length=50)
fk_tbl_rule_tbl_rule_category_id = models.ForeignKey(Tbl_rule_category,on_delete=models.CASCADE, related_name='fk_tbl_rule_tbl_rule_category_id_r')
def __str__(self):
return self.rule_name, self.closure, self.created_by, self.updated_by, self.rule_type
The error is occurring because the following is trying to add an object into an integer field: category_id=Tbl_rule_category.objects.latest('category_id')
You could just add: category_id=dataToRuleCtgry.get('category_id') or category_id=dataToRuleCtgry.category_id which will solve the error.
You also don't need to add: created_date=datetime.date.today() because your model defines auto_now=true.
As mentioned you should also amend the def __str__(self): to return a string.
https://docs.djangoproject.com/en/2.0/ref/models/instances/#django.db.models.Model.str
Alternatively
You could just add the object link directly to your foreign key for the category model.fk_tbl_rule_tbl_rule_category_id=dataToRuleCtgry. You would no longer need the integer field category_id.
It would be better practice to use the model field name category_id instead of fk_tbl_rule_tbl_rule_category_id. This would mean deleting category_id and then rename fk_tbl_rule_tbl_rule_category_id to category_id.
In Django, the ORM takes care of the basic database details for you; which means in your code you really don't have to worry about individual row ids for maintaining foreign key relationships.
In fact, Django automatically assigns primary keys to all your objects so you should concentrate on fields that are relevant to your application.
You also don't have to worry about naming fields in the database, again Django will take care of that for you - you should create objects that have fields that are meaningful to users (that includes you as a programmer of the system) and not designed for databases.
Each Django model class represents a object in your system. So you should name the classes as you would name the objects. User and not tbl_user. The best practice is to use singular names. Django already knows how to create plural names, so if you create a model class User, django will automatically display Users wherever it makes sense. You can, of course, customize this behavior.
Here is how you should create your models (we will define __str__ later):
class RuleCategory(models.Model):
name = models.CharField(max_length=50)
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
class Rule(models.Model):
name = models.CharField(max_length=50)
closure = models.CharField(max_length=50)
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
updated_by = models.CharField(max_length=50)
updated_date = models.DateField(auto_now=True)
rule_type = models.CharField(max_length=50)
category = models.ForeignKey(RuleCategory,on_delete=models.CASCADE)
Django will automatically create any primary or foreign key fields, and any intermediary tables required to manage the relationship between the two models.
Now, to add some records:
new_category = RuleCategory(name='My Category', created_by='XYZ')
new_category.save()
# Another way to set values
new_rule = Rule()
new_rule.name = 'Sample Rule'
new_rule.closure = closure
new_rule.created_by = 'XYZ'
new_rule.updated_by = 'XYZ'
new_rule.rule_type = rule_type
new_rule.category = new_category
new_rule.save()
Note this line new_rule.category = new_category - this is how we link two objects. Django knows that the primary key should go in the table and will take care of that automatically.
The final item is customizing the models by creating your own __str__ method - this should return some meaningful string that is meant for humans.
class RuleCategory(models.Model):
name = models.CharField(max_length=50)
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
def __str__(self):
return '{}'.format(self.name)
class Rule(models.Model):
name = models.CharField(max_length=50)
closure = models.CharField(max_length=50)
created_by = models.CharField(max_length=50)
created_date = models.DateField(auto_now_add=True)
updated_by = models.CharField(max_length=50)
updated_date = models.DateField(auto_now=True)
rule_type = models.CharField(max_length=50)
category = models.ForeignKey(RuleCategory,on_delete=models.CASCADE)
def __str__(self):
return '{} for category {}'.format(self.name, self.category)
If you notice something, I just put self.category in the __str__ for the Rule model. This is because we have already defined a __str__ for the RuleCategory model, which just returns the category name; so now when we print our Rule we created, we will get Sample Rule for category My Category as a result.

Django addField ForeignKey during migrations create unusable constraint name

Env: Django 1.8.11 + Postgis
I'm adding some ForeignKeys on a MyModel.
The models pointed are in another schema ("cartography").
makemigrations
no errors
migrate
One error. Can't create the constraint because the generated name.
But I'm adding 10 fields, really similar between them. Only one is giving that stupid error.
I can't specify the constraint name anywhere.
class myModel(models.Model)
zps_calculated = models.ForeignKey( Cartography_zps, verbose_name="zps_calcolato", null=True, blank=True, on_delete=models.SET_NULL)
zsc_sic_sir_calculated = models.ForeignKey( Cartography_zsc_sic_sir, verbose_name="zsc_sic_sir_calcolato", null=True, blank=True, on_delete=models.SET_NULL)
manyothersdata = "xxx"
That is the slice of code generated from sqlmigrate (to inspect the code the migration generate).
As you see the name of the constraint is the error.
1 on 10 fields is giving the error
CREATE INDEX "segnalazioni_f38ba181" ON "segnalazioni" ("zps_calculated_id");
ALTER TABLE "segnalazioni" ADD CONSTRAINT "se_zps_calculated_id_6844dce0603174b2_fk_"cartography"."zps"_id" FOREIGN KEY ("zps_calculated_id") REFERENCES "cartography"."zps" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "segnalazioni_eb52e53f" ON "segnalazioni" ("zsc_sic_sir_calculated_id");
ALTER TABLE "segnalazioni" ADD CONSTRAINT "cc6ce48808e3a5292779a9787d21e5ad" FOREIGN KEY ("zsc_sic_sir_calculated_id") REFERENCES "cartography"."zsc_sic_sir" ("id") DEFERRABLE INITIALLY DEFERRED;
That is the name giving the error: "se_zps_calculated_id_6844dce0603174b2_fk_"cartography"."zps"_id"
I think should be something like:
"6844dce0603174b2..."
the model NOT giving the error:
class Cartography_zsc_sic_sir(models.Model):
id = models.AutoField(primary_key=True)
slug = models.CharField(max_length=40, blank=True, null=True)
nome = models.CharField(max_length=60, blank=True, null=True)
the_geom = models.MultiPolygonField(srid=23032, blank=True, null=True )
objects = models.GeoManager()
class Meta:
managed = False
db_table = '"cartography"."zsc_sic_sir"'
verbose_name = 'Cartography - zsc_sic_sir'
verbose_name_plural = 'Cartography - zsc_sic_sir'
ordering = ["id","slug"]
def __unicode__(self):
return self.nome
that is the model giving the error:
class Cartography_zps(models.Model):
id = models.AutoField(primary_key=True)
slug = models.CharField(max_length=40, blank=True, null=True)
the_geom = models.MultiPolygonField(srid=23032, blank=True, null=True )
objects = models.GeoManager()
class Meta:
managed = False
db_table = '"cartography"."zps"'
verbose_name = 'Cartography - ZPS'
verbose_name_plural = 'Cartography - ZPS'
ordering = ["id","slug"]
def __unicode__(self):
return self.slug
Going further I'm investigating in Django code, backwards.
The
' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' %
is in
/django/db/backends/base/creation.py row 180
using that
qn = self.connection.ops.quote_name
that SHOULD be the %s constraint name value:
qn(truncate_name(r_name, self.connection.ops.max_name_length()))
Anyone have an hint to help me?
I'm gonna look what qn does.
https://github.com/django/django/releases/tag/1.8.11
The problem was the attribute name (but I still dunno why):
zps_calculated = models.ForeignKey( Carto...
I renamed it to
zpsasd_calculated = models.ForeignKey( Carto
and the generated constraint name changed to (sqlmigrate):
a326518e5e22b0c2c1251e5bbb331adb
Wow!
Renamed the attribute zpsasd_calculated to zps_calculated, with another migration.
Worked.
Next time I will migrate with custom SQL
https://www.ralphlepore.net/custom-foreign-key-constraints-with-django/