Django: Установка IntegerField после отправки формы
Как увеличить поле "наличие" IntergerField после отправки формы?
Каждый новый тип_продукта создается в панели администратора, так как мне понадобится всего несколько типов. Каждый новый продукт создается через форму.
views.py
def new_product(request):
if request.method != 'POST':
# No data submitted, create blank form
form = ProductForm()
else:
# POST data submitted, process the data
form = ProductForm(data=request.POST)
if form.is_valid():
product = form.save(commit=False)
product.owner = request.user
#product.product_type.availability += 1 # This didn't work
#product.product_type.add_product() # And this didn't work
product.save()
return redirect('store')
context = {'form': form}
return render(request, 'store/new_product.html', context)
models.py
class ProductType(models.Model):
availability = models.IntegerField(default=0) ## How to increase this on the fly?
price = models.DecimalField(max_digits=7, decimal_places=2, default=6.99)
product_type = models.CharField(max_length=200, default="Tier1")
cores = models.IntegerField(default=1)
ram = models.IntegerField(default=2)
disk = models.IntegerField(default=10)
def __str__(self):
return self.product_type
def add_product(self):
self.availability = self.availability + 1
print(self.availability)
forms.py
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ['host_name', 'host_password', 'product_type']
Учитывая используемые вами решения, вы можете переопределить метод save()
.
# models.py
def save(self, *args, **kwargs):
self.availability += 1
super().save(*args, **kwargs)
Я бы посоветовал вам использовать сигналы post_save, предоставляемые Django. Сигналы - это отличный способ решения подобных проблем. Когда вы хотите выполнить зависимые действия.
When A happens perform B
When A happens and C is in some state perform B
Вы можете создавать пользовательские сигналы, а если хотите, то можете использовать уже существующие сигналы сохранения Django Model (post_save, pre_save и т.д.)
This is how you implement custom signals
import django.dispatch
product_save_signal = django.dispatch.Signal()
You can emit these signals from anywhere you want. Suppose you want to emit this on Product Model Form save. In your case this can go into your new_product function.
def save(self, *args, **kwargs): # signature of save for the class you are overriding
super().save(*args, **kwargs)
pizza_done.send(sender=<pass_your_sender_here>, <pass other data as kwargs here>)
How to use this signal
@receiver(product_save_signal)
def action_after_product_save(sender, task_id, **kwargs):
product_type_instance = Product.objects.filter(<some_query>).first()
product_type_instance.availability = F('availability') + 1
product_type_instance.save()
Note: You should always use F('availability') + 1
i.e F queries to perform increments and similar operation to ensure Django handles race conditions.
Хотя я и узнал кое-что новое, пробуя идеи из ваших ответов, решение оказалось намного проще, чем я думал.
Ответом на мой профлемму было использование F('availability') + 1
, а не availability += 1
, а затем обновление ProductType из модели Product.
Выглядит это следующим образом:
models.py
class ProductType(models.Model):
availability = models.IntegerField(default=0)
price = models.DecimalField(max_digits=7, decimal_places=2, default=6.99)
product_type = models.CharField(max_length=200, default="Tier1")
cores = models.IntegerField(default=1)
ram = models.IntegerField(default=2)
disk = models.IntegerField(default=10)
def __str__(self):
return self.product_type
def update(self, *args, **kwargs):
self.availability = F('availability') + 1
super().save(*args, **kwargs)
def check_availability(self):
if self.availability > 0:
return True
else:
return False
class Product(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
host_name = models.CharField(max_length=200, default="")
host_password = models.CharField(max_length=200, default="")
product_type = models.ForeignKey(ProductType, null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.host_name
def save(self, *args, **kwargs):
self.product_type.update()
super().save(*args, **kwargs)