mcastle
mcastle

Reputation: 3002

Require ForeignKey object to be a related object of another model

I have a model

class EventArticle(models.Model):
    event = models.ForeignKey(Event, related_name='article_event_commentary')
    author = models.ForeignKey(Person)

and another model

class Event(models.Model):
    attendies = models.ManyToManyField(Person, related_name="people")

How do I restrict an author to only objects that are also attendies?

Upvotes: 0

Views: 45

Answers (2)

Jon Combe
Jon Combe

Reputation: 176

Typically, the ForeignKey limit_choices_to argument is your friend in situations like this. (See https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.ForeignKey.limit_choices_to)

You could restrict the author to a list of users of have attended any event. However, even doing that is far from ideal:

# don't try this at home, this will be excruciatingly slow...
def author_options():
    all_attendee_ids = []
    for e in Event.objects.all():
        for a in e.attendies.all():
            all_attendee_ids.append(a.id)
    return {'author': Person.objects.filter(id_in=set(all_attendee_ids)).id}

# requires Django 1.7+
class EventArticle(models.Model):
    event = models.ForeignKey(Event, related_name='article_event_commentary')
    author = models.ForeignKey(Person, limit_choices_to=author_options)

However, even though you didn't explicitly state it in your question, I suspect you want authors to be limited to a set of attendees from that particular event, i.e. the same event as specified in the EventArticle model's event field.

In which case, this brings about two problems which I don't believe can be solved cleanly:

  1. you can't pass parameters (i.e. the event ID) when using limit_choices_to, and
  2. until the EventArticle model has a value for event, you wouldn't know which event was in question.

As using limit_choices_to isn't going to work here, there probably isn't a way to fix this cleanly. You could add a method to your EventArticle model which will give you a list of potential authors like so...

class EventArticle(models.Model):
    event = models.ForeignKey(Event, related_name='article_event_commentary')
    author = models.ForeignKey(Person)

    def author_options(self):
        if self.event:
            return self.event.attendies.all()
        else:
            return []

...but you will still need to do some legwork to make those options available to the UI so the user can select them. Without knowing more about your setup, I'd be guessing if I tried to answer that part.

Upvotes: 1

Saurabh Goyal
Saurabh Goyal

Reputation: 647

You can override save() of EventArticle model to ensure it.

Upvotes: 0

Related Questions