2014-11-29 8 views
5

Mam to, co uważałem za proste pytanie. W moim modelu mam models.ImageField który wygląda tak:Python Django: Jak przesłać plik z nazwą pliku na podstawie instancji pk

class CMSDocument(BaseItem): 
    thumb = models.ImageField(upload_to= './media/',blank=True) 

Ale chciałbym przesłać go do '.media/' + self.pk+ '.png' Próbowałem zaktualizować pole wewnątrz metody ratowania modelu, ale to nie działa, ponieważ pk nie jest znany, gdy wywoływany jest "save". Próbowałem również dodać niestandardową funkcję upload_to zgodnie z sugestią tutaj: Django: Any way to change "upload_to" property of FileField without resorting to magic?. Ale to pozostawia puste pole. Co mogę zrobić?

EDIT: Używam Django 1.6

EDIT: Kiedyś sygnał post_save który nie jest bardzo ładny:

def video_embed_post_save(sender, instance=False, **kwargs):  
    document = DocumentEmbedType.objects.get(pk=instance.pk)  
    new_thumb = "media/%s.png" % (document.pk,) 
    if not document.thumb == new_thumb: 
     document.thumb = new_thumb 
     document.save() 
    ... 
+0

spróbować tej http://stackoverflow.com/questions/651949/django-access-primary-key-in-models-filefieldupload-to-location – madzohan

+0

bardzo hackowskim podejściem jest, w metodzie save, pobranie ostatniego identyfikatora rekordu, a następnie zwiększenie go o jeden i użycie go jako nowego identyfikatora. – Ymartin

+0

hmmm, faktycznie skończyłem używać sygnału post_save, który jest trochę hackem (sprawdzam, czy nazwa pliku jest już poprawna, jeśli nie, zmienię go i zapiszę model, w ten sposób nie będę miał problemów z rekurencją). Ale sprawdzę rozwiązanie @madzohan. – Magda

Odpowiedz

3

Klucz podstawowy jest przypisany przez bazę danych, więc trzeba czekać aż do modelu wiersz jest zapisywany w bazie danych.

pierwsze podzielić swoje dane w dwóch wersjach, z miniaturki na modelu dziecięcej:

from django.db import models 

from .fields import CMSImageField 


class CMSDocument(models.Model): 
    title = models.CharField(max_length=50) 


class CMSMediaDocument(CMSDocument): 
    thumb = CMSImageField(upload_to='./media/', blank=True) 

Jak widać używam niestandardowe pole do miniatury zamiast ImageField.

Więc stworzyć fields.py plik gdzie należy zastąpić funkcję pre_save klasy FileField odziedziczonej przez ImageField:

from django.db import models 


class CMSImageField(models.ImageField): 
    def pre_save(self, model_instance, add): 

     file = super(models.FileField, self).pre_save(model_instance, add) 

     if file and not file._committed: 
      # Commit the file to storage prior to saving the model 
      file.save('%s.png' % model_instance.pk, file, save=False) 
     return file 

Ponieważ CMSMediaDocument dziedziczy z klasy CMSDocument, w chwili obecnej, że pre_save nazywa Progresywny PK jest już zapisany w bazie danych, więc możesz wyodrębnić pk z model_instance.

Przetestowałem kod i powinien działać dobrze.

Plik Administrator stosowany w teście:

from django.contrib import admin 

from .models import CMSMediaDocument 

admin.site.register(CMSMediaDocument)