장고. 모델에 대한 저장 무시


134

모델을 저장하기 전에 사진 크기를 조정하고 있습니다. 그러나 새 사진이 추가되었거나 설명이 업데이트되었는지 어떻게 확인할 수 있습니까? 모델이 저장 될 때마다 크기 조정을 건너 뛸 수 있습니까?

class Model(model.Model):
    image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()


    def save(self, *args, **kwargs):
        if self.image:
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

새 이미지가로드되거나 이미지가 업데이트 된 경우에만 크기를 조정하고 싶지만 설명이 업데이트되지 않았습니다.


고정 크기 100x100으로 크기를 조정하고 있습니까?
bdd

3
U 찾을 수 있습니다 장고 - imagekit 유용
vikingosegundo

답변:


135

몇 가지 생각 :

class Model(model.Model):
    _image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()

    def set_image(self, val):
        self._image = val
        self._image_changed = True

        # Or put whole logic in here
        small = rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)

    def get_image(self):
        return self._image

    image = property(get_image, set_image)

    # this is not needed if small_image is created at set_image
    def save(self, *args, **kwargs):
        if getattr(self, '_image_changed', True):
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

모든 의사 자동 장고 도구 (예 : ModelForm, contrib.admin 등)에서 잘 작동하는지 확실하지 않습니다.


1
좋아 보인다. 그러나 이미지의 이름을 _image로 바꿀 수 없습니다. 그게 중요합니까?
Pol

좋아, db_column = 'image'로 해결했다. 그러나 그것은 강철이 작동하지 않습니다!
Pol

1
그것은 매우 흥미로운 방법입니다. 나는 그것을 완전히 이해하지 못합니다. 좀 더 설명해 주시겠습니까? 아니면 기사를 뿌려?
Pol

그것은 나에게도 효과가 없다. set_image는 호출되지 않았습니다. Django가 공식적으로 지원하지 않는 것들
Ivan Borshchov

16

모델의 pk 필드를 확인하십시오. None이면 새 개체입니다.

class Model(model.Model):
    image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()


    def save(self, *args, **kwargs):
        if 'form' in kwargs:
            form=kwargs['form']
        else:
            form=None

        if self.pk is None and form is not None and 'image' in form.changed_data:
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

편집 : form.changed_data에 'image'에 대한 검사를 추가했습니다. 이것은 관리자 사이트를 사용하여 이미지를 업데이트한다고 가정합니다. 또한 아래 표시된대로 기본 save_model 메소드를 대체해야합니다.

class ModelAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.save(form=form)

관리자 사이트를 사용한다고 가정하면 AdminModel에서 save_model을 재정 의하여 양식을 저장하여 전달하고 'image'가 form.changed_data인지 확인할 수 있습니다. 시간이 되 자마자 업데이트하겠습니다.
DM 그레이브스

이것은 당신이 말한 것처럼 객체가 새로운 경우에만 작동합니다. 새 사진을 업로드하면 크기 조정이 트리거되지 않습니다.
Jonathan

2
ID를 지정하면 "self.pk is None"이 작동하지 않으므로 Model.objects.get_or_create (id = 234, ...)는이 솔루션에서 작동하지 않습니다
nuts

6

새 이미지가 게시되었음을 확인하기 위해 추가 인수를 제공 할 수 있습니다.
다음과 같은 것 :

def save(self, new_image=False, *args, **kwargs):
    if new_image:
        small=rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)
    super(Model, self).save(*args, **kwargs)

또는 요청 변수를 전달

def save(self, request=False, *args, **kwargs):
    if request and request.FILES.get('image',False):
        small=rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)
    super(Model, self).save(*args, **kwargs)

나는 이것이 단순히 호출 될 때 당신의 세이브를 깨뜨리지 않을 것이라고 생각합니다.

이것을 admin.py에 넣으면 관리자 사이트에서도 작동합니다 (위의 두 번째 해결책).

class ModelAdmin(admin.ModelAdmin):

    ....
    def save_model(self, request, obj, form, change): 
        instance = form.save(commit=False)
        instance.save(request=request)
        return instance

'WSGIRequest'객체에는 'FILE'속성이 없습니다.
Pol

request.FILES.get ( '상'거짓) 대신 request.FILES [ '상']로 갱신 대신 FILE의 SRY 그 파일이 이러한 예외를 피할
crodjer

3

내가 목표를 달성하기 위해 한 것은 이것을 만드는 것입니다.

# I added an extra_command argument that defaults to blank
def save(self, extra_command="", *args, **kwargs):

save () 메소드 아래에 있습니다.

# override the save method to create an image thumbnail
if self.image and extra_command != "skip creating photo thumbnail":
    # your logic here

일부 필드를 편집하지만 이미지를 편집하지 않을 때 이것을 넣습니다.

Model.save("skip creating photo thumbnail")

당신은 대체 할 수 "skip creating photo thumbnail""im just editing the description"또는 형식적인 텍스트입니다.

이것이 도움이 되길 바랍니다!


2

동일한 PK를 가진 기존 레코드에 대해 데이터베이스를 조회하십시오. 새 이미지와 기존 이미지의 파일 크기와 체크섬을 비교하여 동일한 지 확인하십시오.


1

Django 3 : 사전 정의 된 모델 메소드 재정의

from django.db import models

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def save(self, *args, **kwargs):
        do_something()
        super().save(*args, **kwargs)  # Call the "real" save() method.
        do_something_else()

super().save(*args, **kwargs)객체가 여전히 데이터베이스에 저장되도록 하려면 수퍼 클래스 메소드 (즉, 비즈니스) 를 호출하는 것이 중요 합니다. 수퍼 클래스 메소드 호출을 잊어 버린 경우 기본 동작이 발생하지 않고 데이터베이스가 건드리지 않습니다.


0

새 버전에서는 다음과 같습니다.

def validate(self, attrs):
    has_unknown_fields = set(self.initial_data) - set(self.fields.keys())
    if has_unknown_fields:
        raise serializers.ValidationError("Do not send extra fields")
    return attrs

0

데이터베이스에 데이터를 저장하는 또 다른 간단한 방법을 찾았습니다.

models.py

class LinkModel(models.Model):
    link = models.CharField(max_length=500)
    shortLink = models.CharField(max_length=30,unique=True)

데이터베이스에는 2 개의 변수 만 있습니다

views.py

class HomeView(TemplateView):
    def post(self,request, *args, **kwargs):
        form = LinkForm(request.POST)

        if form.is_valid():
            text = form.cleaned_data['link'] # text for link

        dbobj = LinkModel()
        dbobj.link = text
        self.no = self.gen.generateShortLink() # no for shortLink
        dbobj.shortLink = str(self.no)
        dbobj.save()         # Saving from views.py

여기서는 views.py에서만 모델 인스턴스를 만들고 뷰에서만 2 변수에 데이터를 넣거나 저장합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.