Django模型 - 创建后的对象属性更新

时间:2017-07-10 09:45:34

标签: python django object model

我正在研究一些Django项目(第一次),经过大量搜索,我不知道如何在创建后正确更新对象属性。我有模特.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 属性,它应该是这样的(base url + object_id我知道object_id是在创建对象后创建的)但是在搜索文档之后我没有想法如何正确地做到这一点。

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

也许某种 post_save 方法会覆盖?

2 个答案:

答案 0 :(得分:0)

一种选择是覆盖模型保存方法并检测是否正在添加或更新模型实例并相应地更新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方法:

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

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

答案 1 :(得分:0)

这可能是将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")