I have built a wizard in my project. In the first step I create an object "Building" and save it in the db. In the second step I let the user upload an image of the building saved in the first step.
The image is in the Building's model.
When I try to customize the saving path of the image, I found out that "instance.pk" is None.
The same thing happen if I try to access every attribute of the Model that should be in "instance". The only attributes that I can access are those I manually set in the View (ex. nome, descrizione, ...)
I don't undersant why is happening this. Could somebody explain it to me?
Part of the Model:
class Building(models.Model):
utente = models.ForeignKey(User);
nome = models.CharField(max_length=200, unique=True)
descrizione = models.TextField(max_length=1000, blank=True)
link = models.URLField(blank=True)
foto = ImageField(upload_to=content_file_name, blank=True)
...
Content_file_name:
def content_file_name(instance, filename):
estensione = '.jpg'
posizione_punto = filename.rfind('.')
if posizione_punto > 0:
estensione = filename[posizione_punto:]
return '/'.join(['buildings', str(instance.pk), 'vetrina'+estensione])
Part of the View (2nd wizard step):
# I load the building from the db
building = get_object_or_404(Building, pk=b_id)
if request.method == 'POST':
form = StepOneForm(request.POST, request.FILES)
if form.is_valid():
data = form.save(commit=False)
building.data_update = datetime.datetime.now()
building.nome = data.nome
building.descrizione = data.descrizione
building.link = data.link
building.foto = data.foto
building.save()
...
Firstly, you've defined your foto
field as foto = ImageField()
it should probably be foto = models.ImageField()
Secondly, when you initiate your form you're not including the instance
argument (have a look at the docs). It should be something like -
form = StepOneForm(request.POST, request.FILES, instance=building)
That's how django knows to add the html form data to an existing instance. If you declare your form like this -
from django.forms import ModelForm
class BuildingForm(ModelForm):
class Meta:
model = Building
Then when you do data = form.save(commit=False)
your data
variable is actually an instance of Building
. And if you've already said that the form relates to a specific instance (eg the building
you declare at the beginning of your view), then data
will be that specific instance of Building
.
This means that you can change your view code to -
def your_view(request):
building = get_object_or_404(Building, pk=b_id)
if request.method == 'POST':
form = BuildingForm(request.POST, request.FILES, instance=building)
if form.is_valid():
building = form.save(commit=False)
building.save()
else: #...