I'm working with Django 1.7.2 with generic relation (reason: project has two databases), and after import I don't want to have overwritten database.
I want to show only active season
Here is my model, is overwritten after import:
class Season(models.Model):
name = models.CharField('Name', max_length=255)
start = models.DateField('Start')
end = models.DateField('End')
def __unicode__(self):
return self.name
In another place in models.py file I create Generic relation to another model (SaleAndCycle) in another database:
def extend_models(sender, **kwargs):
if sender._meta.app_label != 'extend':
return
def set_stati(self, database='extend', save=True):
online_before = self.online
self.online = True
for flag in self.flags:
if flag.flag == 'offline':
self.online = False
if save and self.online != online_before:
self.save(using=database)
for name, name_singular, name_plural in (
('Season', 'Season', 'Seasons'):
if sender.__name__ == name:
sender._meta.verbose_name = name_singular
sender._meta.verbose_name_plural = name_plural
if sender.__name__ == 'Season':
sender.add_to_class('sale_and_cycles', generic.GenericRelation(SaleAndCycle))
sender.add_to_class('is_sale_active', property(
lambda o: o.sale_and_cycles.using('default')))
sender.add_to_class('is_cyclic_event_active', property(
lambda o: o.sale_and_cycles.using('default')))
sender.add_to_class('cycle_link', property(
lambda o: o.sale_and_cycles.using('default')))
I want to show all active Seasons for not login user:
def get_queryset(self):
seasons = Season.objects.all()
if not self.request.user.is_superuser:
all_seasons = Season.objects.filter(events_isactiveflags__is_active=True)
print all_seasons
I get error:
no such table: events_isactiveflag
But this table exists in my database.
by the line of code
Season.objects.filter(events_isactiveflags__is_active=True)
here events_isactiveflags__is_active=True means events_isactiveflags is a table and is_active is a column of the table. So no such table found named events_isactiveflags . if you are trying to get active sessions you can try this code
Session.objects.filter(expire_date__gte=timezone.now())
delete db and once again run syncdb
I have two db tables in django: "Device" table to store actual devices and "DeviceTest" table to store test checks for each device (Many Tests to one Device).
class Device(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=20)
serial_number = models.CharField(max_length=20)
def __unicode__(self):
return self.name + " - " + self.serial_number
class DeviceTest(models.Model):
device = models.ForeignKey(Device)
created_at = models.DateTimeField(auto_now_add=True)
TEST_OK = '+'
TEST_ERROR = '-'
TEST_RESULT_CHOICES = (
(TEST_OK, 'Test Success'),
(TEST_ERROR, 'Test Error'),
)
status = models.CharField(max_length=1, choices=TEST_RESULT_CHOICES, default=TEST_ERROR)
comment = models.TextField(blank=True, default="")
tester = models.CharField(max_length=255)
action = models.CharField(max_length=255)
def __unicode__(self):
return self.device.name + " - " + \
self.device.serial_number + " - " + \
unicode(self.created_at) + " - " + \
u"Result (" + self.status + ")"
I've made HTML page with table of all devices in format:
name | serial number | created_at | last_test_time | last_test_status | hyperlink to test table page
Now I want to give user all sorting possibilities. I've done that through GET parameters for "name", "serial number" and "created_at" fields. And now I'm stuck with "last_test_time" and "last_test_status" fields.
Can this problem be solved with some standard Django functions? Something like Device.objects.all().filter(???).order_by(???)
You can annotate the queryset with the latest created_at time.
from django.db.models import Max
queryset = Device.objects.annotate(last_test_time=Max('devicetest__created_at'))
You can access last_test_time for each object.
for obj in queryset
print(obj.last_test_time)
And you can order the queryset by this field
queryset = queryset.order_by('last_test_time')
However, this is only a partial answer, because it does not help you get the status of that test.
You could do a lookup for each device individually.
for device in queryset:
device.latest_status = device.device_test.latest('created_at').status
This is ok if the number of devices is small, but it means one query for each device, which isn't ideal as the number of devices increases.
You can use prefetch_related to fetch all the related device tests in one query. (the code below is untested, I might have the syntax slightly wrong).
queryset = queryset.prefetch_related(Prefetch('devicetest', DeviceTest.objects.order_by('-created_at'))
You can then get the status via the first related device test.
for obj in queryset:
print obj.devicetest.all()[0].status
Note this is inefficient, because you have loaded all related items, not just the most recent one.
I want to add a new field when somebody checks an option in my web page ("Add column 'external id' ")
table = IssueTable(issue_list)
show_ext = request.GET.get('show_ext', 0)
if show_ext:
table._meta.fields = table._meta.fields + ('external_id',)
I thought doing that it was the solution but I didn't succeed. The external_id is part of the model. table._meta.fields doesnt get updated and of course I cannot see the column in the table when this one is rendered.
class IssueTable(tables.Table):
def render_id(self, value, record):
if record.status.upper() in ['RESOLVED', 'INVALID']:
return mark_safe('<s>#%s</s>' % (reverse('issues.views.view', args=(record.pk,)), record.pk))
else:
return mark_safe('#%s' % (reverse('issues.views.view', args=(record.pk,)), record.pk))
def render_title(self, value, record):
return mark_safe('%s' % (reverse('issues.views.view', args=(record.id,)), value))
class Meta(object):
model = Issue
fields = ('id', 'title', 'product', 'type', 'priority', 'status', 'created')
attrs = {'class': 'table table-bordered'}
empty_text = _('No records found')
Any ideas?
I am using Django admin to filter objects on their reverse ForeignKey objects field value. The App has a ForeignKey to Contact and I am trying to filter Contacts by Apps category in Django admin. The problem is that the query is very large and I am getting a timeout error. There are around 300k Contact objects and around 1M of Apps. There are 500 results per page in Django admin. The db indexes and prefetch_related are added. What else should I do to optimise Django admin ? I am using sqlite db.
The code:
class App(models.Model):
contact = models.ForeignKey('Contact', related_name='apps', null=True)
category = models.TextField(blank=True, null=True, db_index=True)
store = models.IntegerField(choices=STORE_TYPES, db_index=True)
class Meta:
index_together = [
['category', 'store'],
]
# admin:
class ContactAdmin(admin.ModelAdmin):
list_filter = (
AppCategory,
)
def queryset(self, request):
return super(ContactAdmin, self).queryset(request).prefetch_related(
'apps',
'to_contact',
)
# the main list_filter that is causing troubles:
class AppCategory(admin.SimpleListFilter):
title = 'app category'
parameter_name = 'app_category'
def lookups(self, request, modelAdmin):
return [
('Action', 'Action'),
('Adventure', 'Adventure'),
('Arcade', 'Arcade'),
('Board', 'Board'),
('Books', 'Books'),
('Books & Reference', 'Books & Reference'),
('Business', 'Business'),
('Card', 'Card'),
('Casino', 'Casino',),
('Casual', 'Casual'),
('Catalogs', 'Catalogs'),
('Comics', 'Comics'),
('Communication', 'Communication'),
('Education', 'Education'),
('Educational', 'Educational'),
('Entertainment', 'Entertainment'),
('Family', 'Family'),
('Finance', 'Finance'),
('Food & Drink', 'Food & Drink'),
('Games', 'Games'),
('Health & Fitness', 'Health & Fitness'),
('Libraries & Demo', 'Libraries & Demo'),
('Lifestyle', 'Lifestyle'),
('Media & Video', 'Media & Video'),
('Medical', 'Medical'),
('Music', 'Music'),
('Music & Audio', 'Music & Audio'),
('Navigation', 'Navigation'),
('News', 'News'),
('News & Magazines', 'News & Magazines'),
('Personalization', 'Personalization'),
('Photo & Video', 'Photo & Video'),
('Photography', 'Photography'),
('Productivity', 'Productivity'),
('Puzzle', 'Puzzle'),
('Racing', 'Racing'),
('Reference', 'Reference'),
('Role Playing', 'Role Playing'),
('Shopping', 'Shopping'),
('Simulation', 'Simulation'),
('Social', 'Social'),
('Social Networking', 'Social Networking'),
('Sports', 'Sports'),
('Strategy', 'Strategy'),
('Tools', 'Tools'),
('Transportation', 'Transportation'),
('Travel', 'Travel'),
('Travel & Local', 'Travel & Local'),
('Trivia', 'Trivia'),
('Utilities', 'Utilities'),
('Weather', 'Weather'),
('Word', 'Word')
]
def queryset(self, request, queryset):
if not self.value():
return queryset
else:
qs = queryset.filter(
apps__category=self.value()
)
return qs
I found out the answer. If you are filtering on one reverse ForeignKey relationship (apps__category in this case) everything works fine. But I forgot to mention that I am combining two filters at the right side of Django admin page - the other one is also a reverse ForeignKey - apps__store. When you are doing that, two completely same INNER JOINs are performed and this results in a server timeout. When I am using these filters separately, everything works fine.
See: https://code.djangoproject.com/ticket/16554
I am currently writing unit tests for my Django webapp and have come across a stumbling block.
My Model:
class Employment(models.Model):
applicant = models.ForeignKey(Applicant)
company = models.CharField(max_length=50)
town = models.CharField(max_length=50)
salary = models.CharField(max_length=50)
job_title = models.CharField(max_length=50)
responsibilities = models.CharField(max_length=100)
date_from = models.DateField('Date From')
date_to = models.DateField('Date To')
reason_for_leaving = models.CharField(max_length=50)
My Form:
class EmploymentForm(forms.ModelForm):
error_css_class = 'error' #set some css when an error
company = forms.CharField(label="Company/Agency")
town = forms.CharField(label="Town/City")
salary = forms.CharField(label="Salary/Pay rate")
date_from = forms.DateField(('%d/%m/%Y',), widget=forms.DateInput(format='%d/%m/%Y', attrs={'placeholder':'dd/mm/yyyy'}))
date_to = forms.DateField(('%d/%m/%Y',), widget=forms.DateInput(format='%d/%m/%Y', attrs={'placeholder':'dd/mm/yyyy'}))
class Meta:
model = Employment
My Test:
"""
Complete employment form passes validation
"""
def test_employment_form_complete(self):
applicant = Applicant(job_id=1)
data = {
'company': 'test company',
'town': 'test town',
'salary': '1000000',
'job_title': 'test job name',
'responsibilities': 'test responsibilities',
'date_from': '01/01/1990',
'date_to': '01/02/1991',
'reason_for_leaving': 'test reason for leaving'
}
employment_form = EmploymentForm(instance=applicant, data=data)
result = employment_form.is_valid()
print "errors %s" % employment_form.errors
self.assertEqual(result, True)
If I run the test like this I get:
<ul class="errorlist"><li>applicant<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
If I add:
'applicant': applicant
to my data object it complains it need to be an int.
If I add:
'applicant': 1
(or another integer)
it returns:
<ul class="errorlist"><li>applicant<ul class="errorlist"><li>Select a valid choice. That choice is not one of the available choices.</li></ul></li></ul>
which is understandable really.
How can I get around this? What is the best practise?
Regards,
Chris.
I think You should call applicant.save()
You create new object, but did't save it to database. while testing django create "temporary" database.
Also add to data dictionary 'applicant': 1.
PS. Make sure applicant object will be created with foreign key=1!!
Completely working code.
def test_employment_form_complete(self):
"""
Complete employment form passes validation
"""
applicant = Applicant(job_id=1)
applicant.save()
data = {
'applicant': 1,
'company': 'test company',
'town': 'test town',
'salary': '1000000',
'job_title': 'test job name',
'responsibilities': 'test responsibilities',
'date_from': '01/01/1990',
'date_to': '01/02/1991',
'reason_for_leaving': 'test reason for leaving'
}
employment_form = EmploymentForm(instance=applicant, data=data)
result = employment_form.is_valid()
print "errors %s" % employment_form.errors
self.assertEqual(result, True)