Custom setting model does not apply until server restarted in django - django

I'm trying custom setting model to change some settings from admin.
class Setting(models.Model):
is_duel_cart_allowed = models.BooleanField(default=True)
free_cancellation_duration = models.DurationField(default="0:0:0")
return_order_duration = models.DurationField(default="0:0:0")
is_return_charges_deducted = models.BooleanField(_("Return charges applied when order is returned"),default=True)
is_shipping_charges_deducted_on_return = models.BooleanField(_("Deduct shipping charges when order is returned"),default=True)
is_product_cancellation_charge_deducted = models.BooleanField(_("Cancellation Charges deducted when product is cancelled"), default=True)
is_shipping_charges_deducted_on_cancel = models.BooleanField(_("Deduct shipping charges when order is cancelled"), default=True)
This is my model and when I turn ON/OFF any of these boolean fields, settings will remain unchanged until server is restarted.
How to tackle this problem?
Here is my view function code where I'm checking for these models changes
from core.models import Setting
setting = Setting.objects.first()
class ReturnOrderViewset(viewsets.ModelViewSet):
serializer_class = OrderSerializer
def get_queryset(self):
queryset = Order.objects.prefetch_related('items', 'items__product', 'items__user').filter(status_id=12)
return queryset
def create(self, request, *args, **kwargs):
order = request.POST.get('order_id')
return_reason = request.POST.get('return_reason')
current_time = timezone.now()
return_order_duration = setting.return_order_duration
try:
order = Order.objects.get(id=int(order))
return_reason = ReturnReason.objects.get(id=int(return_reason))
except Order.DoesNotExist:
return Response({'message': 'Order not found'}, status=status.HTTP_404_NOT_FOUND)
except ReturnReason.DoesNotExist:
return Response({'message': 'Order not found'}, status=status.HTTP_404_NOT_FOUND)
exp_time = order.created + return_order_duration
print(order.created, exp_time)
if order.status_id == 8:
print("status is complete ======")
if exp_time > current_time:
print("exp time is great than current time")
if all(item.product.is_return_allowed for item in order.items.all()):
print("All products are return allowed =====")
deductions = 0.0
if setting.is_return_charges_deducted:
deductions += float(return_reason.return_charges)
if setting.is_shipping_charges_deducted_on_return:
deductions += float(order.shipping_charges)
returning_amount = float(order.total_cost) - float(deductions)
order.status_id = 12
order.return_reason=return_reason
order.save()
subject = "Order Return Email"
message = render_to_string('order_return.html', {'order': order})
recipient_list = [order.user.email,]
send_html_email(subject, message, recipient_list)
return Response({
'message': 'Your order is returned',
'deductions': deductions,
'returning_amount': round(returning_amount, 2)},
status=status.HTTP_200_OK
)
else:
print("some products return not allowed =====")
return Response({'message': '[ERR RNA] Your order cannot be returned, please contact customer support'}, status=status.HTTP_200_OK)
else:
print("more than return time =====")
return Response({'message': '[ERR TMEXD] Your order cannot be returned, please contact customer support'}, status=status.HTTP_200_OK)
else:
print('Order status is not complete')
return Response({'message': '[ERR SNCOM] Your order cannot be returned, please contact customer support'}, status=status.HTTP_200_OK)
Even after changing setting from admin the calculations are done on previous settings. And once I restart server then its fine. How to tackle this in production?
Thanks In Advance

Related

400. That’s an error. Your client has issued a malformed or illegal request. That’s all we know - Google App Engine Django App

I have been programming an API using Django and djangorestframework for deployment in Google App Engine. The API is basically a package registry, so you can create, update, get, and delete packages with the API.
All the endpoints seem to work except for one. The only endpoint that doesn't work is one that display a paginated list of all packages in the online registry.
All the endpoints are working, but for some reason, when I hit the specific endpoint '/packages/', GCP gives me the error
400. That’s an error.
Your client has issued a malformed or illegal request. That’s all we know
When I run the application locally on my computer, all the endpoints work perfectly. The application only stops working for that specific route when I deploy it on Google App Engine.The API payload should be:
[
{
"Name": "*"
}
]
I am completely lost on this one and would appreciate any help.
VIEWS.py
import django.db.utils
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.core.paginator import Paginator, EmptyPage
import registry.models
from .serializers import *
from .models import *
# Create your views here.
#api_view(['GET'])
def apiOverview(request):
api_urls = {
'List': '/package-list/',
'Create': '/package-create/',
'Update': '/package-update/',
'Delete': '/package-delete/',
'Rate': '/package-rate/',
'Download': '/package-download/'
}
return Response(api_urls)
#api_view(['GET'])
def packages_middleware(request):
print(request)
print(type(request))
print(request.data)
print(type(request.data))
# determine offset query parameter
offset = request.GET.get('Offset')
if offset is None:
offset = 0
else:
offset = int(offset)
# capturing request body
response = []
queries = request.data
if len(queries) < 1:
return Response({'message: empty request body array'}, status=400)
else:
if len(queries) == 1 and queries[0]['Name'] == '*':
response = list(PackageMetadata.objects.all().values())
else:
for query in queries:
if 'Name' in query.keys() and 'Version' in query.keys():
for x in list(PackageMetadata.objects.filter(Name__icontains=query['Name']).filter(
Version__contains=query['Version']).values()):
response.append(x)
else:
response.append({
'message': 'query {q} is missing at least one attribute - remember to check spelling and capitalization'.format(q=query)
})
paginator = Paginator(response, 10)
try:
return Response(paginator.page(offset + 1).object_list, headers={'Offset': offset + 1})
except EmptyPage:
return Response(paginator.page(1).object_list, headers={'Offset': 2})
#api_view(['GET', 'PUT', 'DELETE'])
def package_middleware(request, pk):
try:
package = Package.objects.get(Metadata__ID__exact=str(pk))
if request.method == 'GET':
# CHECK THAT CONTENT FIELD IS SET
serializer = PackageSerializer(package, many=False)
return Response(serializer.data, status=200)
elif request.method == 'PUT':
payload = request.data
if 'Metadata' in payload and 'Data' in payload:
if payload['Metadata'] != PackageMetadataSerializer(package.Metadata, many=False).data:
return Response({"message": "name, version and ID must match"}, status=400)
else:
# CHECK THAT ONLY ONE DATA FIELD IS SET
serializer_data = PackageDataSerializer(data=payload['Data'], many=False)
if serializer_data.is_valid(raise_exception=True):
try:
serializer_data.update(instance=package.Data, validated_data=serializer_data.validated_data)
except django.db.utils.IntegrityError:
return Response(
{"message": "both Content and URL must be included in query, but exactly one can be set"},
status=400)
return Response(status=200)
else:
return Response(
{"message": "incorrect request body schema - remember to check spelling and capitalization"},
status=400)
else:
package.Metadata.delete()
package.Data.delete()
package.delete()
return Response({"message": "package deleted"}, status=200)
except registry.models.Package.DoesNotExist:
return Response({"message": "package not found"}, status=400)
#api_view(['POST'])
def create_package_middleware(request):
payload = request.data
print(payload)
if 'Metadata' in payload and 'Data' in payload:
serializer_metadata = PackageMetadataSerializer(data=payload['Metadata'], many=False)
serializer_data = PackageDataSerializer(data=payload['Data'], many=False)
if serializer_data.is_valid(raise_exception=True) and serializer_metadata.is_valid(raise_exception=True):
try:
metadata = PackageMetadata.objects.create(ID=serializer_metadata.data.get('ID'),
Name=serializer_metadata.data.get('Name'),
Version=serializer_metadata.data.get('Version'))
except django.db.utils.IntegrityError:
return Response({"message": "duplicate key-value (Name, Version) violates uniqueness constraint"},
status=403)
try:
data = PackageData.objects.create(Content=serializer_data.data.get('Content'),
URL=serializer_data.data.get('URL'))
except django.db.utils.IntegrityError:
metadata.delete()
return Response(
{"message": "both Content and URL must be included in query, but exactly one can be set"},
status=400)
Package.objects.create(Data=data, Metadata=metadata)
serializer_metadata = PackageMetadataSerializer(metadata, many=False)
return Response(serializer_metadata.data, status=200)
else:
return Response({"message": "incorrect request body schema - remember to check spelling and capitalization"},
status=400)
#api_view(['DELETE'])
def byName_middleware(request, name):
if name == '*':
return Response({"message": "query name reserved"}, status=400)
querySet = Package.objects.filter(Metadata__Name__iexact=name)
if len(querySet) == 0:
return Response({"message": "package not found"})
else:
for package in querySet:
package.Metadata.delete()
package.Data.delete()
package.delete()
return Response(status=200)
URLS.py
from django.urls import path, include
from . import views
urlpatterns = [
path('', views.apiOverview),
path('packages/', views.packages_middleware, name='packages_middleware'),
path('package/<str:pk>', views.package_middleware, name='package'),
path('package/', views.create_package_middleware, name='create'),
path('package/byName/<str:name>', views.byName_middleware, name='byName')
]
MODELS.py
from django.db import models
# Create your models here.
class PackageData(models.Model):
Content = models.TextField(blank=True, null=True) # actual zip file
URL = models.CharField(max_length=500, blank=True, null=True) # url of package
# class Meta:
# constraints = [
# models.CheckConstraint(
# name="%(app_label)s_%(class)s_content_or_url",
# check=models.Q(Content__isnull=True, URL__isnull=False) | models.Q(Content__isnull=False, URL__isnull=True)
# )
# ]
class PackageMetadata(models.Model):
class Meta:
constraints = [
models.UniqueConstraint(fields=['Name', 'Version'], name='unique_package')
]
ID = models.CharField(primary_key=True, max_length=50)
Name = models.CharField(max_length=50)
Version = models.CharField(max_length=50)
class Package(models.Model):
Data = models.ForeignKey(PackageData, on_delete=models.CASCADE)
Metadata = models.ForeignKey(PackageMetadata, on_delete=models.CASCADE)
class PackageRating(models.Model):
BusFactor = models.DecimalField(max_digits=10, decimal_places=9)
Correctness = models.DecimalField(max_digits=10, decimal_places=9)
GoodPinningPractice = models.DecimalField(max_digits=10, decimal_places=9)
LicenseScore = models.DecimalField(max_digits=10, decimal_places=9)
RampUp = models.DecimalField(max_digits=10, decimal_places=9)
ResponsiveMaintainer = models.DecimalField(max_digits=10, decimal_places=9)
class PackageQuery(models.Model):
Name = models.CharField(max_length=50)
Version = models.CharField(max_length=50)
You are making a GET call to /packages/ which is handled by the route definition packages_middleware(request).
In that function you have queries = request.data and the rest of your logic is dependent on queries. This document says request.data is for POST, PATCH, PUT. If that is correct, then that seems like where your error lies.
You can put a print statement just before and after that line and see if your App prints the statement after. That will help you confirm if that is the issue.
You should also print the contents of queries. Since you're not actually sending a body with your GET request, it is possible that the rest of your logic fails because the value of queries is not what you're expecting.

DRY-rest-permissions somehow does not check my object permissions except global permissions

I have recently started implementing dry-rest-permissions, but I can't seem to get it to check the has_object_permissions, it appears that only the global permissions work for me.
I am fairly new to implementing permissions and this is my first time implementing DRY-rest-permissions and have only recently started coding in django rest framework, so apologies for the lack of knowledge in advance.
At the moment I am trying to delete a company object by simply having a user call a URL, that URL then gets the current user's active_company and then deletes it only if the current user is the active_company's company_owner.
But what I discovered, is that I somehow can't get has_object_permissions to work anywhere?
I have noticed that if I delete has_write_permission(request), and hit the company_delete URL it gives me the following error:
'<class 'company.models.Company'>' does not have 'has_write_permission' or 'has_company_delete_permission' defined.
This means that it doesn't even look for the has_object_company_delete_permission. Meaning it only checks the global permissions rather than any of the object permissions, what am I possibly doing wrong here?
My model:
class Company(models.Model):
company_name = models.CharField(max_length=100)
company_orders = models.IntegerField(blank=True, null=True)
company_icon = models.ImageField(
upload_to='media/company_icon', blank=True)
company_owner = models.ForeignKey(
User, on_delete=models.SET_NULL, blank=True, null=True)
company_employees = models.ManyToManyField(
User, blank=True, null=True, related_name="company_employees")
def __str__(self):
return self.company_name
#staticmethod
def has_write_permission(request):
return False
def has_object_company_delete_permission(self, request):
return self.company_owner == request.user
My views
class CompanyView(viewsets.ModelViewSet): # made for viewing details
permission_classes = (DRYPermissions, )
queryset = Company.objects.all()
serializer_class = CompanySerializer
def create(self, request):
try:
company_name = request.data['company_name']
company_orders = request.data['company_orders']
company_owner = request.data['company_owner']
company_owner_obj = User.objects.get(id=company_owner)
company = Company(company_name=company_name,
company_orders=company_orders, company_owner=company_owner_obj)
company.save()
except Exception as error:
response = {
'error': str(error)
}
return Response(response, status=status.HTTP_400_BAD_REQUEST)
response = {
'message': 'Company created'
}
return Response(response, status=status.HTTP_201_CREATED)
def company_details(self, request):
try:
company_id = request.user.active_company.id
company = Company.objects.get(id=company_id)
serialized_data = CompanySerializer(company)
except Exception as error:
response = {
'error': str(error)
}
return Response(response)
return Response(serialized_data.data)
def company_edit(self, request, **kwargs):
try:
company_id = request.user.active_company.id
company = Company.objects.get(id=company_id)
serializer = CompanySerializer(
company, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
except Exception as error:
response = {
'message': str(error)
}
return Response(response)
response = {
'message': 'Edited Successfully'
}
return Response(response)
def company_delete(self, request):
try:
company_id = request.user.active_company.id
company = Company.objects.filter(id=company_id)
company.delete()
except Exception as error:
response = {
'message': str(error)
}
return Response(response)
response = {
'message': 'Deleted Successfully'
}
return Response(response)
My urls
urlpatterns = [
# Company URLs
path('company_create/',
CompanyView.as_view({'post': 'create'}), name='company_create'), # Create company
path('company_edit/',
CompanyView.as_view(), name='company_edit'), # Edit company details
path('company_delete/',
CompanyView.as_view({'delete': 'company_delete'}), name='company_delete'), # Delete company
path('company_details/',
CompanyView.as_view({'get': 'company_details'}), name='company_details'), # get company details (owner, employees etc)
]
My serializer
class CompanySerializer(serializers.ModelSerializer):
company_owner = LimitedUserSerializer(read_only=True)
class Meta:
model = Company
fields = ['id', 'company_name', 'company_orders',
'company_icon', 'company_owner']
As described in this part of the documentation the Global permissions are always checked first and Object permissions are checked ONLY if global permissions pass.
Documentation Source:
DRY Rest Permissions allows you to define both global and object level permissions.
Global permissions are always checked first and define the ability of a user to take an action on an entire model. For example you can define whether a user has the ability to update any projects from the database.
Object permissions are checked if global permissions pass and define whether a user has the ability to perform a specific action on a single object. These are also known as row level permissions. Note: list and create actions are the only standard actions that are only global. There is no such object level permission call because they are whole table actions.
In this context you have multiple problem actually that you should correct:
Make sure has_write_permission return True for all users that own their active companies
Make sure to rename has_object_company_delete_permission since we don't need the name of the model inside the function name
Example:
#staticmethod
def has_write_permission(request):
# Everybody can create/update/delete if no specific rule says otherwise
return True
def has_object_delete_permission(self, request):
# Only owner can delete
return self.company_owner == request.user
def has_object_update_permission(self, request):
# Only owner can update
return self.company_owner == request.user
Output:
Everybody can create
Only owner can update
Only owner can delete
I know that it seems a little bit overkill just to delete an object, but with some experience it allow you to clearly define ans setup permission but also to easily share the generic rules with the Frontend by using DryPermissionsField and DRYGlobalPermissionsField
PS: This answer came from my origin answer on Github to allow people finding a solution easily from StackOverFlow
It appears that it somehow does not check for object permissions in any of my custom actions, thus adding the following check in either the get_object() or the custom action itself fixes this.
self.check_object_permissions(self.request, obtainedObject)
An example of what it looks like in my code:
#action(detail=True, methods=['patch'], pk=None)
def company_edit(self, request, **kwargs):
try:
company_id = request.user.active_company.id
company = Company.objects.get(id=company_id)
serializer = CompanySerializer(
company, data=request.data, partial=True)
self.check_object_permissions(self.request, company)
if serializer.is_valid():
serializer.save()
except Exception as error:
response = {
'message': str(error)
}
return Response(response)
response = {
'message': 'Edited Successfully'
}
return Response(response)

How to check if the fields already exist.?

I need to check if the fields already exist. If that field doesn't exist, then I need to create a new one. Like the availability check on a booking system
My Model
# Choices
time = [
('1', 'Morning'),
('2', 'Afternoon'),
('3', 'Evening'),
('4', 'Night'),
]
# Model
class Calender(models.Model):
user = models.ForeignKey(AUTH_USER_MODEL,on_delete=models.SET_NULL)
date = models.DateField()
time = models.CharField(max_length=10, choices=time)
location = models.CharField(max_length=32)
My View
class CheckAvailabilityAPIView(APIView):
def post(self, request):
date = request.data.get('date')
time = request.data.get('time')
location = request.data.get('location')
calender = Calender.objects.all()
for obj in calender:
if obj.booked_date == date and obj.time == time and obj.location == location:
return Response({'response': 'Already exist'})
else:
user_id = request.user.id
user = User.objects.get(id=user_id)
serializer = VendorsCalenderSerializer(data=request.data)
if serializer.is_valid():
serializer.save(
user=user,
date=date,
time=time,
location=location
)
return Response({'response': 'Success', 'result': serializer.data})
else:
return Response({'response': 'Failed', 'error': serializer.errors},
status=status.HTTP_400_BAD_REQUEST)
Can someone help me with this.?
You can try using get_or_create()
Something like this :
appointment, created = Calender.objects.get_or_create(
user=user,
date=date,
time=time,
location=location
)
Returns a tuple of (object, created), where object is the retrieved or created object and created is a boolean specifying whether a new object was created.
Then based on created you can return customised response.
Reference : https://docs.djangoproject.com/en/2.2/ref/models/querysets/#get-or-create
And maybe their is a typo in Calender. Maybe you meant Calendar.
change calender = Calender.objects.all()
to
calender, result = Calender.objects.get_or_create(booked_date= date, section_timing = time, location = location)
if result is True, then new calender is created
You can also use filter :
calender = session.query(Calender).filter_by(**kwargs).first()
if calender:
return Response({'response': 'Already exist'})
else:

Django form efficiency issue

I have inherited some code that was handled by multiple developers, and as such, there is no standard for the product. I am having significant performance issues, and am remedying a lot of them, but don't know how to break this one down. When the user submits on a page that pre-populates with data, and allows the user to select a date for the activity, they can submit, and anything with a date goes away for them. The problem is within the views.py. When the user submits, the following code runs, and hangs up at formset = formset(request.POST). I'm assuming that there are multiple db calls happening, but am not seeing them when I print to terminal. Below is the entirety of the submission process.
STATES = ['Routed','Reconciled']
formset = None
form = StudyOnlyForm()
study_pk = request.GET.get('study', '0')
if study_pk == '' or study_pk == '0':
study_pk = 0
# child transactions that are 'Recoginzed',
# reportable with a 'Routed' parent
qs = Transaction.objects.filter(contract__reportable=True,
cleared = False,
contract__study__pk=study_pk,
transaction_status='Recognized',
parent_transaction__isnull=False,
parent_transaction__transaction_status__in=STATES)
#Designed to capture standalone contracts
qs1 = Transaction.objects.filter(contract__reportable=True,
cleared = False,
contract__study__pk=study_pk,
contract__contract_type__name='Standalone',
transaction_status__in=STATES)
#Captures Arms contracts for Milestone payments
parent_list = []
arms_list = []
parent = Transaction.objects.filter(parent_transaction__isnull=True,
contract__reportable=True,
cleared = False,
contract__study__pk=study_pk,
contract__contract_type__name='ARMs',
transaction_status__in=STATES)
children = Transaction.objects.filter(contract__reportable=True,
cleared = False,
contract__study__pk=study_pk,
transaction_status='Recognized',
contract__contract_type__name='ARMs',
parent_transaction__isnull=False,
parent_transaction__transaction_status__in=STATES)
for child_item in children:
parent_list.append(child_item.parent_transaction.pk)
arms_list.append(child_item.pk)
for parent_item in parent:
if parent_item.pk not in parent_list:
arms_list.append(parent_item.pk)
qs3 = Transaction.objects.filter(pk__in=arms_list)
qs4 = qs | qs1 | qs3
qs = qs4.order_by('-pk')
formset = modelformset_factory(Transaction, form=PaidDateForm, extra=0, can_delete=False)
if request.method == "POST":
print 'if request.POST'
print datetime.datetime.now()
formset = formset(request.POST)
print 'created formset'
print datetime.datetime.now()
if formset.is_valid():
print 'formset valid'
print datetime.datetime.now()
updated_transactions = formset.save(commit=False)
print 'updated transactions'
print datetime.datetime.now()
for trans in updated_transactions:
if trans.paid_amount is not None and trans.date_cleared is not None:
trans_to_change = Transaction.objects.get(pk=trans.pk)
trans_to_change.paid_amount = trans.paid_amount
trans_to_change.date_cleared = trans.date_cleared
trans_to_change.paid_currency = trans_to_change.entered_currency
trans_to_change.paid_amount_usd =
Decimal(str(trans_to_change.paid_amount * Decimal(str(trans_to_change.exchange_rate)).quantize(Decimal('0.01')))).quantize(Decimal('0.01'))
trans_to_change.edited_by = request.user
trans_to_change.cleared = True
trans_to_change.save()
if updated_transactions:
messages.add_message(request, messages.INFO, 'The transactions have been updated successfully.')
return HttpResponseRedirect(reverse('track:update_pdate'))
else:
messages.add_message(request, messages.INFO, 'No transactions have been updated.')
return render_to_response(
'track/paid_date_update.html',
{'formset':formset,
'form': form,
'study_pk':study_pk,
},
context_instance=template.RequestContext(request))
else:
formset = formset(queryset=qs)
return render_to_response(
'track/paid_date_update.html',
{'formset':formset,
'form': form,
'study_pk':study_pk,
},
context_instance=template.RequestContext(request))
Forms:
class StudyOnlyForm(forms.Form):
action = forms.CharField(widget=forms.HiddenInput())
#
# JBL - Q4.0 changed this form to pull all studies (previously
# only 'active' studies), which really means all studies
# that are not 'ccc' studies
#
study = forms.ModelChoiceField(required=False,
label='Protocol',
queryset=Study.objects.all().exclude(study_status='ccc'))
def __init__(self, *args, **kwargs):
self.req = True
if 'req' in kwargs:
self.req = kwargs.pop('req')
super(StudyOnlyForm, self).__init__(*args, **kwargs)
print 'StudyOnlyForm() init'
self.fields['study'].required = self.req
class PaidDateForm(forms.ModelForm):
formfield_callback = jquery_datefield
paid_amount = forms.DecimalField(label="Cleared
Amount",max_digits=14,decimal_places=2,required=False)
date_cleared = forms.DateField(label="Cleared Date",widget=JQueryDateWidget(),
input_formats=settings.DATE_INPUT_FORMATS, required=False)
class Meta:
model = Transaction
include = ('date_time_created')
def __init__(self, *args, **kwargs):
super(PaidDateForm, self).__init__(*args, **kwargs)
print 'PaidDateForm init'
for field in self.fields:
if field != 'date_cleared':
self.fields[field].widget = forms.HiddenInput()
self.fields['paid_amount'].widget.attrs['size'] = 12
self.initial['paid_amount'] = '%.2f' % (self.instance.usd_amount)
You restrict the queryset in the GET branch, but not the POST branch. That means that the POST branch creates a formset containing every transaction.
replace your for loop:
for trans in updated_transactions.exclude(paid_amount=None, date_cleared=None).all():
trans_to_change = Transaction.objects.get(pk=trans.pk)
trans_to_change.paid_amount = trans.paid_amount
trans_to_change.date_cleared = trans.date_cleared
trans_to_change.paid_currency = trans_to_change.entered_currency
trans_to_change.paid_amount_usd = Decimal(str(trans_to_change.paid_amount * Decimal(str(trans_to_change.exchange_rate)).quantize(Decimal('0.01')))).quantize(Decimal('0.01'))
trans_to_change.edited_by = request.user
trans_to_change.cleared = True
trans_to_change.save()

how to overide in forms queryset none() attribute and somehow allow to save the field?

I have models.py
class Visit(Model):
reference_visit = models.ForeignKey('self',
help_text="Visit needs a refrence to Prior Visits",
null=True, blank=True)
show_prior_responses = models.BooleanField(default=False,
help_text="Show PriorResponses")
# has many field but i am making it short.
def __unicode__(self):
result = """Visit id:%s pt:%s""" % (self.id, self.patient.id)
return result
forms.py
class VisitSetupForm(Form):
list_visit_ids = ModelChoiceField(
queryset=Visit.objects.none(),
empty_label='Select Revisit ID',required=False)
show_prior_visit = ModelChoiceField(
queryset=User.objects.all(),
empty_label="Select User for Revisit",required = False)
has many but question is on list_visit_ids.
views.py
def setup(request):
"""
Allow an Admin user the ability to setup a patient & visit all at once.
"""
if request.user.is_superuser:
form_class = AdminVisitSetupForm
all_topics = True
else:
form_class = VisitSetupForm
all_topics = False
f = form_class()
# Get a list of topics for each report.
report_topics = {}
for r in Interview.objects.all():
report_topics[r.id] = [t['ad'] for t in r.topics.values('ad')]
data = {
'superuser':request.user.is_superuser,
'report_topics':simplejson.dumps(report_topics)
}
try:
request.user.reviewer
data['reviewer'] = True
except:
pass
if request.method == "POST":
f = form_class(request.POST)
if f.is_valid():
# Create the patient, generate a password, and send them on their way.
cd = f.cleaned_data
patient = None
if cd['revisit']:
# Check for an existing user first.
try:
patient = Patient.objects.get(username=cd['username'])
except Patient.DoesNotExist, e:
data['form'] = f
data['msg'] = 'There is no user with this username.'
return render_to_response('visit/setup.html', data, context_instance=RequestContext(request))
admin_user = get_user(request)
organization = None
if admin_user:
organization = admin_user.organization
if patient and not request.user.is_superuser:
# Make sure the patient they've selected is one of their own.
if patient.organization != organization:
return HttpResponseForbidden('You are not allowed to see this page.')
if not patient:
password = generate_password()
user = User.objects.create_user(cd['username'], cd['contact_email'], password)
user.first_name = cd['first_name']
user.last_name = cd['last_name']
user.save()
patient = Patient(
user=user,
username=user.username,
contact_phone=cd['contact_phone'],
date_of_birth=cd['date_of_birth'],
email=user.email,
first_name=user.first_name,
gender=cd['gender'],
last_name=user.last_name,
maiden_name=cd['maiden_name'],
organization=organization,
patient_type=cd['patient_type'],
security_answer=cd['security_answer'],
security_question=cd['security_question'],
)
patient.save()
# Send them an email.
t = loader.get_template('www/new_account.txt')
c = Context({
'password':'%s-%s-%s' % (password[:3], password[3:5], password[5:]),
'patient':patient
})
msg = t.render(c)
try:
send_mail(
'A request by your physician to do an online medical history before your appointment.',
msg,
'support#careprep.com',
[user.email]
)
except Exception, e:
log.error('Could not send email for new account %s because: [%s]' % (user.username, e))
request.session['password'] = password
# Create the Visit, too.
interview = cd['interview']
list_visit_ids = cd['list_visit_ids']
print list_visit_ids
visit = Visit(
reference_visit = cd['list_visit_ids'],
show_prior_responses = cd['show_prior_responses'],
patient=patient
)
if request.user.is_superuser:
topics = cd['topics']
else:
topics = set(list(interview.topics.all()) + list(cd['topics']))
reviewer_mode = cd.get('reviewer_mode') or patient.patient_type == 'Reviewer'
url, visit = initialize_visit(
request,
patient=patient,
starting_section=interview.starting_section,
visit_title='%s %s' % (patient, interview.title),
topics=topics,
reviewer_mode=reviewer_mode,
chief_complaint=cd['chief_complaint'],
location=cd['interview_site'],
reference_visit = cd['list_visit_ids'],
show_prior_responses = cd['show_prior_responses'],
)
next_url = "/visit/confirmation/%s/%s/?next=%s" % (patient.user.id, interview.id, url)
else:
v = Visit.objects.get(pk=request.POST['list_visit_ids'])
print v
return HttpResponseRedirect(next_url)
# all the fields that are not given pls ignore.
The template is fine.
Now watch forms.py when i do list_visit_ids = ModelChoiceField(queryset=Visit.objects.all(), empty_label='Select Revisit ID',required=False) It works perfectly fine on my local machine.But on my server it has around 6000 visit objects so this page hangs or i should say keep on loading.
So initially i changed it to list_visit_ids = ModelChoiceField(queryset=Visit.objects.none(), empty_label='Select Revisit ID',required=False)
Now i know that by this the form becomes invalid and should go to the else part Now my question how do i make reference_visit=cd['list_visit_ids'] in else (form is invalid)
case save().How do i override the none() attribute.
Thanks in advance i will really appreciate.
If your goal is to save your html page load by removing the 6000 choices (which I've done too: 10000+ <option> fields wrapped by misc html will absolutely choke a page), you shouldn't be using a ChoiceField at all. By setting queryset=Visit.objects.none() you're allowing zero choices and nothing passed in will validate.
You either show 6000 select item drop downs, radio boxes, etc., or find a way to /not/ have a giant select drop down (such as a hidden input or charfield), not fake around a ModelChoiceField who's main purpose is to populate that select drop down and validate.
In short: don't use a ModelChoiceField if you're not going to be using the html choices generated by it. Use something else and do the validation / model pulling yourself via the clean_FOO methods.
class MyForm(forms.Form):
my_input = forms.CharField()
def clean_my_input(self):
input = self.cleaned_data.get('my_input')
try:
return MyModel.objects.get(pk=input) # add a filter here if you want
# (whatever filters you were using in the queryset argument)
except MyModel.DoesNotExist:
raise forms.ValidationError("Doesn't exist / is invalid")
return input