Django error with models (ManyToManyField) - django

I was building my app using django but I got this error in the models.py file:
creator = models.ManyToManyField(Teacher, on_delete=models.CASCADE)
NameError: name 'Teacher' is not defined
This is my current code in models.py:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class School(models.Model):
nombre = models.CharField(max_length=355)
profesoras = models.ManyToManyField(Teacher)
class Teacher(models.Model):
user = models.ForeignKey(User, related_name="teacherClass", blank=False)
school = models.ManyToManyField(School, blank=True)
class Post(models.Model):
creator = models.ManyToManyField(Teacher, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
text = models.TextField(max_length=2000)
Do you know how can I solve this error?

The issue here is that you are trying to reference a model that has not been created yet. The Django docs state what to do in such a case.
If you need to create a relationship on a model that has not yet been
defined, you can use the name of the model, rather than the model
object itself:
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
So for your case, you would just change your model relationships to strings.
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class School(models.Model):
nombre = models.CharField(max_length=355)
profesoras = models.ManyToManyField("Teacher") # Make this a string because it has not been defined yet
class Teacher(models.Model):
user = models.ForeignKey(User, related_name="teacherClass", blank=False)
school = models.ManyToManyField(School, blank=True)
class Post(models.Model):
creator = models.ManyToManyField("Teacher", on_delete=models.CASCADE) # Same with this one.
title = models.CharField(max_length=255)
text = models.TextField(max_length=2000)
The django docs are always really useful and have a lot of good information.

The error is just fine because you are using it before declaring it and also your relationships are a little messy. You can say that you can have as many schools as you wish in this app and each professor teaches in many schools so it can be something like this by using many to many relation:
class School(models.Model):
name = models.CharField(max_length=355)
class Teacher(models.Model):
user = models.ForeignKey(User, related_name="teacherClass", blank=False, on_delete=models.CASCADE)
school = models.ManyToManyField(School, blank=True)
class Post(models.Model):
creator = models.ManyToManyField(Teacher)
title = models.CharField(max_length=255)
text = models.TextField(max_length=2000)
I suggest you that study a little bit about relations in databases so you won't have any similar problem in future.

Related

How to create relative entry in mongoldb using Django?

I have following Person document model.
from djongo import models
from django.contrib.postgres.fields import ArrayField
class Person(models.Model):
id = models.ObjectIdField()
name = models.CharField(max_length=255)
city = models.CharField(max_length=255)
status = models.CharField(max_length=20)
phone_number = models.CharField(max_length=20)
objects = models.DjongoManager()
And the following Comment model
class Comment:
id = models.OneToOneField(
Person,
on_delete=models.CASCADE,
primary_key=True,
)
comments = ArrayField(models.CharField())
objects = models.DjongoManager()
When I create a document in Person object, I want mongo automatically create a document in Comment model with the same id but empty comments. I thought declaring OneToOneField filed will do it, but it didn't. What should I do?

Django ORM - model referencing another models ManyToMany field

I'm currently trying to setup some database models in djangos ORM. however im unable to figure out how i'm supposed to reference another models many-to-many- field.
Project model
class Project(models.Model):
projectName = models.CharField(max_length=200)
users = models.ManyToManyField(get_user_model())
projectOwner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='projectowner', default=1)
The users = models.manytomanyfield(get_user_mode()) works fine
and generates the correct relation in the database.
now i want to add a new model that adds a many to many relation between rights and project_user
so what the end result tables are supposed to look like:
project:
projectname - string
projectowner - id of referenced user
user: django orm auth user model
rights:
name
description
etc
project_user:
id
project_id
user_id
rights_projectuser:
id
rights_id
project_user_id
now that last one (rights_projectuser) is what i dont know how to make.
You need to turn "project_user" into a through model that you can then add the many to many relationship to.
class Project(models.Model):
projectName = models.CharField(max_length=200)
users = models.ManyToManyField(get_user_model(), through='ProjectUser')
class ProjectUser(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
rights = models.ManyToManyField(Right)
i now get the following problem when running this code:
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Project(models.Model):
projectName = models.CharField(max_length=200)
users = models.ManyToManyField(get_user_model(), through='ProjectUser')
projectOwner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='projectowner', default=1)
class Right(models.Model):
name = models.CharField(max_length=200)
description = models.CharField(max_length=1000)
class ProjectUser(models.Model):
user_id = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
project_id = models.ForeignKey(Project, on_delete=models.CASCADE)
rights = models.ManyToManyField(Right)
ValueError: Cannot alter field wspingpong.Project.users into wspingpong.Project.users - they are not compatible types (you cannot alter to or from M2M fields, or add or remove through= on M2M fields)

What is the process that you follow to create model in Django?

What is the process that you follow to create model in Django? Thanks.
The most important part of a model – and the only required part of a model – is the list of database fields it defines. Fields are specified by class attributes. Be careful not to choose field names that conflict with the models API like clean, save, or delete.
Models.py
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
You can start here Documentation
See also Django Girls Models

Django: need help in designing relationships between models

I have an app which allows to associate to each client multiple boards, boards where I can upload files relevant for the client to make decisions about how the website page in question will look.
So the relationships I need to model are:
one client, multiple boards;
one board, one client;
one board, multiple files;
Let's concentrate on the first two
models.py
class Board(models.Model):
title = models.CharField(max_length=120, verbose_name="Titolo")
description = models.TextField()
files = models.FileField( null=True, blank=True, upload_to = 'clients_download_area', verbose_name = 'Client Reserved File')
date = models.DateTimeField(auto_now_add=True, verbose_name = 'Data di pubblicazione')
def __str__(self):
return str(self.title)
class Client(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=120)
boards = models.ManyToManyField(Board, blank=True)
def __str__(self):
return str(self.name)
Ok, relationship #1 is done. But what if I need to know which client is associated to a board (relationship #2)?
If I set a new field to Board Class
class Board(models.Model):
[...]
client = models.ForeignKey(Client, blank = True)
of course, when I makemigrations Django complains because it does not know what Client is, since I define it in the next model.
How can I design this DB?
Thank you in advance for any help you could provide
The problem here is that you reference to an identifer (here Client), before it is constructed (since Board is defined before the Client class).
Django has some support for this: you can pass strings that contain the name of the model. In the same app, you can just use ClassName, for another app, you can use other_app.ClassName, like the documentation says:
If you need to create a relationship on a model that has not yet been defined, you can use the name of the model, rather than the model
object itself:
from django.db import models
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
So here you can write it like:
class Board(models.Model):
title = models.CharField(max_length=120, verbose_name="Titolo")
description = models.TextField()
files = models.FileField( null=True, blank=True, upload_to = 'clients_download_area', verbose_name = 'Client Reserved File')
date = models.DateTimeField(auto_now_add=True, verbose_name = 'Data di pubblicazione')
client = models.ForeignKey(
'Client',
related_name='my_boards'
on_delete=models.CASCADE
)
def __str__(self):
return str(self.title)
class Client(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=120)
boards = models.ManyToManyField(Board, blank=True)
def __str__(self):
return str(self.name)
Note however that you already defined a ManyToManyField relation from Client to Board. Although it is possible it is not very common that two such relations exists simultaneously.
If you define a ForeignKey relationship from Board to Client, then Django automatically creates a reverse relationship (with the related_name), such that some_client.my_boards, is a manager of all the related Boards.
I think you can pass model class name instead of the class itself:
class Board(models.Model):
[...]
client_id = models.ForeignKey('Client', blank=True)

Django 1.11 many to many does not appear in django admin

Hi i have a django model for notification which have a many-to-many relation but nothing appears in django admin ( all fields do not appear)
class Notification(models.Model):
"""send notification model"""
title = models.CharField(max_length=200)
text = models.TextField(null=True, blank=True)
device = models.ManyToManyField(Device, null=True, blank=True)
country = models.ManyToManyField(Country, null=True, blank=True)
sent = models.BooleanField(default=False)
when i open django admin for this model and press add notification this is what happens (nothing appears)
Country and Device Code
class Device(models.Model):
"""Store device related to :model:`accounts.User`."""
user = models.OneToOneField(User, related_name='device', on_delete=models.CASCADE)
model = models.CharField(max_length=200, blank=True, null=True)
player_id = models.CharField(max_length=200, blank=True, null=True)
class Meta:
verbose_name = 'Device'
verbose_name_plural = 'Devices'
def __str__(self):
return self.model
class Country(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
Admin.py
from django.contrib import admin
from .models import Notification
admin.site.register(Notification)
Edit:
Thank you all the problem is solved
The problem was caused by some entries in device model that did have None in the model field so there was a problem displaying it correctly.
According to https://code.djangoproject.com/ticket/2169 :
When a class has a field that isn't shown in the admin interface but
must not be blank, it's impossible to add a new one. You get a cryptic
"Please correct the error below." message with no shown errors. The
error message should probably say something about a hidden field.
Now ManyToManyFields don't need null=True, try removing those statements and see if you get an improvement.
Also, try adding the Country and Device models in admin.py so admin can see them and display them.
https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#working-with-many-to-many-models
Define an inline for the many-to-manys in admin.py:
from django.contrib import admin
class DeviceInline(admin.TabularInline):
model = Notification.device.through
class CountryInline(admin.TabularInline):
model = Notification.country.through
class NotificationAdmin(admin.ModelAdmin):
inlines = [
DeviceInline, CountryInline
]
exclude = ("device", "country")