简体   繁体   English

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

[英]Django model - object attribute update after creation

I am working on some Django project (first time) and after lot of searching i have no clue how to proper update object attribute after creation. 我正在做一些Django项目(第一次),经过大量搜索,我不知道如何在创建后正确更新对象属性。 I have sucha 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

Question is how to update url attribute after object creation of url to this particular object, it should be something like (base url + object_id i know object_id is created after object creation) but after searching documentation i dont have ideas how to do this properly. 问题是在对象创建到该特定对象的url之后如何更新url属性,应该是这样(基本url + object_id,我知道object_id是在对象创建之后创建的),但是在搜索文档后,我不知道如何正确执行此操作。

I tried get_absolute_path but with no success. 我尝试了get_absolute_path但没有成功。

Maybe some kind post_save method override ? 也许某种post_save方法重写?

One option would be to override the model save method and detect if the model instance is being added or updated and update the url field accordingly: 一种选择是覆盖模型保存方法,并检测是否正在添加或更新模型实例,并相应地更新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)

However, you needn't actually store the url as you can derive the value from other model fields when required. 但是,您实际上不需要存储url,因为可以在需要时从其他模型字段派生值。 Hence, you can delete the url field and create a url method instead: 因此,您可以删除url字段并创建url方法:

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

Here, the @property decoration here allows you to access place.url as if it was a model field. 在这里, @property这里装修允许您访问place.url ,如果它是一个模型字段。

This might be a good time to introduce something like Django celery into you're project and run this task async after creation. 这可能是将Django celery之类的东西引入您的项目并在创建后异步运行此任务的好时机。

You could have a task in a file like this: 您可以在这样的文件中包含一个任务:

# 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()

Then inside of your view when you create your Place you can do this: 那么你的观点的内部,当你创建你的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")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM