英文:
Automatic set/update fields in Django
问题
我在models.py中有两个模型
```python
class Teams(models.Model):
Name = models.CharField(verbose_name="Team Name", max_length=200)
Slug = AutoSlugField(populate_from="Name", always_update=True, editable=True, verbose_name="Team Slug")
Location = models.CharField(verbose_name="Team Location", max_length=200)
Leader = models.ForeignKey('Members', on_delete=models.SET_NULL, null=True, blank=True)
ArrivalDate = models.DateTimeField(default=timezone.now, editable=False, verbose_name="Arrival Date")
DepartureDate = models.DateTimeField(null=True, blank=True, verbose_name="Departure Date")
和
class Members(models.Model):
Name = models.CharField(verbose_name="Member Name", max_length=200)
Team = models.ForeignKey(Teams, on_delete=models.CASCADE)
PhoneNumber = models.CharField(max_length=20, null=True, blank=True)
Email = models.EmailField(max_length=50, null=True, blank=True)
BloodType = models.CharField(max_length=3, choices=BLOOD_TYPE_CHOICES, null=True, blank=True)
isLeader = models.BooleanField(default=False)
当Members模型中的isLeader字段设置为True时,我想要更新Teams模型中的Leader字段。
提前感谢
<details>
<summary>英文:</summary>
I have to models in models.py
class Teams(models.Model):
Name = models.CharField(verbose_name="Team Name", max_length=200)
Slug = AutoSlugField(populate_from="Name", always_update=True, editable=True, verbose_name="Team Slug")
Location = models.CharField(verbose_name="Team Location", max_length=200)
Leader = models.ForeignKey('Members', on_delete=models.SET_NULL, null=True, blank=True)
ArrivalDate = models.DateTimeField(default=timezone.now, editable=False, verbose_name="Arrival Date")
DepartureDate = models.DateTimeField(null=True, blank=True, verbose_name="Departure Date")
and
class Members(models.Model):
Name = models.CharField(verbose_name="Member Name", max_length=200)
Team = models.ForeignKey(Teams, on_delete=models.CASCADE)
PhoneNumber = models.CharField(max_length=20, null=True, blank=True)
Email = models.EmailField(max_length=50, null=True, blank=True)
BloodType = models.CharField(max_length=3, choices=BLOOD_TYPE_CHOICES, null=True, blank=True)
isLeader = models.BooleanField(default=False)
When isLeader field in Members field set True, I want to update Leader field in Teams model.
Thanks in advance
</details>
# 答案1
**得分**: 1
最好的方法是根本不存储领导者,因为那是重复的数据。您可以使用以下方法确定领导者。否则,您将存储重复的数据,正如您自己已经发现的那样,保持表同步实际上是一个比人们可能期望的要困难得多的问题:
```python
class Team(models.Model):
name = models.CharField(verbose_name='Team Name', max_length=200)
slug = AutoSlugField(
populate_from='Name',
always_update=True,
editable=True,
verbose_name='Team Slug',
)
location = models.CharField(verbose_name='Team Location', max_length=200)
arrival_date = models.DateTimeField(
default=timezone.now, editable=False, verbose_name='Arrival Date'
)
departure_date = models.DateTimeField(
null=True, blank=True, verbose_name='Departure Date'
)
@property
def leader(self):
return Member.objects.filter(team=self, is_leader=True).first()
在Member
模型中,我们可以添加一个约束,确保每个团队最多只有一个领导者:
from django.db.models import Q
class Member(models.Model):
name = models.CharField(verbose_name='Member Name', max_length=200)
team = models.ForeignKey(Team, on_delete=models.CASCADE)
phone_number = models.CharField(max_length=20, null=True, blank=True)
email = models.EmailField(max_length=50, null=True, blank=True)
blood_type = models.CharField(
max_length=3, choices=BLOOD_TYPE_CHOICES, null=True, blank=True
)
is_leader = models.BooleanField(default=False)
class Meta:
constraints = [
models.UniqueConstraint(
fields=('team',),
condition=Q(is_leader=True),
name='one_leader_per_team'
),
]
注意: 通常情况下,当相关字段发生更改时,不应更改slug。正如在文章Cool URIs don't change中所写的那样,URI不应更改,因为这些可以被收藏夹保存。因此,slug应该仅在创建对象时创建,而不是在更改slug依赖的任何字段时创建。
注意: 通常情况下,Django模型的名称应该是单数形式,因此应该是
Member
而不是。Members
注意: 通常情况下,Django模型中字段的名称以蛇形命名法书写,而不是帕斯卡命名法,因此应该是:
blood_type
而不是。Bloodtype
英文:
The best way is not to store the leader at all, since that is duplicated data. You can determine the leader with. Otherwise you store duplicated data, and as you actually already found out yourself, keeping tables in sync, turns out to be a much harder problem that what one might expect:
<pre><code>class Team(models.Model):
name = models.CharField(verbose_name='Team Name', max_length=200)
slug = AutoSlugField(
populate_from='Name',
always_update=True,
editable=True,
verbose_name='Team Slug',
)
location = models.CharField(verbose_name='Team Location', max_length=200)
arrival_date = models.DateTimeField(
default=timezone.now, editable=False, verbose_name='Arrival Date'
)
departure_date = models.DateTimeField(
null=True, blank=True, verbose_name='Departure Date'
)
@property
def <b>leader</b>(self):
return Member.objects.filter(team=self, is_leader=True).first()</code></pre>
in the Member
model, we can add a constraint that there is at most one such leader:
<pre><code>from django.db.models import Q
class Member(models.Model):
name = models.CharField(verbose_name='Member Name', max_length=200)
team = models.ForeignKey(Teams, on_delete=models.CASCADE)
phone_number = models.CharField(max_length=20, null=True, blank=True)
email = models.EmailField(max_length=50, null=True, blank=True)
blood_type = models.CharField(
max_length=3, choices=BLOOD_TYPE_CHOICES, null=True, blank=True
)
is_leader = models.BooleanField(default=False)
class Meta:
constraints = [
models.UniqueConstraint(
fields=('team',),
condition=Q(is_leader=True),
name='one_leader_per_team'
),
]</code></pre>
> Note: Normally you should not change slugs when the related fields change. As is written in the article Cool URIs don't change <sup>[w3.org]</sup>, URIs are not supposed to change, since these can be bookmarked. Therefore the slug should only be created when creating the object, not when you change any field on which the slug depends.
> Note: normally a Django model is given a singular name, so Member
instead of <s>Members
</s>.
> Note: normally the name of the fields in a Django model are written in snake_case, not PascalCase, so it should be: blood_type
instead of <s>Bloodtype
</s>.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论