I'm trying to set reportNr field default to a number that iterates every time a report has been added. Is there any way to do this?
In models.py:
from django.db import models
class RapportQuerySet(models.query.QuerySet):
def active(self):
return self.filter()
class RapportManager(models.Manager):
def get_queryset(self):
return RapportQuerySet(self.model, using=self._db)
def all(self):
return self.get_queryset().active()
class Rapport(models.Model):
objects = RapportManager()
reportNr = models.TextField(blank=True, default="?")
avd = models.TextField(max_length=10, null=True, blank=True)
ritningNr = models.TextField(max_length=20, null=True, blank=True)
enhetsNr = models.TextField(max_length=40, null=True, blank=True)
atgard = models.TextField(max_length=100,null=True, blank=True)
namn = models.TextField(max_length=100,null=True, blank=True)
anstNr = models.TextField(max_length=100,null=True, blank=True)
date = models.DateTimeField()
file = models.FileField(null=True, blank=True)
def __str__(self):
return self.reportNr
what is the report (I do not see any relations with report), if it model instance then:
reportNr = = models.IntegerField(default=0) - must be integer
Also you can override create method
def save(self, *args, **kwargs):
super(Report, self).save(*args, **kwargs)
#Iterate the reportNr
Hopefully, I understand right) If not can you describe problem in details
Related
what i want to do is compute the value in percent for each learning styles there are and save them as default value to the field **result** on AssessmentLearningStyle model
here is the model
#MODEL_FOURTEEN
class QuestionResults(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
student = models.ForeignKey(to=FacilityUser, on_delete=models.SET_NULL, null=True, blank=True)
question = models.ForeignKey(to=QuestionLearningStyle, on_delete=models.SET_NULL, null=True, blank=True)
agree = models.BooleanField(null=False)
disagree = models.BooleanField(null=False)
def __str__(self):
return str(self.question)
#MODEL_FIFTEEN
class AssessmentLearningStyle(models.Model):
#property
def test(self):
u = self.learning_style
s = 0
if u == QuestionResults.question.learning_style:
k = int(QuestionResults.objects.filter(agree=True, question__learning_style=self.learning_style).count())
l = int(QuestionResults.objects.filter(question__learning_style=self.learning_style).count())
if l != 0:
s = (k/l) * 100
else:
s = 0
return float(s)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
student = models.ForeignKey(to=FacilityUser, on_delete=models.SET_NULL, null=True, blank=True)
assessent_date = models.DateField(blank=True, null=True)
learning_style = models.ForeignKey(to=LearningStyle, on_delete=models.SET_NULL, null=True, blank=True)
result = models.FloatField(default=test, editable=False)
def __str__(self):
return str(self.student)
i want to save the value of test function to the result field...but it says float can't accept the value of property...and if i remove property... this method doesn't work at all...can you guys help me to fix this or show me a better way of doing this?
Blockquote
Have tried overriding the save function
Class AssignmentLearningStyle(models.Model):
def save(self, *args, **kwargs):
self.result = self.test
super(AssignmentLearningStyle, self).save(*args, **kwargs)
I've two model. I would like to save data from ForeignKey model. I'm created a modelform and save with my main foreignkey model. But I got this error ValueError at /c/customer/1/
Cannot assign "'1'": "BillingData.customer" must be a "CustomerData" instance.
I created Django model form and hocked up with view.
models.py file
class CustomerData(models.Model):
customer_name = models.CharField(max_length=100)
customer_no = models.CharField(max_length=100, default='', blank=True)
mobile_number = models.IntegerField()
alternative_phone = models.IntegerField(null=True, blank=True)
union_name = models.ForeignKey(UnionName, on_delete=models.SET_NULL, null=True)
word_name = models.ForeignKey(UnionWordName, on_delete=models.SET_NULL, null=True)
full_address = models.CharField(max_length=200, null=True, blank=True)
create_date = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return '%s, Mobile: %s' % (self.customer_name, self.mobile_number)
def get_absolute_url(self):
return reverse('customer_data', kwargs={'pk': self.pk})
class BillingData(models.Model):
bill_no = models.CharField(max_length=100, default='', blank=True)
customer = models.ForeignKey(CustomerData, on_delete=models.CASCADE)
sales_person = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True)
customer_money = models.IntegerField()
create_date = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return '%s %s' % (self.customer.customer_name, self.create_date.date())
def get_absolute_url(self):
return reverse('customers.views.BillingPage', kwargs={'pk': self.pk})
forms.py file
class BillCreateForms(forms.ModelForm):
bill_no = forms.CharField(max_length=100)
customer = forms.ChoiceField(choices=[(x.id, x.customer_name) for x in CustomerData.objects.all()])
customer_money = forms.IntegerField()
def save(self, commit=True):
instance = super(BillCreateForms, self).save(commit=False)
customer_pk = self.cleaned_data['customer']
instance.customer = CustomerData.objects.get(pk=customer_pk)
instance.save(commit)
return instance
class Meta:
model = BillingData
fields = ('bill_no', 'customer', 'customer_money',)
views.py file
class CustomerDataView(FormMixin, generic.DetailView):
model = CustomerData
form_class = BillCreateForms
template_name = "customers/customerdata_detail.html"
print(form_class)
success_url = '/c/'
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
I expect data save with foreignkey relation data. But doesn't save here.
You can't fix this problem in the save method, because the error happens before it gets that far.
You should be using a ModelChoiceField, not a ChoiceField. Not only would this fix the problem, it would also let you remove your entire save method.
customer = forms.ModelChoiceField(queryset=CustomerData.objects.all())
Change this line
instance.customer = CustomerData.objects.get(pk=customer_pk)
to
instance.customer_id = CustomerData.objects.get(pk=customer_pk).pk
Model:
class Blog(models.Model):
# ...
pass
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, null=True)
Set object
b = Blog.objects.get(id=1)
e = Entry.objects.get(id=234)
b.entry_set.add(e)
Here i have two models.In these models i want to make the value of amount_to_pay dynamic in Ledger model.For Example i have two different forms for these two models and while saving expense form if the user select the payment_option which comes from ledger model and gives some value for the amount_to_pay field then if only ledger.id and expense.payment_option_id are same then the value of amount_to_pay in ledger model should be replaced with that value.how can i do it ?
models.py
class Expense(models.Model):
pay_from = models.CharField(max_length=200)
payment_option = models.ForeignKey('Ledger', on_delete=models.CASCADE)
amount_to_pay = models.IntegerField(default=0)
expense_date = models.DateField(default=datetime.date.today)
expense_type = models.ForeignKey(ExpenseType, on_delete=models.CASCADE)
note = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = AutoSlugField(unique_with='id', populate_from='expense_type')
def get_amount_to_pay(self):
return self.amount_to_pay
class Ledger(models.Model):
name = models.CharField(max_length=200)
account_number = models.CharField(max_length=250, unique=True)
account_type = models.CharField(max_length=200)
opening_balance = models.IntegerField(default=0)
amount_to_pay = models.IntegerField(default=0, blank=True, null=True)
current_balance = models.IntegerField(default=0, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = AutoSlugField(unique_with='id', populate_from='name')
def save(self, *args, **kwargs):
self.amount_to_pay = Expense.get_amount_to_pay(self)
# here how can i save the amount_to_pay from expense form if the ledger.id and expense.payment_option.id matches??
#i got stuck here.
self.current_balance = self.opening_balance - self.amount_to_pay
super(Ledger, self).save(*args, **kwargs)
Solution One:
I think instead of changing in Ledger model, you should change in Expense model, like this:
class Expense(models.Model):
...
def save(self, *args, **kwargs):
self.payment_option.amount_to_pay = self.payment_option.amount_to_pay + self.amount_to_pay
self.payment_option.save()
super(Expense, self).save(*args, **kwargs)
Solution Two:
But to be honest, Solution One does not seem good to me. Reason is that you are saving same data in 2 places(in both expense and ledger). Instead, it should be once, then the amount_to_pay value in Ledger should be calculated dynamically. Like this:
from django.db.models import Sum
class Ledger(...):
#property
def amount_to_pay(self):
# I am using a property method to show the amount_to_pay value.
# FYI: in this way, you need to remove amount_to_pay field from Ledger model
return self.opening_balance - self.expense_set.all().aggregate(a_sum=Sum('amount_to_pay')).get('a_sum', 0)
In that way, with each ledger, the value amount_to_pay will be dynamically calculated at runtime. For example:
for l in Ledger.objects.all():
l.amount_to_pay
Solution Three:
If you are wary of making DB hits with each l.amount_to_pay(as it calculates amount_to_pay from DB dynamically) from previous solution, then you can always annotate the value. Like this:
For this solution, you need to change your Expense model and add a related_name:
class Expense(models.Model):
pay_from = models.CharField(max_length=200)
payment_option = models.ForeignKey('Ledger', on_delete=models.CASCADE, related_name='expenses')
Then use that related_name in query like this(FYI: You can't keep def amount_to_pay(...) method in Ledger model for the following usage example):
from django.db.models import Sum, F, ExpressionWrapper, IntegerField
ledgers = Ledger.objects.all().annotate(expense_sum=Sum('expenses__amount_to_pay')).annotate(amount_to_pay=ExpressionWrapper(F('opening_balance') - F('expense_sum'), output_field=IntegerField()))
# usage one
for l in ledgers:
l.amount_to_pay
# usage two
ledgers.values('amount_to_pay')
Best thing is you override the call in save method any way you have foreginkey.
def save(self, *args, **kwargs):
#self.date_created = timezone.now()
# YOUR LOGIC HERE
super(YOUR_OVERRIDING_MODEL , self).save(*args, **kwargs
check if Ledger have child and then update it:
class Expense(models.Model):
def save(self, *args, **kwargs):
self.payment_option.amount_to_pay = self.payment_option.amount_to_pay + self.amount_to_pay
self.payment_option.save()
super(Expense, self).save(*args, **kwargs)
Override save method and update some field dynamically in django
For my case i wanted to update done column in answer model dynamically when i comment on an answer it should return true instead of False. So in my example i am checking for whether that column done which is boolean is False and if it's False,i change it's status to True using the answer object from Comment and then save the answer object, see more about update vs insert fields https://docs.djangoproject.com/en/3.2/ref/models/instances/
class Answer(models.Model):
user = models.ForeignKey("User", on_delete=models.CASCADE, blank=True, null=True)
username = models.CharField(max_length=250)
codeAnswer = models.CharField(max_length=250)
girAnswer = models.CharField(max_length=250)
correct = models.BooleanField(default=False)
firebaseToken = models.CharField(max_length=250)
done = models.BooleanField(default=False)
created_at = models.DateTimeField()
updated_at = models.DateTimeField(auto_now=True)
def __unicode__(self):
return "{0}: {1}".format(self.username, self.value)
def __str__(self):
return "%s" % (self.codeAnswer)
# So here i override the save method in the Comment model to do what i want as below.
class Comment(models.Model):
answer = models.ForeignKey("Answer", on_delete=models.CASCADE, blank=False , related_name="comments")
writerName = models.CharField(max_length=250)
content = models.CharField(max_length=250)
deleted = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return "%s" % (self.writerName)
def save(self, *args, **kwargs):
if self.answer.done is False:
self.answer.done = True
self.answer.save()
super(Comment, self).save(*args, **kwargs)
Hope it answers the question above thanks
I have followed many examples and docs, but cannot get this right.
I'm trying to make my Elasticsearch index whenever I update a model. Using the 'autoindex' does not log M2M's.
When I change a value inside Tag it should update the index of all the Items is is in
I am using django-elasticsearch (here) which is a wrapper around elasticsearch-py.
When I try connect(tag_index, sender=Tag.item.through) it cannot find tag as it hasn't been imported by models yet.
How is this correctly achieved?
class Tag(models.Model):
name = models.CharField(max_length=500, blank=True)
taglevel = models.IntegerField(null=True, blank=True)
def tag_index(instance, **kwargs):
Task.instance.es.do_index()
class Item(EsIndexable, models.Model):
title = models.CharField(max_length=100, blank=True)
tag = models.ManyToManyField('Tag', blank=True)
class Elasticsearch(EsIndexable.Elasticsearch):
serializer_class = TaskEsSerializer
fields = ['title', 'tag']
#receiver(post_save, sender= Task)
def index_elastic(instance, **kwargs):
instance.es.do_index()
m2m_changed.connect(tag_index, sender=Item.tag.through)
Ok, it isn't as "smart" as I thought it was. You need to refer to functions in each model
class Tag(models.Model):
name = models.CharField(max_length=500, blank=True)
taglevel = models.IntegerField(null=True, blank=True)
#receiver(post_save, sender= Tag)
#receiver(post_delete, sender= Tag)
def index_tag(instance, **kwargs):
Item.objects.get().es.do_index()
def tag_index(instance, **kwargs):
instance.es.do_index()
class Item(EsIndexable, models.Model):
title = models.CharField(max_length=100, blank=True)
tag = models.ManyToManyField('Tag', blank=True)
class Elasticsearch(EsIndexable.Elasticsearch):
serializer_class = ItemEsSerializer
fields = ['title', 'tag']
#receiver(post_save, sender= Item)
def index_elastic(instance, **kwargs):
instance.es.do_index()
I am working on a blog like project but different and I have recently started learning Django. So, in my app we have categories and tags as well. Now there's an Entry model which has ManyToMany relation with both Category and Tag. Now I am trying to get all the Entries which falls under a particular category, it's a similar feature that we have in blogs.
Following is my Tag and Category Model.
class CategoryQuerySet(models.QuerySet):
def category_menu(self):
return self.filter(intopmenu=True)
def top_catgories(self):
return self.order_by("views")[:5]
class Category(models.Model):
name = models.CharField(max_length=50, unique=True)
views = models.IntegerField(default=0)
intopmenu = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
slug = models.SlugField(unique=True)
objects = CategoryQuerySet.as_manager()
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Category, self).save(*args, **kwargs)
def __str__(self):
return self.name
class Meta:
verbose_name = "Entry Category"
verbose_name_plural = "Entry Categories"
ordering = ["created"]
class Tag(models.Model):
name = models.CharField(max_length=20)
slug = models.SlugField(max_length=200, unique=True)
def __str__(self):
return self.slug
Following is my Entry Model.
class EntryQuerySet(models.QuerySet):
def published(self):
return self.filter(publish=True)
def most_liked(self, num):
return self.order_by("-likes")[:num]
def most_views(self, num):
return self.order_by('-views')[:num]
class Entry(models.Model):
image = models.ImageField(upload_to='entries_images/', null=True)
image_alt = models.CharField(max_length=200, blank=True)
name = models.CharField(max_length=50, blank=True)
text = models.CharField(max_length=500, unique=True)
views = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
publish = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
source = models.URLField(blank=True)
slug = models.SlugField(unique=True)
categories = models.ManyToManyField(Category)
tags = models.ManyToManyField(Tag)
objects = EntryQuerySet.as_manager()
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Entry, self).save(*args, **kwargs)
def __str__(self):
return self.text
class Meta:
verbose_name = "Entry"
verbose_name_plural = "Entries"
ordering = ["created"]
In my urls.py I have the following url to view all entries by that fall under a particular category.
url(r'^category/(?P<category_slug>[\w\-]+)/$', views.category, name='category'),
Apparently, I don't understand how to write the view to retrieve list of all the entries falling under particular category or tag. Any help will be appreciated. I did refer many blog posts on the web regarding my problem and also searched SO, 1 is a similar question I found but that didn't help much.
try:
def category(request,category_slug):
category = get_object_or_404(Category,slug=category_slug)
return render(request,'template_name.html',{'category':category,'posts':category.entry_set.all()})
More information on https://docs.djangoproject.com/en/1.9/topics/db/examples/many_to_many/