Dav*_*ave 9 python django foreign-keys django-models python-3.x
我正在使用Python 3.7和Django.我有以下型号,带有另一个型号的外键......
class ArticleStat(models.Model):
objects = ArticleStatManager()
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='articlestats')
...
def save(self, *args, **kwargs):
if self.article.exists():
try:
article_stat = ArticleStat.objects.get(article=self.article, elapsed_time_in_seconds=self.elapsed_time_in_seconds)
self.id = article_stat.id
super().save(*args, **kwargs, update_fields=["hits"])
except ObjectDoesNotExist:
super().save(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
如果相关的外键存在,我只想保存它,否则,我注意到错误结果.做这样的事情的标准Django/Python方法是什么?我以为我读过我可以使用".exists()"(检查一个对象是否存在),但我得到一个错误
AttributeError: 'Article' object has no attribute 'exists'
Run Code Online (Sandbox Code Playgroud)
编辑:这是我必须检查的单元测试...
id = 1
article = Article.objects.get(pk=id)
self.assertTrue(article, "A pre-condition of this test is that an article exist with id=" + str(id))
articlestat = ArticleStat(article=article, elapsed_time_in_seconds=250, hits=25)
# Delete the article
article.delete()
# Attempt to save ArticleStat
articlestat.save()
Run Code Online (Sandbox Code Playgroud)
如果你想确保文章中存在ArticleStat的save
方法,你可以尝试从您的数据库,而不仅仅是测试得到它self.article
.
"...... Grace Murray Hopper着名的座右铭,"请求宽恕比允许更容易",有很多有用的应用 - 在Python中,......"
我认为使用try .. except .. else
更pythonic,我会做这样的事情:
from django.db import models
class ArticleStat(models.Model):
...
article = models.ForeignKey(
Article, on_delete=models.CASCADE, related_name='articlestats'
)
def save(self, *args, **kwargs):
try:
article = Article.objects.get(pk=self.article_id)
except Article.DoesNotExist:
pass
else:
try:
article_stat = ArticleStat.objects.get(
article=article,
elapsed_time_in_seconds=self.elapsed_time_in_seconds
)
self.id = article_stat.id
super().save(*args, **kwargs, update_fields=["hits"])
except ArticleStat.DoesNotExist:
super().save(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
如果您使用的是关系数据库,则会在迁移后自动添加外键约束.save
方法可能不需要任何自定义.
class ArticleStat(models.Model):
objects = ArticleStatManager()
article = models.ForeignKey(
Article, on_delete=models.CASCADE, related_name='articlestats'
)
Run Code Online (Sandbox Code Playgroud)
使用以下代码创建ArticleStats
from django.db import IntegrityError
try:
ArticleStats.objects.create(article=article, ...)
except IntegrityError:
pass
Run Code Online (Sandbox Code Playgroud)
如果article_id有效,则会创建ArticleStats对象,否则会引发IntegrityError.
article = Article.objects.get(id=1)
article.delete()
try:
ArticleStats.objects.create(article=article, ...)
print("article stats is created")
except IntegrityError:
print("article stats is not created")
# Output
article stats is not created
Run Code Online (Sandbox Code Playgroud)
注意:在MySQL v5.7,Django 1.11上测试过
ArticleStat模型上的文章字段不是可选的.没有ForeignKey to Article,您无法保存ArticleStat对象
这是一个类似的代码,item是Item模型的ForeignKey,它是必需的.
class Interaction(TimeStampedModel, models.Model):
...
item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='interactions')
type = models.IntegerField('Type', choices=TYPE_CHOICES)
...
Run Code Online (Sandbox Code Playgroud)
如果我尝试从shell中保存Interaction的对象而不选择ForeignKey到该项,我会收到IntegrityError.
~ interaction = Interaction()
~ interaction.save()
~ IntegrityError: null value in column "item_id" violates not-null constraint
Run Code Online (Sandbox Code Playgroud)
你不需要检查self.article.exists()
.Django和数据库将需要该字段,并且不允许您在没有它的情况下保存对象.
您应该阅读Django Docs中的 ForeignKey字段
您可以只测试该字段的值article
。如果没有设置,我相信它默认为None
.
if self.article: # Value is set
Run Code Online (Sandbox Code Playgroud)
如果您希望此外键字段是可选的(听起来像您所做的那样),则需要在该字段上设置blank=True
和null=True
。这将允许该字段为空(在验证中),并且null
当该字段不存在时将在该字段上设置。
正如下面的评论中提到的,您的数据库可能会强制执行该字段是必需的这一事实,并拒绝删除该article
实例。
归档时间: |
|
查看次数: |
866 次 |
最近记录: |