Foreign key to get column from another model - Django - django

I have been trying to add a new column to my TrainingSubject model called "email" and link its value to another model (Training) via foreign key, and then display it all on front end (back is django, front is react.
I've added this line to TrainingSubject model:
email = models.CharField(_('Email assigned'), max_length=100, default='', blank=True)
and this one to Training model:
email_to = models.ForeignKey(TrainingSubject, related_name='manager_email', default='', blank=True)
so it all reads as follows:
class TrainingSubject(models.Model):
"""TrainingSubject model for storing subjects."""
name = models.CharField(_('name'), max_length=160, unique=True)
email = models.CharField(_('Email assigned'), max_length=100, default='', blank=True)
def __str__(self):
return self.name
class Meta:
verbose_name = _('Training subject')
verbose_name_plural = _('Training subjects')
class Training(models.Model):
"""Training model for storing trainings."""
subject = models.ForeignKey(TrainingSubject, verbose_name=_('subject'),
related_name='trainings')
email_to = models.ForeignKey(TrainingSubject, related_name='manager_email', default='', blank=True)
date = models.DateTimeField(_('date'))
timezone = models.CharField(
The migration cannot be applied, I get this error every single time I start creating these things.
Running migrations:
Rendering model states... DONE
Applying sonel_core.0089_training_email_to...Traceback (most recent call last):
File "/home/vagrant/.pyenv/versions/cms/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
psycopg2.IntegrityError: column "email_to_id" contains null values
Previously I tried to add it all in one step only, now I have broken it down to two steps: 1. add email to TrainingSubject (which work perfectly well) and 2. add email_to to Training model and the be able to finally display this email on the front-end.
What am I doing wrong?

Define the field to accept null values, as the table already does have some data, when adding new FK field, null has to be given or a valid values.
email_to = models.ForeignKey(TrainingSubject, related_name='manager_email', default='', blank=True, null=True)

Related

After rewriting Django models to remove unecessary primary keys got InvalidCursorName error message

After learning most of my primary keys did not have to be hardcoded in Django models, I decided to remove them all. In order to have Django-admin up and running I had to solve a few issues first, which I did by deleting all migrations files.
Once those issues were out of the way, after making migrations and migrating sucessfully again, while in Django admin trying to add data to a particular model, right after clicking the add button I got this error message:
Traceback (most recent call last):
File "C:\Users\fsoar\urban_forest_box\virtualenv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedColumn: column app_species_catalog_nome_popular.id does not exist
LINE 1: ...188_sync_1" NO SCROLL CURSOR WITH HOLD FOR SELECT "app_speci...
This lead to a series of exceptions which ledd to another series of exceptions of which the last erros message was:
psycopg2.errors.InvalidCursorName: cursor "_django_curs_17188_sync_1" does not exist
models.py is a bit long, so I am pasting only the main model of this app, which is the one I was using to add data when it happened, and which speaks for itself regarding my Python/Django skills level :)
I would like to understand what is going on, and I imagine it will take several months before I get to that, but most important, I would like to fix it first, so as to keep my learning journey going.
# ARVORE
class Img_Arvore(models.Model):
img_arvore = models.ImageField(upload_to=r'urban_forest_django_project\uploads\img_arvores_completas')
class Meta:
verbose_name = "Foto da árvore"
verbose_name_plural = "Fotos da árvore"
class Arvore(models.Model):
nome_cientifico = models.CharField("Nome científico", max_length=200, help_text="Nome científico completo", primary_key=True)
nomes_populares = models.ManyToManyField(Nome_Popular, verbose_name="Nomes populares")
estados_de_conservacaos = (
('EX', 'Extinta'),
('EW', 'Extinta no ambiente silvestre'),
('CR', 'Criticamente em perigo'),
('EN', 'Em perigo'),
('VU', 'Vulnerável'),
('NT', 'Quase ameaçada'),
('LC', 'Menos preocupante'),
('DD', 'Dados insuficientes'),
('NE', 'Não avaliado')
)
estado_de_conservacao = models.CharField("Estado de conservação", max_length=50, choices=estados_de_conservacaos)
botanic_description = models.TextField('Descrição botânica', blank=True)
create_date = models.DateTimeField(auto_now_add=True)
update_date = models.DateTimeField(blank=True, null=True)
taxonomia = models.OneToOneField(Taxonomia, on_delete=SET_NULL, null=True, blank=True)
biotipo = models.ForeignKey(Biotipo, on_delete=SET_NULL, null=True, blank=True)
dendrometria = models.ForeignKey(Dendrometria, on_delete=SET_NULL, null=True, blank=True)
peculiaridades = models.ForeignKey(Peculiaridade, on_delete=SET_NULL, null=True, blank=True)
caule = models.ForeignKey(Caule, on_delete=SET_NULL, null=True, blank=True)
raiz = models.ForeignKey(Raiz, on_delete=SET_NULL, null=True, blank=True)
folha = models.ForeignKey(Folha, on_delete=SET_NULL, null=True, blank=True)
flor = models.ForeignKey(Flor, on_delete=SET_NULL, null=True, blank=True)
fruto = models.ForeignKey(Fruto, on_delete=SET_NULL, null=True, blank=True)
distribuicao_estadual = models.ManyToManyField(UF_Brasileira, blank=True)
distribuicao_regional = models.ManyToManyField(Regiao_Brasileira, blank=True)
dominio_fitogeografico = models.ManyToManyField(Bioma_Brasileiro, blank=True)
vegetacao_encontrada = models.ManyToManyField(Vegetacao_Brasileira, blank=True)
maiores_informacoes = models.ForeignKey(Link_Externo, on_delete=SET_NULL, null=True, blank=True)
class Meta:
verbose_name = "Árvore"
verbose_name_plural = "Árvores"
def __str__(self):
return self.nome_cientifico
Did you also drop (delete) your database?
Your database changes with migrations, So if you delete migrations and you dont drop your database, database will be confused because it is not synced with your django app. Try to run it on another database, but dont forget to makemigration and also migrate.
You should think of migrations as a version control system for your database schema. makemigrations is responsible for packaging up your model changes into individual migration files - analogous to commits - and migrate is responsible for applying those to your database.
For more information : https://docs.djangoproject.com/en/3.2/topics/migrations/

Django: error while trying to access ManyToMany field

I'm trying to create a twitter like application as a practice project, and following this video tutorial. I've created following models in my app.
class Profile(models.Model):
user = models.OneToOneField(to=User, on_delete=models.CASCADE)
bio = models.CharField(max_length=160, blank=True)
profile_photo = models.ImageField(blank=True, null=True)
followers = models.ManyToManyField("self", through="Relationship", related_name="follow_to",
symmetrical=False, blank=True)
class Relationship(models.Model):
user_followed = models.ForeignKey("User", related_name="followed", on_delete=models.CASCADE)
followed_by = models.ForeignKey("Profile", related_name="follower", on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now=True)
The migrations ran successfully.
After this for testing, I created two users (user1 and user2) with their respective profiles and made user2 to follow user1. Here's the code for that-
Relationship.objects.create(user_followed=user1,followed_by=user2.profile)
This relationship was successfully created. I try the following code to try to get followers of user1-
user1.profile.followers.all()
But above code is giving following errors-
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/mayank/.pyenv/versions/dwitter/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 535, in __get__
return self.related_manager_cls(instance)
File "/Users/mayank/.pyenv/versions/dwitter/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 821, in __init__
self.target_field_name = rel.field.m2m_reverse_field_name()
File "/Users/mayank/.pyenv/versions/dwitter/lib/python3.8/site-packages/django/db/models/fields/related.py", line 1554, in _get_m2m_reverse_attr
return getattr(self, cache_attr)
AttributeError: 'ManyToManyField' object has no attribute '_m2m_reverse_name_cache'
I tried following the method mentioned here, but it is also giving the same error. I'm not sure where have I committed a mistake. I would be thankful if someone can correct me.
Since you make an ManyToManyField to 'self' both the ForeignKeys should point to Profile:
class Relationship(models.Model):
followed = models.ForeignKey(
'Profile',
related_name='followed',
on_delete=models.CASCADE
)
followed_by = models.ForeignKey(
'Profile',
related_name='follower',
on_delete=models.CASCADE
)
timestamp = models.DateTimeField(auto_now=True)
Since now both ForeignKeys point to the same model, there is an ambiguity what the source field, and what the target field is. You resolve this by specifying this with the through_fields=… parameter [Django-doc]:
class Profile(models.Model):
user = models.OneToOneField(to=User, on_delete=models.CASCADE)
bio = models.CharField(max_length=160, blank=True)
profile_photo = models.ImageField(blank=True, null=True)
followers = models.ManyToManyField(
'self',
through='Relationship',
related_name='follow_to',
related_fields=('followed', 'followed_by')
symmetrical=False,
blank=True
)
You thus can create a follower Relation with:
Relationship.objects.create(
followed=user1.profile,
followed_by=user2.profile
)

Exception handling in django import-export

A quick question about django import-export. Suppose I have a model like the one in the docs, but with some additional constraints (note the Meta class):
class Book(models.Model):
name = models.CharField('Book name', max_length=100)
author = models.ForeignKey(Author, blank=True, null=True)
author_email = models.EmailField('Author email', max_length=75, blank=True)
imported = models.BooleanField(default=False)
published = models.DateField('Published', blank=True, null=True)
price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
categories = models.ManyToManyField(Category, blank=True)
def __unicode__(self):
return self.name
class Meta:
unique_together = ('name', 'author')
On bulk upload, I would ideally like that any rows containing errors (duplicate entries in this case -- but could be other type of "corrupt" rows too) to be skipped and the rest of the upload to continue. The corrupt rows should be logged into a file containing the row(s) in question and an additional column with the exception name.
There is a generic exceptions.py file :
class ImportExportError(Exception):
"""A generic exception for all others to extend."""
pass
class FieldError(ImportExportError):
"""Raised when a field encounters an error."""
pass
But it is not clear how to deal with the row by row situation and skipping. Any help from anyone who's dealt with this would greatly appreciated.
documentation is pretty clear:
dry_run is a Boolean which determines if changes to the database are
made or if the import is only simulated. It defaults to False.
raise_errors is a Boolean. If True, import should raise errors. The
default is False, which means that eventual errors and traceback will
be saved in Result instance.

Django get_or_create trying to create row, throwing IntegrityError?

I'm working in Django 1.7 and Postgres, and using the ORM to create some new rows. I am using get_or_create as follows:
p, created = Practice.objects.get_or_create(
code=row[1],
name=row[2],
address1=row[3],
address2=row[4],
address3=row[5],
address4=row[6],
postcode=row[7]
)
But when I try to run this I get:
django.db.utils.IntegrityError: duplicate key value violates unique constraint
DETAIL: Key (code)=(A82057) already exists
What's this about? I thought the point of get_or_create was to only try to create new rows if they didn't already exist.
My model looks like this:
class Practice(TimeStampedModel):
code = models.CharField(max_length=6, primary_key=True, db_index=True)
name = models.CharField(max_length=200)
address1 = models.CharField(max_length=200, null=True, blank=True)
address2 = models.CharField(max_length=200, null=True, blank=True)
address3 = models.CharField(max_length=200, null=True, blank=True)
address4 = models.CharField(max_length=200, null=True, blank=True)
postcode = models.CharField(max_length=9, null=True, blank=True)
def __str__(self):
return self.name
class Meta:
app_label = 'frontend'
ordering = ['name']
Is it something to do with the fact that I've set a manual primary key? I can't see anything in the Django docs about this restriction.
get_or_create attempts to do a get with all of the parameters you pass, not just the PK. So if there is an object with a matching PK but a different postcode, for example, the get will fail so a create will be attempted - but, since you have a manual PK, it will try to create a duplicate one using the data you have passed.
Generally speaking using a non-autoincrementing PK is a bad idea. But if you are just trying to look up against the PK only, use the defaults argument:
p, created = Practice.objects.get_or_create(
code=row[1],
defaults={
'name': row[2],
'address1': row[3],
'address2': row[4],
'address3': row[5],
'address4': row[6],
'postcode': row[7]
})

Django ForeignKey TemplateSyntaxError and ProgrammingError

This is are my models i want to relate. i want for collection to appear in the form of occurrence.
class Collection(models.Model):
id = models.AutoField(primary_key=True, null=True)
code = models.CharField(max_length=100, null=True, blank=True)
address = models.CharField(max_length=100, null=True, blank=True)
collection_name = models.CharField(max_length=100)
def __unicode__(self):
return self.collection_name
class Meta:
db_table = u'collection'
ordering = ('collection_name',)
class Occurrence(models.Model):
id = models.AutoField(primary_key=True, null=True)
reference = models.IntegerField(null=True, blank=True, editable=False)
collection = models.ForeignKey(Collection, null=True, blank=True, unique=True),
modified = models.DateTimeField(null=True, blank=True, auto_now=True)
class Meta:
db_table = u'occurrence'
Every time i go to check the Occurrence object i get this error
TemplateSyntaxError at /admin/hotiapp/occurrence/
Caught an exception while rendering: column occurrence.collection_id does not exist
LINE 1: ...LECT "occurrence"."id", "occurrence"."reference", "occurrenc..
And every time i try to add a new occurrence object i get this error
ProgrammingError at /admin/hotiapp/occurrence/add/
column occurrence.collection_id does not exist
LINE 1: SELECT (1) AS "a" FROM "occurrence" WHERE "occurrence"."coll...
What am i doing wrong? or how does ForeignKey works?
The problem is that you have not updated your database table definition since adding the ForeignKey. syncdb doesn't do this for you, as the documentation clearly states. You need to update the SQL manually, or use a tool like South.
Are you sure you mean
collection = models.ForeignKey(Collection, null=True, blank=True, unique=True),
Nullable and Unique? This may not be possible in some databases.
Generally, the unique constraint doesn't seem to make much sense here.
Are you trying to force a 1-to-1 relationship? Use the OneToOneField. http://docs.djangoproject.com/en/1.1/ref/models/fields/#django.db.models.OneToOneField