I am using ModelForm to allow multiple rows edit at the same time. It is a very simple form that has series of yes_no columns. The model looks like:
models.py
class Yn(models.Model):
yn_id = models.IntegerField(primary_key=True)
description = models.CharField(max_length=30)
def __str__(self):
return ' '.join([
self.description,
])
class Meta:
managed = False
db_table = 'yn'
class Invoice(models.Model):
description = models.CharField(max_length=50)
invoice_date = models.DateTimeField()
...
invoice_sent_yn = models.ForeignKey('Yn', models.DO_NOTHING, db_column='invoice_sent_yn', related_name="invoice_sent_yn")
confirm_receipt_yn = models.ForeignKey('Yn', models.DO_NOTHING, db_column='confirm_receipt_yn', related_name="confirm_receipt_yn")
paid_yn = models.ForeignKey('Yn', models.DO_NOTHING, db_column='paid_yn', related_name="paid_yn")
forms.py
class InvoiceGridEdit(ModelForm):
model = Invoice
fields = ['description','invoice_date','invoice_sent_yn', 'confirm_receipt_yn', 'paid_yn']
def __init__(self, *args, **kwargs):
super(JurisGridEditForm, self).__init__(*args, **kwargs)
...
...
InvoiceFormSet = modelformset_factory(models.Invoice, form=InvoiceGridEdit)
views.py
class InvoiceUpdateGrid(CreateView):
template_name = "/invoice_update_grid.html"
model = Invoice
form_class = InvoviceViewEditForm
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return redirect("account_login")
def get(self, request, *args, *kwargs):
self.object = None
customer_number = self.request.GET.get('customer_number')
invoice_form = InvoiceFormSet(queryset=Invoice.objects.filter(customer_number = customer_number)
return self.render_to_response(self.get_context_data(invoice_form=invoice_form))
def post(self, request, *args, **kwargs):
self.object = None
invoice_form = InvoiceFormSet(self.request.POST)
if (invoice_form.is_valid()):
return self.form_valid(invoice_form)
else:
return self.form_invalid(invoice_form)
def form_valid(self, invoice_form):
...
...
invoice_form.save()
return redirect("customer_list")
def form_invalid(self, invoice_form):
return self.render_to_response(self.get_context_data(invoice_form=invoice_form))
The forms works fine, get and post works, except, it takes a while (~30 sec) to retrieve and update. Using django-debug-toolbar, it looks like the yn columns retrieve separately for each column for each row (~2k rows). The Yn table only has 3 rows -1 - Unknown, 0 - No, 1 - Yes.
I tried to search for work around to stop the craziness of Django hitting the DB 900 times per retrieval. I found something about caching but I have no idea how to do it.
Thanks in advance.
Related
class PlayerList(models.Model):
name = models.CharField(max_length=300)
position = models.CharField(max_length=200)
h_code = models.ForeignKey(HList, related_name="h_code", on_delete=models.CASCADE)
d_code = models.CharField(primary_key=True, max_length = 200, editable=False)
Serializers.py
class PlayerSerializer(serializers.ModelSerializer):
class Meta:
fields = ["name", "position", "h_code", "d_code"]
model = PlayerList
view.py
class PostPlayer(generics.ListCreateAPIView):
queryset = PlayerList.objects.all().order_by('-d_code')
serializer_class = PlayerListSerializer
def get(self, request, *args, **kwargs):
d_code = request.data.get('h_code') + 'test'
print(d_code)
print(d_code) :
h000001test
When entering a value through api, I want to implement that the entered value is changed to another value in view.py and saved in the db.
I want to save d_code processed by def get in db.
I don't know what to do. Can you please let me know?
There is no answer, so I will post again.
You can override your views perform_create() method, as stated in the docs (you might have to scroll a little, its in the Save and deletion hooks section:
class PostPlayer(generics.ListCreateAPIView):
queryset = PlayerList.objects.all().order_by('-d_code')
serializer_class = PlayerListSerializer
def get(self, request, *args, **kwargs):
d_code = request.data.get('h_code') + 'test'
print(d_code)
...
...
def perform_create(self, serializer):
d_code = request.data.get('h_code') + 'test'
#do something with d_code
new_code = d_code + 'someSampleValue'
serializer.save(d_code=new_code)
I have a ModelForm for a parent model and and an InlineForm for a foreign key related model. The Inline form data is read only and can only be updated via a file upload. I have this working on the intial creation and save, but if you replace the students by uploading a new file, while the data updates properly after the upload and save, the inline form doesn't reload properly right after this save and displays an error. However, if you navigate away and return everything looks good.
Models.py
class Room(models.Model):
room_id = models.AutoField(primary_key=True)
name = models.TextField(blank=False, verbose_name = "Room Name ")
code = models.TextField(blank=False)
file = models.TextField(blank=False)
class Meta(object):
managed = False
db_table = 'public\".\"room'
class Student(models.Model):
room = models.ForeignKey(Room, related_name="students, to_field="room_id", db_column="room_id")
student_id = models.TextField(blank=False, primary_key=False)
#property
def grade(self):
return util.get_grade(self.student_id)
class Meta(object):
managed = False
db_table = 'public\".\"student’
admin.py
class StudentsInline(admin.TabularInline):
model = Student
form = StudentInlineForm
formset = StudentFormSet
readonly_fields = ('student_id', 'grade')
extra = 0
def get_actions(self, request):
'''
Removes the delete action
'''
actions = super(StudentsInline, self).get_actions(request)
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
def has_add_permission(self, request, obj=None):
return False
class RoomAdmin(admin.ModelAdmin):
def student_count(self, obj):
return obj.students.count()
student_count.short_description = " Total Enrolled "
form = RoomForm
list_display = [name', ‘code']
readonly_fields = ['student_count']
list_per_page = 25
inlines = [StudentsInline]
def get_actions(self, request):
actions = super(RoomAdmin, self).get_actions(request)
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
def save_formset(self, request, form, formset, change):
form.instance.file = 'processed file'
form.instance.save
formset.save()
forms_admin.py
class RoomsForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(RoomsForm, self).__init__(*args, **kwargs)
self.fields[‘name'].required = True
self.fields[‘code'].required = True
self.fields['file'] = forms.FileField(
label='Upload your enrollees:'
def load_file(self, upload_file):
student_list = []
data = upload_file.read() #simplified for this example
for s in reader:
s_id = s[0]
new_student = Student(student_id=s_id)
student_list.append(new_student)
return student_list
def save(self, *args, **kwargs):
room_form = super(RoomsForm, self).save(commit=False)
enrollee_list = self.load_file(self.instance.file.file)
if instance.room_id is None:
instance.file = 'uploaded'
instance = super(RoomsForm, self).save(commit=True)
Student.objects.filter(room_id=self.instance.room_id).all().delete()
instance.students.add(*enrollee_list)
return instance
class Meta:
model = Room
fields = '__all__'
class StudentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(StudentForm, self).__init__(*args, **kwargs)
My models.py looks like this :
class Prescription(models.Model):
date_prescribed = models.DateTimeField()
doctor = models.ForeignKey(Doctor)
pharmacy = models.ForeignKey(Pharmacy)
class Doctor(models.Model):
name = models.CharField(max_length=150)
age = models.PositiveSmallIntegerField()
class Pharmacy(models.Model):
name = models.CharField(max_length=150)
status = models.CharField()
In my views,I want the count of prescriptions grouped by month.I am using Django rest framework.My views.py is as follows:
class PrescriptionTrendListView(generics.ListAPIView):
queryset = Prescription.objects.all()
serializer_class = LineGraphSerializer
def get_queryset(self):
end_date = timezone.now()
start_date = end_date - relativedelta(months=6)
truncate_date = connection.ops.date_trunc_sql('month', 'date_prescribed')
qs = super().get_queryset.extra(select={'month': truncate_date})
return qs.filter(date_prescribed__range=(start_date, end_date)
).annotate(pk_count=Count('pk')).order_by('month')
def get(self, request, *args, **kwargs):
graph_data = self.get_queryset().values('pk_count', 'month')
serializer = self.get_serializer(data=graph_data, many=True)
return Response(serializer.data)
However,the error I get when I run this is :
I am assuming this has something to do with new style classes in Python 3.0.But that is all i know.Any help on how to fix this on 2.x ?
Your super() call in get_queryset is missing the type and self arguments.
class PrescriptionTrendListView(generics.ListAPIView):
queryset = Prescription.objects.all()
serializer_class = LineGraphSerializer
def get_queryset(self):
end_date = timezone.now()
start_date = end_date - relativedelta(months=6)
truncate_date = connection.ops.date_trunc_sql('month', 'date_prescribed')
# Bug was here
qs = super(PrescriptionTrendListView, self).get_queryset.extra(select={'month': truncate_date})
return qs.filter(date_prescribed__range=(start_date, end_date)
).annotate(pk_count=Count('pk')).order_by('month')
def get(self, request, *args, **kwargs):
graph_data = self.get_queryset().values('pk_count', 'month')
serializer = self.get_serializer(data=graph_data, many=True)
return Response(serializer.data)
https://docs.python.org/2/library/functions.html#super
In Python 2, syntax for super is this:
class MyClass(Base):
def func(self, *args, **kwargs):
super(MyClass, self).func(*args, **kwargs)
This is really stupid but I suspect it's because you're referencing Doctor and Pharmacy before you declare them. Try this instead:
class Doctor(models.Model):
name = models.CharField(max_length=150)
age = models.PositiveSmallIntegerField()
class Pharmacy(models.Model):
name = models.CharField(max_length=150)
status = models.CharField()
class Prescription(models.Model):
date_prescribed = models.DateTimeField()
doctor = models.ForeignKey(Doctor)
pharmacy = models.ForeignKey(Pharmacy)
I looked at some of my old Django on Python 2.x and your models look fine, just that seems to be an issue maybe(?)
The admin.py is as follows :-
class SiteDetailInline(admin.TabularInline):
model = SiteDetail
form = SiteDetailForm
fields = ('name', )
can_delete = False
extra = 1
max_num = 1
def get_readonly_fields(self, request, obj=None):
if obj:
return ('clmsid',) + self.readonly_fields
return self.readonly_fields
class SiteAdmin(admin.ModelAdmin):
inlines = [ SiteDetailInline, ]
def queryset(self, queryset):
return Site.objects.filter(~Q(id = settings.SITE_ID))
signals.post_save.connect(create_sites_default_user, sender=Site)
admin.site.unregister(Site)
admin.site.register(Site, SiteAdmin)
The models.py is as follows :-
class SiteDetail(models.Model):
name = models.CharField(max_length=100, unique=True)
client = models.ForeignKey(client)
site = models.ForeignKey(Site)
clmsid = models.CharField(max_length=15, unique=True, verbose_name='clms id', help_text='clms identifier', ) # unique identifier L-XXXXXX-id
def save(self, *args, **kwargs):
if "L-" != self.clmsid[:2]:
self.clmsid = "%s-%s-%s" % ("L", self.accountid, self.id)
super(SiteDetail, self).save(*args, **kwargs)
def __unicode__(self):
return u''
I want to show the extra site details inline in the admin for the site framework. It is not giving any error. However the site details are not displayed inline. Please let me know, what mistake am I doing. Thanks in advance.
Try this
def get_fields(self, request, obj=None):
if obj:
return ('clmsid',) + self.fields
return self.fields
After researching for days I'm still confused with creating a form involving 4 tables which are all connected via ForiegnKey. I'm not even sure if I'm using the right approach.
Should I use forms.Form or ModelForm? What I'm looking for I'm sure is common but all of my attempts are in vain. It seems like I'm making this more complicated than it should be since all 4 tables are related.
To the Point: To create a workorder, pick a Building, then pick a Unit within that Building, then pick a caller from Tenant(s) within that Unit. Then gather all data in view and save WorkOrder.
Using Django 1.6
# models.py
class Building(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=200)
...
def __unicode__(self):
return self.name
class Unit(models.Model):
name = models.ForeignKey(Building)
unit = models.CharField(max_length=30)
...
def __unicode__(self):
return self.unit
class Tenant(models.Model):
unit = models.ForeignKey(Unit)
name = models.ForeignKey(Building)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
...
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class WorkOrder(models.Model):
name = models.ForeignKey(Building)
unit = models.ForeignKey(Unit)
ordernum = models.AutoField(primary_key=True)
...
def __unicode__(self):
return self.unit
forms.py
# forms.py
class WorkOrderForm(forms.Form):
building_choice = forms.ModelChoiceField(queryset=Building.objects.all(),
empty_label='Pick a building',
)
def __init__(self, *args, **kwargs):
super(WorkOrderForm, self).__init__(*args, **kwargs)
self.fields['building_choice'].label = 'Building'
unit_choice = forms.ModelChoiceField(queryset=Unit.objects.(????),
empty_label='Pick a unit',
)
def __init__(self, *args, **kwargs):
super(WorkOrderForm, self).__init__(*args, **kwargs)
self.fields['unit_choice'].label = 'Unit'
caller_choice = forms.ModelChoiceField(queryset=Tenant.objects.(????),
empty_label='Who called',
)
def __init__(self, *args, **kwargs):
super(WorkOrderForm, self).__init__(*args, **kwargs)
self.fields['caller_choice'].label = 'Tenant'
views.py (incomplete)
#views.py
def create(request):
if request.method == 'POST':
form = WorkOrderForm(request.POST)
if form.is_valid():
workorder = WorkOrder(name=form.cleaned_data['name'],
unit=form.cleaned_data['unit'],
call_date=form.cleaned_data['call_date'],
caller=form.cleaned_data['caller'],
problem_desc=form.cleaned_data['problem_desc'])
workorder.save()
return HttpResponseRedirect('/workorder/')
else:
form = WorkOrderForm()
return render(request, 'workorder_form.html', {'form': form})
If someone could let me know the correct way to go about this I'd be forever grateful.
It's been a while since I posted this question but I found a django package django-clever-selects that met my needs. The docs and example project were well commented. Thanks to all that helped mr earlier.