How to relate multiple same models related_name in django - django

I have two models Movie and Actor:
class Actor(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
name = models.CharField(name="name", max_length=2000, blank=True, null=True)
class Movie(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
name = models.CharField(name="name", max_length=2000, blank=True, null=True)
actors = models.ManyToManyField(Actor, related_name='movie_actor')
Now I would like to let the users to add their favourite actors like:
class MyUser(AbstractUser):
actors = models.ManyToManyField(Actor, related_name='user_actor')
Now, I would like to make the response for each movie so that the movie can tell that this movie has one/more of their favourite actors or not.

To tell if a movie has one or more favorite actors of a given user:
has_favorite_actors = movie.actors.filter(user_actor=user).exists()

You can simply filter the Actor objects by the two parameters to get all actors in your_movie that are favored by your_user.
Actor.objects.filter(movie_actor = your_movie, user_actor = your_user)
If you just want to check if favored actors exist, add the exists() method.
Actor.objects.filter(movie_actor = your_movie, user_actor = your_user).exists()

Related

django model to yeild specific HTML output without redundancy in the model

I have 3 models (supervisor, students, and allocation)
I am building an allocation system where multiple students can be allocated to one supervisor
Now I want my model to be able to yeld this output
Example of how i want the output to come out
Here are the structure of my model
class StudentProfile(models.Model):
stud_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True)
user_id = models.OneToOneField(User,blank=True, null=True, on_delete=models.CASCADE)
programme_id = models.ForeignKey(Programme, on_delete=models.CASCADE)
session_id = models.ForeignKey(Sessi`**enter code here**`on, on_delete=models.CASCADE)
type_id = models.ForeignKey(StudentType, on_delete=models.CASCADE)
dept_id = models.ForeignKey(Department, on_delete=models.CASCADE)
class SupervisorProfile(models.Model):
super_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True)
user_id = models.ForeignKey(User, on_delete=models.CASCADE)
dept_id = models.ForeignKey(Department, on_delete=models.CASCADE)
class Allocate(models.Model):
allocate_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True)
stud_id = models.ForeignKey(StudentProfile, on_delete=models.CASCADE)
super_id = models.ForeignKey(SupervisorProfile, on_delete=models.CASCADE)
now my main focus is the Allocate model where the allocation is made, and there is a lot of redundancy any suggestions on how to improve my model to remove redundancy in yielding the expected HTML output would be appreciated 🙏
As far as I understand, you need to assign several students to one Supervisor
For this, you only need to use ForeignKey in class StudentProfile
As below:
supervisor=models.ForeignKey(Supervisor,on_delete=models.DO_NOTHING)
But if you need to connect a student to several Supervisor, you should use ManyToManyField
ManyToManyField automatically creates a third table like class Allocate of yourself
For more information, refer to the hire.
It is also possible to reduce the redundancy by considering the department.
However
It doesn't seem that less redundancy can be found in sql database
I hope it was useful

Having trouble linking two fields with one another, then implementing them to another model

I'm working on a project which helps users find jobs.
So one of the models, named Oferta is used for details about a job. Someone who is looking for emplooyes, just completes a form which is based on this model, and people will be looking at it.
Here's this model:
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
cor = models.CharField(max_length=50)
dataSolicitare = models.DateField(default=date.today)
denumireMeserie = models.CharField(max_length=50)
locuri = models.IntegerField()
agentEconomic = models.CharField(max_length=50)
adresa = models.CharField(max_length=150)
dataExpirare = models.DateField()
experientaSolicitata = models.CharField(max_length=200)
studiiSolicitate = models.CharField(max_length=200)
judet = models.CharField(max_length=20)
localitate = models.CharField(max_length=25)
telefon = models.CharField(max_length=12)
emailContact = models.EmailField(max_length=40)
rezolvata = models.BooleanField(default=False)
def __str__(self):
return self.cor
The COR field is the code asociated to a job. Also, denumireMeserie means job name.
So these should be linked. Let's say, if code 1 means "Cook", these should be link - there will be no other job with a different code, or another job for code 1.
So, in my opinion, these two fields should have a OneToOne relationship between them, if I'm not mistaken.
But these codes and jobs need to be implemented in the database - so they need a model too.
class CORMeserii(models.Model):
CodCOR = models.CharField(max_length=25, primary_key=True, unique=True)
MeserieCor = models.OneToOneField(CodCOR, max_length=50, unique=True, on_delete=models.CASCADE)
And here is how I tried to do it, but obviously it won't work, because onetoonefield needs a model as the first parameter.
So, my questions are:
How can I link these two fields as I told you, and then link Oferta.cor to CORMeserii.CodCOR and Oferta.denumireMeserie to CORMeserii.MeserieCor?
(because each job with its code and name should be implemented in the database, then chosen in each Oferta (which means offer))
As Dirk pointed out on your previous question, you have not understood what relationship fields do in Django.
A ForeignKey or a OneToOneField gives you access to the entire related object. This means you can access any of the fields on that related object.
So your Oferta model does not need a denumireMeserie field; that belongs on the other model, which we might call "Job". Oferta has a link to that model, ie a ForeignKey:
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
job = models.ForeignKey('Job', on_delete=models.CASCADE)
and Job has the details of the job:
class Job(models.Model):
cor = models.CharField(max_length=50)
denumireMeserie = models.CharField(max_length=50)
Now you can create a Job and an Oferta for that job:
my_job = Job.objects.create(cor=1, denumireMeserie='Cook')
my_oferta = Job.objects.create(job=my_job, ...rest of the fields...)
Now you can access the job name via the relationship:
print(my_oferta.job.denumireMeserie)
which will give you "Cook".

Django : pre selection or tags. model relations

Django Version is 2.1.7
Hello, i have a OneToMany Relation and i ask my self if there is a possibility to make some kind of pre-selection (Tags or so?) for my Farmers?
Because not every Farmer has or wants Chickens or he is specialist in Cows only.
Means, right now, whenever i want to assign an individual Animal to a Farmer, i see all Farmers displayed in my Django Admin. With a growing Number of Farmers it gets confusing. So i thought to insert some Kind of Model Field in my Farmers Model... like chickens = true or not true and cows = true or not true or to introduce a new model for every species.
My Goal is, to assign a set of species to a every farmer. So that the Next time i want to add a chicken django shows only Farmers that will work with Chickens on their Farmland, it makes no sense to Display all Farmers, when some Farmers know that they handel only a specific set of species.
As a Newbie i would guess i have to make some new models for every Species with a ManyToMany Relation? So Farmers >< Species X, Y, Z < Indiviual Anmial.
Thanks
class Farmers(models.Model):
name = models.CharField(max_length=100)
farm_img = models.ImageField(upload_to='farm/', max_length=255, null=True, blank=True)
slug_farm = models.SlugField(blank=True)
<...>
class Chickens(models.Model):
farmer = models.ForeignKey(Farmers, on_delete=models.CASCADE, null=True)
chickenname = models.CharField(max_length=100)
<...>
class Cows(models.Model):
farmer = models.ForeignKey(Farmers, on_delete=models.CASCADE, null=True)
cowname = models.CharField(max_length=100)
<...>
class Rabbits(models.Model):
farmer = models.ForeignKey(Farmers, on_delete=models.CASCADE, null=True)
cowname = models.CharField(max_length=100)
<...>
If we are using postgres as DB then arrayFieldlink
can be a good option for doing this job.
from django.contrib.postgres.fields import ArrayField
class Farmers(models.Model):
.... necessary fields
SAMPLE_CHOICES = (
('CHICKEN', 'CHICKEN'),
('COW, 'COW'),
('No Species', 'No Species')
.....
)
choices = ArrayField(
models.CharField(choices=SAMPLE_CHOICES, max_length=10, blank=True, default='No Species'),
)
Now whenever we need to filter on Farmer model based on choices we can do this like following
Farmer.objects.filter(choices__contains=['cow'])
Update
As you are using django-mysql database, following thing by django-mysql link here we can have field feature like ListField link and can easily achieve this.
class ChickenFarmers(models.Model):
name = models.CharField(max_length=100)
farm_img = models.ImageField(upload_to='farm/', max_length=255, null=True, blank=True)
slug_farm = models.SlugField(blank=True)
class CowFarmers(models.Model):
name = models.CharField(max_length=100)
farm_img = models.ImageField(upload_to='farm/', max_length=255, null=True, blank=True)
slug_farm = models.SlugField(blank=True)
class RabbitsFarmers(models.Model):
name = models.CharField(max_length=100)
farm_img = models.ImageField(upload_to='farm/', max_length=255, null=True, blank=True)
slug_farm = models.SlugField(blank=True)
class Chickens(models.Model):
farmer = models.ForeignKey(ChickenFarmers, on_delete=models.CASCADE, null=True)
chickenname = models.CharField(max_length=100)
class Cows(models.Model):
farmer = models.ForeignKey(CowFarmers, on_delete=models.CASCADE, null=True)
cowname = models.CharField(max_length=100)
class Rabbits(models.Model):
farmer = models.ForeignKey(RabbitsFarmers, on_delete=models.CASCADE, null=True)
cowname = models.CharField(max_length=100)
'''
I think at this point this will give you best relief
'''

How to use two unique constraints in Django model?

I have a Django model for a player of a game
class Player(models.Model):
name = models.CharField(max_length=50)
team = models.ForeignKey('Team', on_delete=models.CASCADE, blank=True, null=True)
game = models.ForeignKey('Game', on_delete=models.CASCADE)
objects = GameManager()
class Meta:
unique_together = ('name', 'game',)
I have only one unique constraint, that the name and the game are unique together.
Now, I would like to extend our page by adding registered users. So, I would add this to the model.
user = models.ForeignKey('auth.User', on_delete=models.CASCADE, blank=True, null=True)
So, an registered user can subscribe to a game by adding a name, team, game, and his/her user. However, the user should only be able to add his account once to an game, which would be a second unique constrain
unique_together = ('user', 'game',)
Is it possible to give in Django two unique constraints to the model? Or do I have to search in the table manually prior to saving the new entries? Or is there a better way?
Yes, in fact by default unique_together is a collection of collections of fields that are unique together, so something like:
class Player(models.Model):
name = models.CharField(max_length=50)
team = models.ForeignKey('Team', on_delete=models.CASCADE, blank=True, null=True)
game = models.ForeignKey('Game', on_delete=models.CASCADE)
objects = GameManager()
class Meta:
unique_together = (('name', 'game',), ('user', 'game',))
Here we thus specify that every name, game pair is unique, and every user, game pair is unique. So it is impossible to create two Player objects for the same user and game, or for the same game and name.
It is only because a single unique_together constraint is quite common, that one can also pass a single collection of field names that should be unique together, as is written in the documentation on Options.unique_together [Django-doc]:
Sets of field names that, taken together, must be unique:
unique_together = (("driver", "restaurant"),)
This is a tuple of tuples that must be unique when considered
together. It's used in the Django admin and is enforced at the
database level (i.e., the appropriate UNIQUE statements are included
in the CREATE TABLE statement).
For convenience, unique_together can be a single tuple when dealing with a single set of fields:
unique_together = ("driver", "restaurant")
You should use models.UniqueConstraint (reference).
As noted in the reference:
UniqueConstraint provides more functionality than unique_together. unique_together may be deprecated in the future.
Do this:
class Meta:
constraints = [
models.UniqueConstraint(fields=['name', 'game'], name="unique_name_game"),
models.UniqueConstraint(fields=['user', 'game'], name="unique_user_game"),
]
For example please refer to this :-
class Stores(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=50)
lat = models.FloatField()
lng = models.FloatField()
merchant = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name="stores")
def __str__(self):
return "{}: {}".format(self.name, self.address)
class Meta:
verbose_name_plural = 'Stores'
class Items(models.Model):
name = models.CharField(max_length=50, unique=False)
price = models.IntegerField()
description = models.TextField()
stores = models.ForeignKey(Stores, on_delete=models.CASCADE, related_name="items")
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "Items"
unique_together = ('name', 'stores',)

constructing a joined django query

I'm interacting with a legacy db on another system, so the models are written in stone and not very django-ey.
My models.py:
class Site(models.Model):
site_code = models.CharField(max_length=30, primary_key=True)
name = models.CharField(unique=True, max_length=300)
class Document(models.Model):
id = models.IntegerField(primary_key=True)
site_ref = models.ForeignKey(Site)
description = models.CharField(max_length=1500)
class DocumentStatusCategory(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(unique=True, max_length=90)
class DocumentStatus(models.Model):
id = models.IntegerField(primary_key=True)
document = models.ForeignKey(Document)
status = models.ForeignKey(DocumentStatusCategory)
changed_by = models.ForeignKey(User)
created_at = models.DateTimeField()
In my views.py I want to retrieve a queryset with all the Document objects that belong to a specified Site (say site_ref=mysite) which do not have any related DocumentStatus objects with status=4.
Any idea how I can do this as a single (non-sql intensive) line?
Document.objects.filter(site_ref=mysite).exclude(documentstatus__status_id=4)
Document.objects.filter(site_ref=site_obj).exclude(documentstatus_set__in=DocumentStatus.objects.filter(status_id=4))
Not exactly one query, but I don't think that's achievable without going down to raw sql. Two queries isn't bad though I suppose.
I should mention that the above assumes that the reverse relation between Document and DocumentStatus is documentstatus_set. You can explicitly state what the reverse relation is like so:
# inside the DocumentStatus model definition
document = models.ForeignKey(Document, related_name='document_statuses')
Then the query becomes:
Document.objects.filter(site_ref=site_obj).exclude(document_statuses__in=DocumentStatus.objects.filter(status_id=4))