Django: error while trying to access ManyToMany field - django

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
)

Related

AttributeError: 'str' object has no attribute '_meta' when attempting to use Many to Many field on self with through model - Django

Django version - 4.0.4
I am making a recipe engine website and I am trying to create a table Ingredient where each ingredient may have substitutable ingredients.
For example, ingredient "acorn squash" has the following substituable ingredients:
ingredient title: butternut squash. Conversion: 1 cup acorn squash = 1 cup butternut squash
ingredient title: pumpkin. Conversion: 1 cup acorn squash = 1 cup pumpkin
To achieve this, I have a class Ingredient and a class SubstitutableIngredient in models.py. I use a many to many field in Ingredient which uses "through" to link to the SubstitutableIngredient table, as I have extra fields such as "conversion". I use 'self' as a substitutable ingredient is still an ingredient. When attempting to makemigrations or migrate, I get the following error: AttributeError: 'str' object has no attribute '_meta' when attempting to makemigrations or migrate. Stack trace shown further below.
My code in Models.py is:
from django.db import models
# Create your models here.
class Ingredient(models.Model):
title = models.CharField(max_length=200,
unique=True) # unique field. There may only be one ingredient in the database with the same title.
# many to many field
substitutableIngredients = models.ManyToManyField(
'self',
through='SubstitutableIngredient',
through_fields=('originalIngredient', 'newIngredient'),
)
def __str__(self):
return self.title
class SubstitutableIngredient:
originalIngredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE, related_name="originalIngredient")
newIngredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE, related_name="newIngredient")
# the conversion rules between the ingredients (e.g. 1 cup = 2 cups)
conversion = models.CharField(max_length=200)
# A Cuisine has a title which is unique.
class Cuisine(models.Model):
title = models.CharField(max_length=200, unique=True)
def __str__(self):
return self.title
# recipe class inherits from Model
class Recipe(models.Model):
# attributes
title = models.CharField(max_length=200)
# every Recipe can have many ingredients and each ingredient can have many recipes.
# relationship is modelled by the IngredientInRecipe model.
ingredients = models.ManyToManyField(
Ingredient,
through='IngredientInRecipe',
through_fields=('recipe', 'ingredient')
)
instructions = models.TextField(blank=True, null=True)
vegetarian = models.BooleanField(blank=True, null=True)
vegan = models.BooleanField(blank=True, null=True)
glutenFree = models.BooleanField(blank=True, null=True)
dairyFree = models.BooleanField(blank=True, null=True)
sourceUrl = models.CharField(max_length=200, blank=True, null=True)
image = models.CharField(max_length=200, blank=True, null=True)
cuisines = models.ManyToManyField(Cuisine, blank=True, null=True)
def __str__(self):
return self.title
# Intermediary class working between Recipe and Ingredient.
class IngredientInRecipe(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
unit = models.CharField(max_length=200)
quantity = models.FloatField()
def __str__(self):
return self.recipe.title + "," + self.ingredient.title
Strack trace:
C:\[pathname]>python manage.py makemigrations
Traceback (most recent call last):
File "C:[pathname]\manage.py", line 22, in <module>
main()
File "C:[pathname]\manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "C:\Users\[pathname]\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\__init__.py", line 446, in execute_from_command_line
utility.execute()
File "C:\Users\[pathname]\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\__init__.py", line 440, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Users\[pathname]\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\base.py", line 414, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Users\[pathname]\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\base.py", line 455, in execute
self.check()
File "C:\Users\[pathname]\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\base.py", line 487, in check
all_issues = checks.run_checks(
File "C:\Users\[pathname]\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\checks\registry.py", line 88, in run_checks
new_errors = check(app_configs=app_configs, databases=databases)
File "C:\Users\[pathname]\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\checks\model_checks.py", line 36, in check_all_models
errors.extend(model.check(**kwargs))
File "C:\Users\[pathname]\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 1442, in check
*cls._check_fields(**kwargs),
File "C:\Users\[pathname]\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 1556, in _check_fields
errors.extend(field.check(from_model=cls, **kwargs))
File "C:\[pathname]\lesle\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\fields\related.py", line 1376, in check
*self._check_relationship_model(**kwargs),
File "C:\Users\[pathname]\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\fields\related.py", line 1603, in _check_relationship_model
for f in through._meta.fields:
AttributeError: 'str' object has no attribute '_meta'
I'm very confused because the following code, which is almost identical to mine, works perfectly fine.
Example code:
# Create your models here.
class Person(models.Model):
name = models.CharField(max_length=50)
# note the additional arguments here
friends = models.ManyToManyField(
'self',
# recursive relationships to self with intermediary
# through model are always defined as non-symmetrical
# symmetrical=False,
through='PersonFriend',
# this argument is required to define a custom
# through model for many to many relationship to self
# position matters: 1 - source (from), 2 - target (to)
through_fields=('person', 'friend'),
)
class PersonFriend(models.Model):
# required relationship-defining foreign keys
# (note that the order does not matter, it matters
# in 'through_fields' argument in 'friends' field of the 'Person' model)
person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name="person")
friend = models.ForeignKey(Person, on_delete=models.CASCADE, related_name="friend")
# additional fields
comment = models.CharField(max_length=50)
What I've already tried:
Deleting the database and migrations files
changing to through=main.SubstituableIngredient as suggested in Django many-to-many 'str' object has no attribute '_meta' does not help

Strange module behavior djangoql

We use djangoql for easy search in our django admin panel.
The mixin DjangoQLSearchMixin has been added to some of our models in the admin panel.
And sometimes after deployment we get an error in the handler
application_name/model_name/introspect/
Error:
FieldDoesNotExist at /admin/user/user/introspect/
Model_name has no field named 'field_name'
After the reboot, the error disappears. The error cannot be reproduced locally.
Example:
"Address has no field named 'membership_requests'"
#admin.register(MembershipRequest, site=admin_site)
class MembershipRequestAdmin(DjangoQLSearchMixin, admin.ModelAdmin):
list_display = ("company", "user", "request_type", "status", "created_on", "updated_on")
class MembershipRequest(PureModelMixin):
company = models.ForeignKey("constrafor.Company", on_delete=models.CASCADE, related_name="membership_requests")
user = models.ForeignKey("user.User", on_delete=models.CASCADE, related_name="membership_requests")
address = models.OneToOneField(
"constrafor.Address",
related_name="membership_requests",
on_delete=models.CASCADE,
null=True,
blank=True,
help_text="FK to constrafor.Address",
)
code = models.ForeignKey(
"constrafor.Code", on_delete=models.SET_NULL, related_name="membership_requests", blank=True, null=True
)
company_name = models.CharField(null=True, blank=True, max_length=1000)
company_phone = models.CharField(null=True, blank=True, max_length=15)
company_type = models.CharField(max_length=15, choices=Company.COMPANY_TYPE_CHOICES)
is_needed_email_verification = models.BooleanField(default=False)
status = models.CharField(
max_length=8,
choices=MembershipRequestStatus.choices,
default=MembershipRequestStatus.pending,
)
request_type = models.CharField(
max_length=10,
choices=MembershipRequestType.choices,
default=MembershipRequestType.natural,
)
As I remarked in an earlier comment on your question, this seems to be a very tricky heisenbug. Not being able to properly debug it, as it cannot be reproduced, I found a way around it:
class CustomDjangoQLSchema(DjangoQLSchema):
def get_field_instance(self, model, field_name):
"""Some obscure heisenbug caused introspect requests to raise, rendering DjangoQL useless.`
This catch the exception and just skip the problematic field.
"""
try:
return super().get_field_instance(model, field_name)
except FieldDoesNotExist:
return None
If you use this Schema instead of the default you should be able to skip those failing fields.
UPDATE: Later I found out that the model that caused trouble was not registered with Django properly. It makes sense that a model that is not imported in models.__init__ but that does have a referral causes unexpected behaviour like this.

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/

Foreign key to get column from another model - 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)

Cannot run django server after integrating database

I am having problems running my server after I try to integrate the database with the application using the "python manage.py inspectdb > /models.py" command.
This is what I have in my models.py file
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
# * Rearrange models' order
# * Make sure each model has one field with primary_key=True
# Feel free to rename the models, but don't rename db_table values or field names.
#
# Also note: You'll have to insert the output of 'django-admin.py sqlcustom [appname]'
# into your database.
from __future__ import unicode_literals
from django.db import models
class AuthGroup(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=80)
class Meta:
db_table = 'auth_group'
class AuthGroupPermissions(models.Model):
id = models.IntegerField(primary_key=True)
group = models.ForeignKey(AuthGroup)
permission = models.ForeignKey('AuthPermission')
class Meta:
db_table = 'auth_group_permissions'
class AuthPermission(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
content_type = models.ForeignKey('DjangoContentType')
codename = models.CharField(max_length=100)
class Meta:
db_table = 'auth_permission'
class AuthUser(models.Model):
id = models.IntegerField(primary_key=True)
password = models.CharField(max_length=128)
last_login = models.DateTimeField()
is_superuser = models.BooleanField()
username = models.CharField(max_length=30)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.CharField(max_length=75)
is_staff = models.BooleanField()
is_active = models.BooleanField()
date_joined = models.DateTimeField()
class Meta:
db_table = 'auth_user'
class AuthUserGroups(models.Model):
id = models.IntegerField(primary_key=True)
user = models.ForeignKey(AuthUser)
group = models.ForeignKey(AuthGroup)
class Meta:
db_table = 'auth_user_groups'
class AuthUserUserPermissions(models.Model):
id = models.IntegerField(primary_key=True)
user = models.ForeignKey(AuthUser)
permission = models.ForeignKey(AuthPermission)
class Meta:
db_table = 'auth_user_user_permissions'
class DjangoContentType(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
app_label = models.CharField(max_length=100)
model = models.CharField(max_length=100)
class Meta:
db_table = 'django_content_type'
class DjangoSession(models.Model):
session_key = models.CharField(max_length=40)
session_data = models.TextField()
expire_date = models.DateTimeField()
class Meta:
db_table = 'django_session'
class DjangoSite(models.Model):
id = models.IntegerField(primary_key=True)
domain = models.CharField(max_length=100)
name = models.CharField(max_length=50)
class Meta:
db_table = 'django_site'
class DjangoUser(models.Model):
firstname = models.CharField(max_length=256)
lastname = models.CharField(max_length=256)
username = models.CharField(primary_key=True, max_length=256)
password = models.CharField(max_length=256)
class Meta:
db_table = 'django_user'
and this is the error message I get
Unhandled exception in thread started by <bound method Command.inner_run of <django.contrib.staticfiles.management.comma
nds.runserver.Command object at 0x0000000002CD1518>>
Traceback (most recent call last):
File "C:\Python33\lib\site-packages\django\core\management\commands\runserver.py", line 92, in inner_run
self.validate(display_num_errors=True)
File "C:\Python33\lib\site-packages\django\core\management\base.py", line 280, in validate
num_errors = get_validation_errors(s, app)
File "C:\Python33\lib\site-packages\django\core\management\validation.py", line 35, in get_validation_errors
for (app_name, error) in get_app_errors().items():
File "C:\Python33\lib\site-packages\django\db\models\loading.py", line 166, in get_app_errors
self._populate()
File "C:\Python33\lib\site-packages\django\db\models\loading.py", line 72, in _populate
self.load_app(app_name, True)
File "C:\Python33\lib\site-packages\django\db\models\loading.py", line 96, in load_app
models = import_module('.models', app_name)
File "C:\Python33\lib\site-packages\django\utils\importlib.py", line 35, in import_module
__import__(name)
TypeError: source code string cannot contain null bytes
It seems I have a null variable some place but I don't know where that is coming from. I would appreciate some help.
I just had this problem myself. I finally fixed it:
open the generated model.py file in Notepad++ (or other)
copy/paste the generated code into a new file in IDLE
Save over model.py
I'm not sure why this works, but I got an encoding error trying to open the file directly in IDLE. So I copy/pasted the code, and it fixes everything.
I had the same problem using Sublime 3 as editor. It got solved if I resaved the models.py file in my app folder as 'Save with Encoding :: UTF-8'.