Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#29631 closed New feature (wontfix)

Feature Request: models.UniqueBooleanField()

Reported by: Michael Owned by: nobody
Component: Database layer (models, ORM) Version: 2.1
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Imagine the schema for a tweet on Twitter:

class Tweet(models.Model):
   content = models.Charfield(max_length=280)
   user = models.ForeignKey(User)
   pinned = models.UniqueBooleanField(default=False, unique_with='user')

The user pins a tweet and behind the scenes UniqueBooleanField would set the previous tweet's pinned field to False (if any) and set the current one to True. This has tons of other use cases, including: the default group for a user and anything where there can only be one "default" given a unique_with property.

Is this a dumb idea? Is there already a better, more Django-idiomatic way? All feedback is appreciated.

Thanks,

Michael

Change History (2)

comment:1 Changed 4 years ago by Carlton Gibson

Resolution: wontfix
Status: newclosed

Hi iMerica,

Thanks for the input. Here are my thoughts:

  1. There's nothing to stop you creating a custom field for this. I'm not sure it's something we'd add to Django itself — It would be a bit too special case — but if you had an implementation, we could certainly look.
  2. Assuming I've understood the use-case correctly, you could model this with a nullable OneToOneField. (Each user can pin at most one of their own tweets.) When pinning you'd just need to clear any existing pin before saving. Then you'd just access via something like user.pinned_tweet.
  3. I'd probably be inclined to store the pinned_tweet for each user in a third table. (Do you have a profile model or such — maybe there — or just a two-field lookup model if not.) Again here the foreign key to User would be unique (or, the same thing, one-to-one).

Hopefully that gives you options. If you need further help please post to the Django Users mailing list.

If you come up with an implementation for your field that you think might be good for inclusion, create a Pull Request on GitHub and re-open this issue or post to the Django Developers mailing list to get feedback.

Thanks again.

Last edited 4 years ago by Carlton Gibson (previous) (diff)

comment:2 Changed 4 years ago by Simon Charette

I'd add that the usual way to implement such a feature is using a partial composite unique index which is something #29547 is trying to add support for.

In the mean time you can enforce it at the database level using a RunSQLOperation.

CREATE UNIQUE INDEX pinned_tweet ON tweet (user_id, pinned) WHERE pinned = true;

If your database doesn't support partial index a workaround would be to declare your pinned field as NULLable and use NULL as the falsey value as it will be ignored in unique constraints.

Note: See TracTickets for help on using tickets.
Back to Top