[英]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.