I got a model containing two counters :
class MyObject(models.Model):
...
student_c = models.PositiveIntegerField(default=0, blank=True, null=True)
company_c = models.PositiveIntegerField(default=0, blank=True, null=True)
def total_followers(self):
return self.student_c + self.company_c
one is working perfectly and returns an integer value but the other one returns :
django.db.models.expressions.ExpressionNode object at 0x7ff4d8320a10
I tried to change PositiveIntegerField to IntegerField and to rename the field with another name but I still get the same result ? I destroyed the database and rebuilt it many times
In my template I can see this : (+: (DEFAULT: ), 1)
In fact I'm trying to do an atomic increment like this:
project = get_object_or_404(Project, pk=kwargs['pk'])
project.student_c = F('student_c') + 1
project.save(update_fields=['student_c']) or even just project.save()
This is where the problem is coming from. I looked there and I found the same code :
Atomic increment of a counter in django
What am I doing wrong ?
Any help would be very appreciated.
Thanks
I'm not sure you're using the F() object correctly. Have you tried just doing
Projects.objects.filter(pk=kwargs['pk']).update(student_c=F('student_c') + 1)
That would replace those three lines. Also you could try this for the second line:
project.student_c = project.student_c + 1
I don't know if this is similar to your problem, but maybe can help you
http://www.voidspace.org.uk/python/weblog/arch_d7_2011_04_30.shtml
Maybe you need to call .save before call total_followers in your view...
For example:
import model.MyObject
myObj = MyObject.objects.create(....)
myObj.save()
myObj.total_followers()
Related
I am familiar with the Django and I am using Django framework(2.2.2) in one of my website, But I am getting one weird issue for saving record with the foreign key:
I have following two models
class quick_note(models.Model):
note_id = models.AutoField(primary_key=True)
meeting_date = models.DateField(max_length=55)
title = models.TextField(blank = True,null=True)
headline = models.TextField(blank = True,null=True)
class quick_note_details(models.Model):
meeting_id = models.ForeignKey(quick_note,on_delete = models.CASCADE)
summary = models.TextField(default='',null=True)
Following is the code I have used for saving:
quick_note_details_data = quick_note_details(summary = summary_data,meeting_id = 1)
quick_note_details_data.save()
Using this I am getting following error:
ValueError: Cannot assign "2": "quick_note_details.meeting_id" must be a "quick_note" instance.
Then, I have tried the following approach suggested in the following question,
Django: ValueError when saving an instance to a ForeignKey Field
quick_note_obj = quick_note.objects.get(note_id = note_id)
quick_note_details_data = quick_note_details(summary = summary_data,meeting_id = quick_note_obj)
quick_note_details_data.save()
Using this I am getting following error:
django.db.utils.ProgrammingError: column "meeting_id_id" of relation "website_quick_note_details" does not exist
LINE 1: INSERT INTO "website_quick_note_details" ("meeting_id_id", "...
I don't have a column like meeting_id_id in the model anywhere, then why I am getting this error?
I have been searching for this long time, but didn't get any solution,
Hope I will get help here.
change meeting_id to meeting_id_id , try following
quick_note_details_data = quick_note_details(summary = summary_data,meeting_id_id = 1)
So, I had got my answer days back, so decided to answer so this will help people like me,
Basically, Django appends a suffix to the foreign_key columns,
e.g if your columns name is note ,Django will assume this as note_id,
So,To avoid this I had done only the following:
note_id = models.ForeignKey(quick_note,on_delete = models.CASCADE,db_column='note_id')
By using db_column property, now the foreign key will refer as note_id,
This solves my issue.
Bonjour, I have a question regarding django-filters. My problem is:
I have two classes defined in my models.py that are:
class Volcano(models.Model):
vd_id = models.AutoField("ID, Volcano Identifier (Index)",
primary_key=True)
[...]
class VolcanoInformation(models.Model):
# Primary key
vd_inf_id = models.AutoField("ID, volcano information identifier (index)",
primary_key=True)
# Other attributes
vd_inf_numcal = models.IntegerField("Number of calderas")
[...]
# Foreign key(s)
vd_id = models.ForeignKey(Volcano, null=True, related_name='vd_inf_vd_id',
on_delete=models.CASCADE)
The two of them are linked throught the vd_id attribute.
I want to develop a search tool that allows the user to search a volcano by its number of calderas (vd_inf_numcal).
I am using django-filters and for now here's my filters.py:
from .models import *
import django_filters
class VolcanoFilter(django_filters.FilterSet):
vd_name = django_filters.ModelChoiceFilter(
queryset=Volcano.objects.values_list('vd_name', flat=True),
widget=forms.Select, label='Volcano name',
to_field_name='vd_name',
)
vd_inf_numcal = django_filters.ModelChoiceFilter(
queryset=VolcanoInformation.objects.values_list('vd_inf_numcal', flat=True),
widget=forms.Select, label='Number of calderas',
)
class Meta:
model = Volcano
fields = ['vd_name', 'vd_inf_numcal']
My views.py is:
def search(request):
feature_list = Volcano.objects.all()
feature_filter = VolcanoFilter(request.GET, queryset = feature_list)
return render(request, 'app/search_list.html', {'filter' : feature_filter, 'feature_type': feature_type})
In my application, a dropdown list of the possible number of calderas appears but the search returns no result which is normal because there is no relation between VolcanoInformation.vd_inf_numcal, VolcanoInformation.vd_id and Volcano.vd_id.
It even says "Select a valid choice. That choice is not one of the available choices."
My question is how could I make this link using django_filters ?
I guess I should write some method within the class but I have absolutely no idea on how to do it.
If anyone had the answer, I would be more than thankful !
In general, you need to answer two questions:
What field are we querying against & what query/lookup expressions need to be generated.
What kinds of values should we be filtering with.
These answers are essentially the left hand and right hand side of your .filter() call.
In this case, you're filtering across the reverse side of the Volcano-Volcano Information relationship (vd_inf_vd_id), against the number of calderas (vd_inf_numcal) for a Volcano. Additionally, you want an exact match.
For the values, you'll need a set of choices containing integers.
AllValuesFilter will look at the DB column and generate the choices from the column values. However, the downside is that the choices will not include any missing values, which look weird when rendered. You could either adapt this field, or use a plain ChoiceFilter, generating the values yourself.
def num_calderas_choices():
# Get the maximum number of calderas
max_count = VolcanoInformation.objects.aggregate(result=Max('vd_inf_numcal'))['result']
# Generate a list of two-tuples for the select dropdown, from 0 to max_count
# e.g, [(0, 0), (1, 1), (2, 2), ...]
return zip(range(max_count), range(max_count))
class VolcanoFilter(django_filters.FilterSet):
name = ...
num_calderas = django_filters.ChoiceFilter(
# related field traversal (note the connecting '__')
field_name='vd_inf_vd_id__vd_inf_numcal',
label='Number of calderas',
choices=num_calderas_choices
)
class Meta:
model = Volcano
fields = ['name', 'num_calderas']
Note that I haven't tested the above code myself, but it should be close enough to get you started.
Thanks a lot ! That's exactly what I was looking for ! I didn't understand how the .filter() works.
What I did, for other attributes is to generate the choices but in a different way. For instance if I just wanted to display a list of the available locations I would use:
# Location attribute
loc = VolcanoInformation.objects.values_list('vd_inf_loc', flat=True)
vd_inf_loc = django_filters.ChoiceFilter(
field_name='vd_inf_vd_id__vd_inf_loc',
label='Geographic location',
choices=zip(loc, loc),
)
I am trying to create a custom primary_key within my helpdesk/models.py that I will use to track our help desk tickets. I am in the process of writing a small ticking system for our office.
Maybe there is a better way? Right now I have:
id = models.AutoField(primary_key=True)
This increments in the datebase as; 1, 2, 3, 4....50...
I want to take this id assignment and then use it within a function to combine it with some additional information like the date, and the name, 'HELPDESK'.
The code I was using is as follows:
id = models.AutoField(primary_key=True)
def build_id(self, id):
join_dates = str(datetime.now().strftime('%Y%m%d'))
return (('HELPDESK-' + join_dates) + '-' + str(id))
ticket_id = models.CharField(max_length=15, default=(build_id(None, id)))
The idea being is that the entries in the database would be:
HELPDESK-20170813-1
HELPDESK-20170813-2
HELPDESK-20170814-3
...
HELPDESK-20170901-4
...
HELPDESK-20180101-50
...
I want to then use this as the ForeignKey to link the help desk ticket to some other models in the database.
Right now what's coming back is:
HELPDESK-20170813-<django.db.models.fields.AutoField>
This post works - Custom Auto Increment Field Django Curious if there is a better way. If not, this will suffice.
This works for me. It's a slightly modified version from Custom Auto Increment Field Django from above.
models.py
def increment_helpdesk_number():
last_helpdesk = helpdesk.objects.all().order_by('id').last()
if not last_helpdesk:
return 'HEL-' + str(datetime.now().strftime('%Y%m%d-')) + '0000'
help_id = last_helpdesk.help_num
help_int = help_id[13:17]
new_help_int = int(help_int) + 1
new_help_id = 'HEL-' + str(datetime.now().strftime('%Y%m%d-')) + str(new_help_int).zfill(4)
return new_help_id
It's called like this:
help_num = models.CharField(max_length=17, unique=True, default=increment_helpdesk_number, editable=False)
If gives you the following:
HEL-20170815-0000
HEL-20170815-0001
HEL-20170815-0002
...
The numbering doesn't start over after each day, which is something I may look at doing. The more I think about it; however, I am not sure if I even need the date there as I have a creation date field in the model already. So I may just change it to:
HEL-000000000
HEL-000000001
HEL-000000002
...
I'm working with django 1.9
Model :
class Comment(models.Model):
title = models.CharField(max_length=250, null=False)
date = models.DateField(auto_now_add=True)
As 'extra()' will be deprecated in django i try to figure out how to count Comments group by year-month without using 'extra'
Here is the code with extra :
Comment.objects.extra(select={'year': "EXTRACT(year FROM date)",
'month': "EXTRACT(month from date)"})\
.values('year', 'month').annotate(Count('pk'))
Thank you for your help.
See year and month in the docs, may be something like the following will do the job:
Comment.objects.annotate(year=Q(date__year),
month=Q(date__month)
).values('year', 'month').annotate(Count('pk'))
If this won't work, then instead of Q(date__year), you could define a custom Func() expression representing EXTRACT(year FROM date) function and use it in annotate(). Or, well, as last resort there's RawSQL().
Using Func(), something like this:
from django.db.models import Func
class Extract(Func):
"""
Performs extraction of `what_to_extract` from `*expressions`.
Arguments:
*expressions (string): Only single value is supported, should be field name to
extract from.
what_to_extract (string): Extraction specificator.
Returns:
class: Func() expression class, representing 'EXTRACT(`what_to_extract` FROM `*expressions`)'.
"""
function = 'EXTRACT'
template = '%(function)s(%(what_to_extract)s FROM %(expressions)s)'
#Usage
Comment.objects.annotate(year=Extract(date, what_to_extract='year'),
month=Extract(date, what_to_extract='month')
).values('year', 'month').annotate(Count('pk'))
I'm a beginner, so please go easy on me. I am working on a script so that I don't have to keep entering in data when I decide to drop the database. My entire script works well, except when I'm dealing with a one-to-many relationship. It will not save to the database. Can anyone tell me what I am doing wrong or point me in the right direction?
SCRIPT:
try:
pmod.Instrument.objects.get(title='kjkjsdfsadfs')
except pmod.Instrument.DoesNotExist:
u = pmod.Instrument()
u.title = 'Bach 42 Trombone'
u.price = 550.00
u.soundDescription = 'Good'
u.functionalityDescription = 'Good'
u.damageDescription = 'Good'
u.accessoryDescription = 'Good'
u.customerName = 'Jake'
u.customerEmail = 'ks#gmail.com'
u.instrumentCategory = 1
print('Good2')
u.save()
print('Instrument1 saved')
MODEL:
class Category(models.Model):
instrumentCategory=models.CharField(max_length=50,blank=True,null=True)
def __str__(self):
return self.instrumentCategory
class Instrument(models.Model):
title = models.CharField(help_text='title',max_length=50,blank=True,null=True)
price = models.DecimalField(max_digits=8, decimal_places=2)
soundDescription=models.CharField(max_length=1000,blank=True,null=True)
functionalityDescription=models.CharField(max_length=1000,blank=True,null=True)
damageDescription=models.CharField(max_length=1000,blank=True,null=True)
accessoryDescription=models.CharField(max_length=1000,blank=True,null=True)
customerName=models.CharField(max_length=50,blank=True,null=True)
customerEmail=models.EmailField(max_length=254,help_text='Enter valid email address')
instrumentCategory=models.ForeignKey(Category)
u.instrumentCategory = 1
That's not how a models.ForeignKey field works in Django. You need to get an instance of the Category object and assign that to u.instrumentCategory.
u.instrumentCategory = pmod.Category.objects.get(id=1)
You may try :
u.instrumentCategory_id = 1