Django ORM - model referencing another models ManyToMany field - django

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)

Related

Django error with models (ManyToManyField)

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.

How to automatically create an object for a model in Django, if it doesn't exist?

I have two models. One is for UserProfile and the other is for Company.
class UserProfile(models.Model):
company_name = models.ForeignKey(Company, on_delete = models.CASCADE, related_name = 'company')
class Company(models.Model):
name = models.CharField(max_length = 100)
I am using Django Rest Framework for user creation. What I want to achieve is when I create a new user, I want to assign a company_name to that user. And if that company_name is not present in the db, then I want to create it on the go. But it is throwing an error. "Invalid hyperlink - No URL match."
You can use python's #property to tackle this problem in a clean and simple way. It works well for creating and for updating the object aswell. Note that the UserPorifle's field is renamed to company. Here is how you do it:
class Company(models.Model):
name = models.CharField(max_length=100)
class UserProfile(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='company')
#property
def company_name(self):
return self.company.name
#company_name.setter
def company_name(self, value):
self.company, _ = Company.objects.get_or_create(name=value)
Now you can create objects using:
UserProfile.objects.create(company_name='Some name')
First you need to link your UserProfile Model with the user. It should be a OnetoOne Relationship because a User should only have one company I guess.
In your serializer you should add in the Company model and save the company name from the input in the API and then connect it to the new user that is being created.

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

Can't use the extended User model

I want to add a department field on my User model. I am using sql server as my db. I did the following in models.py
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, db_column='user')
department = models.CharField(max_length=20, blank=True)
class Meta:
db_table = 'Employee'
Then, using stored procedure I can fill all the fields of User easily, but when I want to fill the extra field department, I get the error
RelatedObjectDoesNotExist at /fetched
User has no employee.
in views.py, where I retrieve the data from procedure:
q = User(id=result_set[i][0], username=result_set[i][1], is_staff=False,
first_name=result_set[i][4], last_name=result_set[i][3], email=result_set[i][8])
q.set_password(result_set[i][2])
q.employee.department = 'something'
q.save()
You can extend the AbstractUser to your model
In models.py
from django.contrib.auth.models import AbstractUser
class Employee(AbstractUser):
department = models.CharField(max_length=20, blank=True)

Get all related field in Django model

I am struggling to understand how one-to-many and many-to-many relation works in Django model. My schema looks something like this so far, I am open for suggestions to make it better.
A many-to-many relation between users and team. Also, there will be schedules that belong to a particular user of a team.
This is how my model looks like so far,
class Team(models.Model):
tid = models.AutoField(primary_key=True)
team_name = models.CharField(max_length=30)
manager_name = models.CharField(max_length=30)
class Schedule(models.Model):
sid = models.AutoField(primary_key=True)
user = models.OneToOneField(User)
date = models.DateField()
start_time = models.TimeField()
end_time = models.TimeField()
pay_rate = models.CharField(max_length=30)
location = models.CharField(max_length=50)
class BelongsTo(models.Model):
bid = models.AutoField(primary_key=True)
user = models.OneToOneField(User)
team = models.ForeignKey(Team, on_delete=models.CASCADE)
schedule = models.ForeignKey(Schedule, on_delete=models.CASCADE)
Question: I want to get the information of each user, what are their schedules and which team each schedule belongs to. How would I to do it? I have tried BelongsTo.objects.select_related().all(), but it is not working for me.
Note: I am open for suggestions, if something is wrong with my schema or model or the approach, please let me know.
BelongsTo is seems like utility table.So
BelongsTo.objects.all().values('user', 'team__team_name', 'schedule')
Your schema looks almost right, but I would modify it a little bit. In particular, I will change how Schedule is implemented. Instead of having a sid in the User Belongs To join-table, I would include the user and team in the Schedule table as foreign keys.
This is how the Django models should then look like:
class User(models.Model):
username = models.CharField(max_length = 200)
# put other fields like password etc. here
class Team(models.Model):
team_name = models.CharField(max_length=30)
manager_name = models.CharField(max_length=30)
user = models.ManyToManyField("User")
class Schedule(models.Model):
user = models.ForeignKey("User")
team = models.ForeignKey("Team")
date = models.DateField()
start_time = models.TimeField()
end_time = models.TimeField()
pay_rate = models.CharField(max_length=30)
location = models.CharField(max_length=50)
Note the following:
You don't need to have a primary key field in the models because Django adds a primary key field called pk or id automatically.
Note the absence of the User Belongs To model. Django implements join-tables like User Belongs To automatically when you use a ManyToManyField. See the Django docs on many-to-many relationships.
You also don't need on_delete = models.CASCADE on ForeignKey fields, because this is the default behavior.
To see how to get information about users, teams and schedule from this configuration of models, consult the Django documentation on making db queries. It's quite easy.