Reputation: 2482
My goal is to be able to limit the amount of models created to 3 and being able to UPDATE them.
my model.py is as follows:
class FeatureteImage(models.Model):
park = models.ForeignKey(Park)
header = models.CharField(max_length=50, blank=True)
body = models.TextField(max_length=250, blank=True)
image = models.ImageField(upload_to='featureteimages')
def get_absolute_url(self):
return reverse('park-features', kwargs={'pk': self.park.pk,})
def save(self, *args, **kwargs):
park = Park.objects.get(id=self.park.id)
if park.featurete >= 3:
pass
else:
park.featurete += 1
park.save()
super(FeatureteImage, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
park = Park.objects.get(id=self.park.id)
if park.featurete > 0:
park.featurete -= 1
park.save()
super(FeatureteImage, self).delete(*args, **kwargs)
else:
pass
def get_absolute_url(self):
park = Park.objects.get(id=self.park.id)
return reverse('park-features', kwargs={'pk': self.park.pk})
As you can see I am trying to limit the amount of featurete's park. So just 3 of them. I overwrote the custom save() so that if a park has 3 featuretes they can't add more.
But this still passes and still saves the new Featurete model. But it does update the model.
First I tried:
def save(self, *args, **kwargs):
park = Park.objects.get(id=self.park.id)
if park.featurete >= 3:
pass
else:
park.featurete += 1
park.save()
super(FeatureteImage, self).save(*args, **kwargs)
my views.py:
class AddFeaturete(generic.CreateView):
template_name = 'images/addfeaturete.html'
model = FeatureteImage
fields = ['header', 'body', 'image']
def form_valid(self, form):
self.venue = get_object_or_404(Park, pk=self.kwargs['pk'])
form.instance.park = self.park
return super(AddFeaturete, self).form_valid(form)
class UpdateFeaturete(generic.UpdateView):
template_name = 'images/updatefeaturete.html'
model = FeatureteImage
fields = ['header', 'body', 'image']
def get_object(self):
return get_object_or_404(FeatureteImage, pk=self.kwargs['f_pk'])
def form_valid(self, form):
return super(UpdateFeaturete, self).form_valid(form)
But when I tried to update the model it did not save the changes because the park had already 3 features and it just passes.
What do you think is the best way to work through this? I appreciate all your answers.
Upvotes: 0
Views: 229
Reputation: 1700
def save(self, *args, **kwargs):
if self.park.featureteimage_set.exclude(pk=self.pk).count() >= 3:
raise ValidationError('too much featuretes')
super(FeatureteImage, self).save(*args, **kwargs)
Upvotes: 1
Reputation: 934
The problem is that if you do reference counting then you have to act only if the park attribute of the Featurette was changed, not if the object was updated in some other way. You can solve that in two ways:
I think the first version would be more elegant if you do not need the count very often as it saves the whole delete logic.
Note: currently your code has the additional problem that the reference counter doesn't only need to be decremented on deletion, but also when an update changes the park. I don't know if that could be a problem in your use case.
The save() method with the first solution would look like this and you could get rid of the delete logic:
def save(self, *args, **kwargs):
count = self.objects.filter(park=self.park).exclude(pk=self.pk).count()
if not count < 3:
raise ValidationError('A park may not contain more than 3 featuretes')
super(FeatureteImage, self).save(*args, **kwargs)
Upvotes: 0
Reputation: 1082
Your code will pass in if condition and then call super of the model that is normal behavior of save function. Simply just say:
def save(self, *args, **kwargs):
park = Park.objects.get(id=self.park.id)
if self.pk: #update if it exists
super(FeatureteImage, self).save(*args, **kwargs)
elif park.featurete < 3:
park.featurete += 1
park.save()
super(FeatureteImage, self).save(*args, **kwargs)
else:
return
Upvotes: 0