class Product(models.Model):
varient_property = models.ManyToManyField(to='store.AttributeValue', blank=True)
def save(self, *args, **kwargs):
super(Product, self).save(*args, **kwargs)
# here varient_propery is manytomany field
# here i am saving this from django admin panel
print(self.varient_property.all())
many to many class
class AttributeValue(models.Model):
value = models.CharField(max_length=30)
available = models.BooleanField(default=True)
def __str__(self):
return self.value
the print statement returns none
how can I get many to many data after my model gets save?
I want all set many-to-many relations.
thanks in advance.
You can try this:
If you want all the records from AttributeValue model you need to use the all() method on the class not on the instance that you obtain from varient_property in Product model.
class Product(models.Model):
varient_property = models.ManyToManyField(to='store.AttributeValue', blank=True)
def save(self, *args, **kwargs):
super(Product, self).save(*args, **kwargs)
print(AttributeValue.objects.all()) #like this
Related
I have a model of the category with title and count and I also have another model called Products which has category as one of its foreign-key. How can I auto-update the category count field by the number of products that comes under the same category?
class Category(models.Model):
title = models.CharField(max_length = 20)
count = models.IntegerFIeld()
class Product(models.Model):
title = models.CharField(max_length = 20)
category = models.ForeignKey(Category, on_delete = models.CASCADE)
You can either override save method or write a signal to auto-update the field, i.e.:
class Category(models.Model):
def save(self, *args, **kwargs):
self.count = self.product_set.count()
super().save(*args, **kwargs)
or with signals:
from django.dispatch import receiver
#receiver(post_save, sender=Category)
def category_post_save(sender, instance, *args, **kwargs):
instance.count = instance.product_set.count()
instance.save()
But I would suggest you using a calculated property:
class Category(models.Model):
...
#property
def count(self):
return self.product_set.count()
If you want to keep the field count I recommend you use signals. You should use post_signal and pre_signal (to get the previous category from a query) on the model Product.
Here are the signals:
#receiver(signals.pre_save, sender=Product)
def product_pre_save_signal(sender, instance, *args, **kwargs):
if instance.id:
previous_instance = Product.objects.get(id=instance.id)
if previous_instance.category != instance.category:
instance.previous_category = previous_instance.category
#receiver(signals.post_save, sender=Product)
def product_post_save_signal(sender, instance, created, *args, **kwargs):
if not created:
if hasattr(instance, "previous_category"):
if instance.previous_category:
instance.previous_category.count -= 1
instance.previous_category.save()
if instance.category:
instance.category.count += 1
instance.category.save()
else:
if instance.category:
instance.category.count += 1
instance.category.save()
Another recommendation for this situation is, make it a read-only field(add editable=False to the field declaration), so no one can edit it from Django admin or serializer.
But I highly recommend you remove the field because it's hard to keep this field sync with the table Product, so calculate the value each time.
You can have almost any query that is related field count over Category or Product, so don't worry:)
I need to filter in EmployeeForm just to show me options of Companies related to user is logged in. I'm using ModelForm and CreateViews
This is my code:
models.py:
class Company(models.Model):
reg_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
cuit = models.CharField(max_length=20)
class Employee(models.Model):
company = models.ForeignKey(Empresa, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
cuil = models.CharField(max_length=20)
forms.py:
class EmployeeForm(ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
...
self.fields['name'].widget.attrs['autofocus'] = True
What is the code I need to write in the ellipses? It's currently showing me all companies even ones not owned by the user.
I use forms.Form for this instead of ModelForm, but what i do is:
class EmployeeForm(forms.Form):
companies = forms.ModelChoiceField(queryset=None)
def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['companies'].queryset = Company.objects.filter(reg_user=user)
I finally could solve this by using this in views.py
def get_form(self):
form = super(EmployeeCreateView, self).get_form()
form.fields['company'].queryset = Company.objects.filter(reg_user=self.request.user)
return form
Thanks for everyone!
Different proxy models should be different in type.
If I query those models I the right ones.
I am trying to save a default type field in a proxy model.
I don't want to set it everytime in the view.
This does not work. The type field is always "TYPE1".
models.py:
class MyModel(models.Model):
class ModelType(models.TextChoices):
TYPE1 = 'TYPE1', _('TYPE1')
TYPE2 = 'TYPE2', _('TYPE2')
type = models.CharField(max_length=100, choices=ModelType.choices, default='TYPE1')
class Type2Manager(models.Manager):
def get_queryset(self):
return super(Type2Manager, self).get_queryset().filter(type='TYPE2')
def save(self, *args, **kwargs):
kwargs.update({'type': 'TYPE2'})
return super(Type2Manager, self).save(*args, **kwargs)
class Type2ProxyModel(MyModel):
class Meta:
proxy = True
objects = Type2Manager()
views.py:
def create_type2_model(request):
form = Type2Form(request.POST, initial={})
f = form.save(commit=False)
f.save()
forms.py:
class Type2Form(ModelForm):
class Meta:
model = Type2ProxyModel
Update 25.02.2020 12:18:
I found out that this sets the correct type. But I don't know how to use create() in a ModelForm.
class Type2Manager(models.Manager):
...
def create(self, **kwargs):
kwargs.update({'type': 'TYPE2'})
return super(Type2Manager, self).create(**kwargs)
Type2ProxyModel.objects.create()
A model manager operates on a "table-level". When you create an object via a form it uses the model objects and not the model manager and thus you'd need to override the save of your proxy model. If I modify your Type2ProxyModel to this it works:
class Type2ProxyModel(MyModel):
class Meta:
proxy = True
objects = Type2Manager()
def save(self, *args, **kwargs):
self.type = 'TYPE2'
return super(Type2ProxyModel, self).save(*args, **kwargs)
I would like to save model id along with other format characters into another column, based on the model id being automatically created. For example,
For example, I have column name formated_id in shipment model, and want set its value to "easter" + ID which is automatically generated. How could I achieve that? Thanks.
class Shipment(models.Model):
formated_id = models.CharField("formatedid",max_length= 50)
class Meta:
ordering = ['-id']
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
You would need to set the formated_id after the instance is first saved, which is when the primary key is created. Something along the lines of the following (untested) code should do the trick
class Shipment(models.Model):
formated_id = models.CharField("formatedid",max_length= 50)
class Meta:
ordering = ['-id']
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.formated_id = 'easter{}'.format(self.pk)
super().save(*args, **kwargs)
My model.py:
class RelayAddress(models.Model):
id = models.AutoField(primary_key=True,default=0)
sister_relay_relation = models.ManyToManyField('self', through='RelaySisterRelation',symmetrical=False)
def save(self, *args, **kwargs):
self.update_time = int(time.time())
super(RelayAddress,self).save(*args, **kwargs)
class RelaySisterRelation(models.Model):
id = models.AutoField(primary_key=True,default=0)
relay = models.ForeignKey(RelayAddress,related_name="relay")
sister_relay = models.ForeignKey(RelayAddress,related_name="sister_relay")
My admin.py
class RelaySisterRelationForm(forms.ModelForm):
relay=forms.ModelMultipleChoiceField(label=u'relay',widget=forms.CheckboxSelectMultiple(),queryset=RelayAddress.objects.all())
sister_relay=forms.ModelMultipleChoiceField(label=u'sister_relay',widget=forms.CheckboxSelectMultiple(),queryset=RelayAddress.objects.all())
def save(self, *args, **kwargs):
return super(RelaySisterRelationForm, self).save(*args,**kwargs)
And my view.py is null, then I get a ValueError:
Cannot assign "[<RelayAddress: RelayAddress object>]": "RelaySisterRelation.relay" must be a "RelayAddress" instance.
And how to solve this problem.
RelaySisterRelation.relay is a ForeignKey to RelayAddress meaning it can only store a references to one RelayAddress but your RelaySisterRelationForm.relay uses ModelMultipleChoiceField which is for many-to-many relations so returns a (potentially empty) list of RelayAddress instances.