【问题标题】:Django model - object attribute update after creationDjango模型-创建后对象属性更新
【发布时间】:2017-12-13 23:50:48
【问题描述】:

我正在处理一些 Django 项目(第一次),经过大量搜索后,我不知道如何在创建后正确更新对象属性。我有这样的models.py

    from django.db import models
import os


# Create your models here.

class Place(models.Model):
    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    # Add templates folder for dynamic usage, os independent
    TEMPLATE_DIR = os.path.join(BASE_DIR, "templates/places")

    name = models.CharField(max_length=100, unique=True)
    display_name = models.CharField(max_length=100)
    floor = models.DecimalField(max_digits=3, decimal_places=0)
    template = models.FilePathField(path=TEMPLATE_DIR, match=".*html")
    url = models.URLField(unique=True)

# Display name of object in object list view
    def __str__(self):
        return self.name

问题是如何在对象创建 url 到这个特定对象后更新 url 属性,它应该类似于(基本 url + object_id 我知道 object_id 是在对象创建后创建的)但是在搜索文档之后我不知道如何正确地做到这一点。

我尝试了 get_absolute_path,但没有成功。

也许是某种 post_save 方法覆盖?

【问题讨论】:

  • 为什么要在创建后更新同一个对象?保存前不计算吗?
  • @AvinashRaj 因为我写了正确的 url 我需要在对象保存到 DB 后创建的 object_id,如果有一些方法可以更早地获取 id,我愿意接受建议。跨度>
  • 好的,你可以使用 django post_save 信号..

标签: python django object model


【解决方案1】:

一种选择是覆盖模型保存方法并检测是否正在添加或更新模型实例并相应地更新 url 字段:

class Place(models.Model):
    # ...
    def save(self, *args, **kwargs):
        is_adding = self._state.adding
        super(Place, self).save(self, *args, **kwargs)

        if is_adding:
            url = os.path.join(self.TEMPLATE_DIR, str(self.pk))
            super(Place, self).save(self, *args, **kwargs)

但是,您实际上不需要存储 url,因为您可以在需要时从其他模型字段中获取值。因此,您可以删除 url 字段并创建一个 url 方法:

class Place(models.Model):
    # ...
    @property
    def url(self):
        return os.path.join(self.TEMPLATE_DIR, str(self.pk))

这里,@property 装饰允许您访问place.url,就好像它是一个模型字段一样。

【讨论】:

    【解决方案2】:

    现在可能是将Django celery 之类的内容引入您的项目并在创建后异步运行此任务的好时机。

    你可以在这样的文件中有一个任务:

    # I'm making assumptions on project architecture..
    from app.places import Place
    from app.places.utils import PLACE_BASE_URL
    
    @shared_task
    def task_update_place_url(place_id):
        """ 
        Simple method to update Place url after creation. 
        """
        place = Place.objects.get(pk=place_id)
        place.url = PLACE_BASE_URL + place_id
        place.save()
    

    然后,当您创建 Place 时,您可以在视图内部执行以下操作:

    import json
    from django.http.response import HttpResponse
    
    from app.places.models import Place
    from app.places.tasks import task_update_place_url
    
    def create_place(request):
        """ 
        Creates a new Place and update url in task 
        """
        data = json.loads(request)
        place = Place.objects.create(**data)
        task_update_place_url.delay(place.id)
        return HttpResponse("Finished")
    

    【讨论】:

      猜你喜欢
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-06
      相关资源
      最近更新 更多