在Django中自动设置/更新字段。

huangapple go评论57阅读模式
英文:

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 &lt;b&gt;leader&lt;/b&gt;(self):
    return Member.objects.filter(team=self, is_leader=True).first()&lt;/code&gt;&lt;/pre&gt;

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=(&#39;team&#39;,),
            condition=Q(is_leader=True),
            name=&#39;one_leader_per_team&#39;
        ),
    ]&lt;/code&gt;&lt;/pre&gt;

> Note: Normally you should not change slugs when the related fields change. As is written in the article Cool URIs don't change&nbsp;<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>.

huangapple
  • 本文由 发表于 2023年7月3日 15:08:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76602554.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定