【问题标题】:Django: Set many-to-many value to a modelDjango:为模型设置多对多值
【发布时间】:2022-01-27 17:07:09
【问题描述】:

我正在尝试测试我的模型ProjectCategoryTag。我在尝试将标签添加到我的项目模型时遇到了问题。

例如,它不允许我在 Project 模型本身中执行此操作。

self.project = Project.objects.create(
...
tags=Tag.objects.create("HTML5"),
)

Django 文档建议我按照以下方式进行操作。但是我不能在不保存模型的情况下“添加”Tag,如果不添加Tag,我也无法保存模型

测试

class ProjectTests(TestCase):
    def setUp(self):

        self.tag = Tag.objects.create(name="HTML5")

        self.project = Project(
            title="Oaks on Main Shopping Center",
            url="www.oaksonmain.co.za",
            image=SimpleUploadedFile(
                name="test-image.jpg",
                content=open(
                    "static\\images\\test_images\\florian-olivo-4hbJ-eymZ1o-unsplash (1).jpg", "rb"
                ).read(),
                content_type="image/jpeg",
            ),
            description="Beautiful website created for Oaks on Main Shopping Center in Knysna!",
            category=Category.objects.create(name="Website"),
        )

        self.project.save() <- Problem here
        self.project.tags.add(self.tag)  <- Problem here
        

    def test_project_model(self):
        self.assertEqual(f"{self.project.title}", "Oaks on Main Shopping Center")
        self.assertEqual(f"{self.project.url}", "www.oaksonmain.co.za")
        self.assertEqual(
            f"{self.project.description}",
            "Beautiful website created for Oaks on Main Shopping Center in Knysna!",
        )
        self.assertEqual(self.tags.count(), 3)
        self.assertEqual(self.category.count(), 1)
        self.assertEqual(self.image.count(), 1)

    def test_project_listview(self):
        resp = self.client.get(reverse("index"))
        self.assertEqual(resp.status_code, 200)
        self.assertContains(resp, self.project.title)
        self.assertTemplateUsed(resp, "page/index.html")

型号

class Project(models.Model):
    class Meta:
        ordering = ["-id"]  # Always show latest projects first
        verbose_name_plural = "Projects"

    title = models.CharField(max_length=50)
    url = models.URLField()
    image = models.ImageField(upload_to=f"{title}/")
    description = models.TextField()
    category = models.ForeignKey("Category", on_delete=models.PROTECT, related_name="categories")
    tags = models.ManyToManyField("Tag", verbose_name="tags")

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("index")


class Category(models.Model):
    class Meta:
        ordering = ["name"]
        verbose_name_plural = "Categories"

    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("index")


class Tag(models.Model):
    class Meta:
        ordering = ["name"]
        verbose_name_plural = "Tags"

    name = models.CharField(max_length=10)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("index")

【问题讨论】:

  • 如果您尝试保存不带标签的对象,究竟会出现什么问题。对于给定的模型,没有任何东西可以阻止在没有Tags 的情况下保存Project
  • 它给了我这个错误OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect: '&lt;personal filepath&gt;\\media\\&lt;django.db.models.fields.CharField&gt;'
  • 这与tags无关,而与SimpleUploadedFile的使用有关。

标签: django unit-testing django-models django-testing


【解决方案1】:

您可以先保存标签或模型对象,然后将标签链接为tagstags 中的一个Project,所以:

html5_tag, __ = Tag.objects.get_or_create(name='HTML5')
self.project = Project.objects.create(
    # no tags=…
)
self.project.tags.add(html5_tag)

您的ImageField 也应该与upload_to=… 参数的callable 一起使用,所以:

class Project(models.Model):
    # …
    def upload_image(self, filename):
        return f'{self.title}/{filename}'
    image = models.ImageField(upload_to=upload_image)
    # …

【讨论】:

    猜你喜欢
    • 2021-03-17
    • 2016-07-17
    • 2019-09-15
    • 2023-04-06
    • 1970-01-01
    • 2011-12-20
    • 2018-01-13
    • 2019-05-09
    • 2020-05-04
    相关资源
    最近更新 更多