Django. Ghi đè lưu cho mô hình


134

Trước khi lưu mô hình, tôi chỉnh lại kích thước ảnh. Nhưng làm thế nào tôi có thể kiểm tra nếu hình ảnh mới được thêm vào hoặc chỉ mô tả được cập nhật, vì vậy tôi có thể bỏ qua việc thay đổi kích thước mỗi khi mô hình được lưu?

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)

Tôi chỉ muốn bán lại nếu hình ảnh mới được tải hoặc hình ảnh được cập nhật, nhưng không phải khi mô tả được cập nhật.


Bạn đang thay đổi kích thước đến kích thước cố định 100x100?
bdd

3
Bạn có thể thấy django-imagekit hữu ích
vikingosegundo

Câu trả lời:


135

Một vài suy nghĩ:

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)

Không chắc chắn nếu nó sẽ chơi tốt với tất cả các công cụ django giả tự động (Ví dụ: ModelForm, contrib.admin, v.v.).


1
Có vẻ tốt đẹp. Nhưng tôi không thể đổi tên hình ảnh thành _image. Điều đó rất quan trọng?
Pol

Ok tôi đã giải quyết nó với db_column = 'image'. Nhưng nó thép không hoạt động!
Pol

1
Nó là phương pháp rất thú vị .. bởi tôi không hiểu nó đầy đủ. Bạn có thể vui lòng giải thích nó một cách rõ ràng hơn? Hoặc gieo một số bài viết?
Pol

Nó không làm việc cho tôi quá. set_image không bao giờ được gọi. Có vẻ như một số Django không được hỗ trợ chính thức
Ivan Borshchov

16

Kiểm tra trường pk của mô hình. Nếu nó là Không, thì nó là một đối tượng mới.

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)

Chỉnh sửa: Tôi đã thêm một kiểm tra cho 'hình ảnh' trong form.changed_data. Điều này giả định rằng bạn đang sử dụng trang quản trị để cập nhật hình ảnh của mình. Bạn cũng sẽ phải ghi đè phương thức save_model mặc định như được chỉ ra bên dưới.

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

Tôi nghĩ bạn đã đúng ... giả sử anh ta đang sử dụng trang quản trị, anh ta có thể ghi đè save_model trong AdminModel của mình để chuyển biểu mẫu qua để lưu và kiểm tra xem 'hình ảnh' có ở dạng không.changed_data. Tôi sẽ cập nhật ngay khi có thời gian.
DM Graves

Điều này chỉ hoạt động nếu đối tượng là mới như bạn nói. Nếu bạn tải lên một hình ảnh mới, kích hoạt lại sẽ không kích hoạt.
Jonathan

2
"self.pk là Không" không hoạt động nếu một người chỉ định id, vì vậy: Model.objects.get_or_create (id = 234, ...) sẽ không hoạt động trong giải pháp này
nut

6

Bạn có thể cung cấp thêm đối số để xác nhận hình ảnh mới được đăng.
Cái gì đó như:

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)

hoặc vượt qua biến yêu cầu

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)

Tôi nghĩ rằng những điều này sẽ không phá vỡ sự tiết kiệm của bạn khi được gọi đơn giản.

Bạn có thể đặt cái này trong admin.py để nó cũng hoạt động với trang quản trị (đối với các giải pháp thứ hai ở trên):

class ModelAdmin(admin.ModelAdmin):

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

nó nói với tôi rằng: 'Đối tượng WSGIRequest' không có thuộc tính 'TẬP_TIN'
Pol

sry PHIM của nó thay vì TẬP TIN, được cập nhật thành request.FILES.get ('hình ảnh', Sai) thay vì yêu cầu.FILES ['hình ảnh'], điều này sẽ tránh ngoại lệ
crodjer

3

Những gì tôi đã làm để đạt được mục tiêu là thực hiện điều này ..

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

và bên dưới phương thức save () là đây ..

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

Vì vậy, khi tôi chỉnh sửa một số trường nhưng không chỉnh sửa hình ảnh, tôi đặt nó ..

Model.save("skip creating photo thumbnail")

bạn có thể thay thế "skip creating photo thumbnail"bằng"im just editing the description" hoặc một văn bản chính thức hơn.

Hy vọng điều này sẽ giúp!


2

Truy vấn cơ sở dữ liệu cho một bản ghi hiện có cùng PK. So sánh kích thước tệp và tổng kiểm tra của hình ảnh mới và hình ảnh hiện tại để xem chúng có giống nhau không.


1

Django 3: Ghi đè các phương thức mô hình được xác định trước

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

Điều quan trọng cần nhớ là gọi phương thức siêu lớp - đó là super().save(*args, **kwargs)doanh nghiệp - để đảm bảo rằng đối tượng vẫn được lưu vào cơ sở dữ liệu. Nếu bạn quên gọi phương thức siêu lớp, hành vi mặc định sẽ không xảy ra và cơ sở dữ liệu sẽ không được chạm vào.


0

Trong phiên bản mới, nó là như thế này:

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

Tôi đã tìm thấy một cách đơn giản khác để lưu trữ dữ liệu vào cơ sở dữ liệu

mô hình

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

Trong cơ sở dữ liệu tôi chỉ có 2 biến

lượt xem

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

Trong phần này, tôi đã tạo ra thể hiện của mô hình chỉ trong view.txt và đặt / lưu dữ liệu vào 2 biến từ các khung nhìn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.