Reputation: 8648
I have the following models:
class PermanentList(models.Model):
permanent_employees = models.ManyToManyField(Employee, through='PermanentMembership')
class EventList(models.Model):
event_employees = models.ManyToManyField(Employee, through='EventMembership')
class Employees(models.Model):
email = models.EmailField()
And the following through models to handle the M2M relationship:
class PermanentMembership(models.Model):
permanent_list = models.ForeignKey(PermanentList, null=True, on_delete=models.PROTECT)
permanent_employees = models.ForeignKey(Employee,null=True, on_delete=models.PROTECT)
class Meta:
constraints = [models.UniqueConstraint(
fields=['permanent_list', 'permanent_employees'],
name="unique_event_list_employees")]
class EventMembership(models.Model):
event_list = models.ForeignKey(EventList, null=True, on_delete=models.PROTECT)
event_employees = models.ForeignKey(Employee,null=True, on_delete=models.PROTECT)
def clean(self):
// missing code
class Meta:
constraints = [models.UniqueConstraint(
fields=['event_list', 'event_employees'],
name="unique_event_list_employees")]
EDITS:
- Each
Employee
can only be in 1EventList
or 1PermanentList
EventList
andPermanentList
are completely separate models, only sharingEmployees
. They can't be combined and managed as one list.
2 Questions:
event_employee
using def clean(self):
to ensure that if an Employee
is already on a PermanentList
they can not be added to a EventList
?Employee
is already on an EventList
how can I create a function to transfer them to a PermanentList
? Can this be done on a Model
class or would it have to be in a View
? How would I go about this?Upvotes: 0
Views: 101
Reputation: 16072
IIUC:
class EventMembership(models.Model):
...
def clean(self):
if PermanentMembership.objects.filter(
permanent_employees__id=self.event_employees.id
).exists():
raise ValidationError("Employee in PermanentList")
As for the second question, you could create an insert signal on PermanentMembership
that checks if the employee is in EventMembership
, and if it is, then delete it:
from django.db.models.signals import post_save
from django.dispatch import receiver
class PermanentMembership(models.Model):
...
@reciever(post_save, sender=PermanentMembership)
def handler(sender, **kwargs):
try:
event_employee = EventMembership.objects.get(id=sender.id)
event_employee.delete()
except EventMembership.DoesNotExist:
pass
Unfortunately, this will hinder performance a bit, since you will have to query the PermanentMembership
each time you insert on EventMembership
. To circumvent this I would cache a list of employee ids that are in PermanentMembership
, and update that list after each insert.
That being said, I would encourage you to reconsider your database design, because something seems out of place (with the limited info I have on the situation, at least). I could be completely wrong though, it really depends on the details.
Upvotes: 1
Reputation: 32314
Take this potential model layout for example, each Employee
can only be assigned to 1 Job
and can only be either PERMANENT
or EVENT
. What's wrong with having this layout?
from django.db import models
PERMANENT = 'PERMANENT'
EVENT = 'EVENT'
class Job(models.Model):
name = models.CharField(max_length=100)
@property
def permanent_list(self):
return self.employees.filter(type=PERMANENT)
@property
def event_list(self):
return self.employees.filter(type=EVENT)
class Employee(models.Model):
EMPLOYMENT_TYPES = (
(PERMANENT, 'Permanent'),
(EVENT, 'Event'),
)
email = models.EmailField()
job = models.ForeignKey(Job, on_delete=models.PROTECT, related_name='employees')
type = models.CharField(max_length=100, choices=EMPLOYMENT_TYPES)
Upvotes: 0