简体   繁体   中英

In my Django model, how can I automatically populate a field?

I have a Django model for a book club, which contains a single president, and many members. Naturally, a club president would automatically be considered a member as well. How can I configure my members field to always add the president, with room for expansion? Here is my current Club model:

class Club(models.Model):
    president = models.ForeignKey(User, related_name='president')
    name = models.CharField(max_length=30)
    description = models.TextField(max_length=320)
    members = models.ManyToManyField(User, related_name='members')
    creation_date = models.DateTimeField(auto_now_add=True)

You can't configure "members" field automatically.

I would recommend using ManyToMany relationship with through option, so you will be able to add extra field to relationship between Member(User) and Club. eg is_president=True . (see docs example ManyToMany.through )

# models.py
from django.db import models
from django.contrib.auth import get_user_model

class Club(models.Model):
    name = models.CharField(max_length=30)
    description = models.TextField(max_length=320)
    members = models.ManyToManyField(through="Membership", related_name='clubs')

class Member(models.Model):
    user = models.OneToOne(get_user_model())

class Membership(models.Model):
    member = models.ForeignKey(Member)
    club = models.ForeignKey(Club)
    date_joined = models.DateField()
    is_president = models.BooleanField(default=False)

However in your current model setup you can overload Model.save() which is not recommended, or use Django's build in post-save signal which is prefered.

1, Create method (or function) which will check if "president" is "member" of Club

# models.py
def check_president_as_member(sender, instance, **kwargs):
    #check if instance.president is in instance.members.all()
    #add president to members if necessary
    return True

2, Register method with post-save on Club model.

# models.py
from django.db import models 
models.signals.post_save.connect(check_president_as_member, sender=Club, dispatch_uid="check_president_as_member_post_save", weak=False)

You want to validate that the president is always in members and if not, to add the president to members. You can do this by validating model objects. See the docs .

A better design for your model will be

class Club(models.Model):
    name = models.CharField(max_length=30)
    description = models.TextField(max_length=320)
    members = models.ManyToManyField(User, related_name='members')
    member_type = models.IntegerField(default=0) #0 member 1 president
    creation_date = models.DateTimeField(auto_now_add=True)

What I have done is removed the president column as it was redundant. President will also be the member of club so use a flag member_type to identify which member is president.

This will also give you flexibility to change the president by just changing the member_type column.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM