Defaulting an updateview action in django form under a def post - django

Working with another coder on a project. His change stopped the UpdateView on some forms from saving edits. I realized why.... he defined a
def post
which works for the case he was working on, but needs an else action that just does a default update. I am not sure how to do this when he UpdateView isn't doing it all automagically.
The code to the UpdateView:
class ProviderUpdateView(UpdateView):
model = Provider
form_class = ProviderForm
provider_form_class = ProviderForm
provider_term_form_class = ProviderTermForm
template_name = 'ipaswdb/provider/provider_form.html'
success_url = '/ipaswdb/provider/'
def get_context_data(self, **kwargs):
context = super(ProviderUpdateView, self).get_context_data(**kwargs)
provider = context['object']
context['provider_id'] = provider.id
prov = Provider.objects.get(pk=provider.id)
#print "provider: ",
#print prov
#print "provider terminated: ",
#print prov.is_terminated
if prov.is_terminated:
provider_form = ProviderFormView(instance=prov)
context['readonly'] = True
else:
print("NOT TERMINATED SO LETS DO THIS")
provider_form = ProviderForm(instance=prov)
context['readonly'] = False
context['provider_form'] = provider_form
provider_term_form = ProviderTermForm()
context['provider_term_form'] = provider_term_form
### Get the list of GroupLocations, but remove the current one this provider is associated with
### I just need the grouplocation id and the name
#grplocs = GroupLocationProvider.objects.filter(
return context
def post(self, request, *args, **kwargs):
#print self.request.POST.keys()
#print self.request.POST.values()
print("Posting...")
if self.request.POST.has_key('terminate'):
provider = Provider.objects.get(pk=kwargs['pk'])
form = ProviderTermForm(request.POST)
if form.is_valid():
print "Terminating Provider: ",
print provider
provider_term = ProviderTerm()
provider.is_terminated = True
provider.save()
### Update the term fields
provider_term.provider = provider
provider_term.old_id = provider.id
provider_term.term_date = form.cleaned_data['term_date']
provider_term.term_comment = form.cleaned_data['term_comment']
provider_term.save()
return HttpResponseRedirect(self.success_url)
I know I need an else to this statement in the post:
if self.request.POST.has_key('terminate'):
I am just not sure what the just do your regular thing' is in the UpdateView. I tested my hypothesis that his code broke the ability to edit and save a provider cause I removed the def post completely, and all worked well with the UpdateView automagic. Since we are overriding? the def post it seems to me we have to handle the regular update ourselves, just not sure how that looks.

Related

Django and Bokeh: How do I add my graph to a Class Detail View?

I can't seem to figure out how to add my graph to a Class Detail View? Is it not possible to do so? I add it to the detailView, and call it in my template with:
{{ div | safe }}
But it does not show? I've gotten it to work perfectly fine in a view and template separately.
Here's the whole detailview I'm trying to implement it into.
DetailView
class MedarbejderDetailView(FormMixin, DetailView):
template_name = 'evalsys/medarbejder/detail.html'
model = Medarbejder
form_class = OpretEvalForm
def evalgraph(self):
colors = ["#40e862", "#ff9d26", "#ff1424"]
over = 0
møder = 0
under = 0
none = 0
counts = []
items = ["Overstiger forventning", "Møder forventning", "Under forventning", "Ingen bedømmelse"]
eval_vudering = Evaluering.objects.values("vuderingsnavn__vuderingsnavn")
source = ColumnDataSource(data=dict(items=items, counts=counts))
for i in eval_vudering:
if "Overstiger forventning" in i.values():
over += 1
elif "Møder forventning" in i.values():
møder += 1
elif "Under forventning" in i.values():
under += 1
elif None in i.values():
none += 1
counts.extend([over, møder, under, none])
plot = figure(x_range=items, plot_height=500, plot_width=500, title="Opsumering af evalueringer",
toolbar_location=None, tools="pan, wheel_zoom, box_zoom, reset, tap", tooltips="#items: #counts")
plot.title.text_font_size = "20pt"
plot.vbar(x="items", top="counts", width=0.9, source=source, legend="items", line_color='black',
fill_color=factor_cmap("items", palette=colors, factors=items))
plot.legend.label_text_font_size = "13pt"
script, div = components(plot)
return render(self, 'evalsys/medarbejder/detail.html', {'script': script, 'div': div})
def view_medarbejder_with_pk(self, pk=None):
if pk:
medarbejder = Medarbejder.objects.get(pk=pk)
else:
medarbejder = self.medarbejder
args = {'medarbejder': medarbejder}
return render(self, 'evalsys/medarbejder/detail.html', args)
def get_context_data(self, **kwargs):
context = super(MedarbejderDetailView, self).get_context_data(**kwargs)
context['eval_list'] = Evaluering.objects.all()
context['fag_list'] = Fag.objects.all()
context['ma'] = Medarbejder.objects.get(pk=self.kwargs.get('pk'))
context['instruktør'] = User.objects.get(username=self.request.user)
return context
def post(self, request, pk):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
print(form.cleaned_data)
instance = form.save(commit=False)
instance.instruktør = request.user
instance.ma = self.object
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
item = form.save()
self.pk = item.pk
return super(MedarbejderDetailView, self).form_valid(form)
def form_invalid(self, form):
return super(MedarbejderDetailView, self).form_invalid(form)
def get_success_url(self):
return reverse_lazy("evalsys:view_evaluering_with_pk", kwargs={'pk': self.pk})
URLs
path('se_alle_evalueringer/<int:pk>', views.MedarbejderEvalDetailView.as_view(), name="view_evaluering_with_fag"),
I know I'm calling the function "view_evaluering_with_fag", so it is because I'm not calling my Bokeh function "evalgraph"?
Didn't know folks couldn't use this as a way to ask follow up questions when we're researching the same question.
Anyhow, I am so about to make your day! With A LOT of trial and error (I've only been coding with Python and Django for a month with no real coding background except Java back in 1999) I got bokeh to render from detailview. It appears the trick is to get stuff under the get_context_data function. I don't know how I came to this conclusion, but I figured the script and div context weren't making their way to the render so I was trying to get them into context. As you'll see below, I put script and div as context['script']=script and context['div']=div. My situation looks a bit simpler, I'm just parsing a bike data file and plotting the data, but hopefully this gets you on your way if you're still trying to make this work.
class FitFileDetailView(DetailView):
model = FitFiles
def get_context_data(self, **kwargs):
model = FitFiles
ff = FitFiles.objects.get(pk=self.kwargs.get('pk'))
ffile = ff.fitfiles.path
fitfile2 = FitFile(ffile)
while True:
try:
fitfile2.messages
break
except KeyError:
continue
workout2 = []
for record in fitfile2.get_messages('record'):
r2 = {}
# Go through all the data entries in this record
for record_data in record:
r2[record_data.name] = record_data.value
workout2.append(r2)
df2 = pd.DataFrame(workout2)
df2['time']=(df2['timestamp'] - df2['timestamp'].iloc[0]).astype('timedelta64[s]')
#Bokeh code
df2 = pd.DataFrame(workout2)
df2['time']=(df2['timestamp'] - df2['timestamp'].iloc[0]).astype('timedelta64[s]')
p2 = figure(x_axis_label='time', y_axis_label='watts', tools="", plot_width=1000, plot_height=500)
p2.line(df2['time'], df2['power'])
p2.line(df2['time'], df2['heart_rate'], color='red')
script, div = components(p2)
context = super(FitFileDetailView, self).get_context_data(**kwargs)
context['script']=script
context['div']=div
return context

Django Two Factor Authentication - Remove Token Generator Option From Wizard

I've been playing with Django Two Factor authentication for the last two days or so, and I have it partially working. I am trying to figure out a way to remove the QR Token Generator. I have tried subclassing the setup view, but the form wizard is causing me some grief. The wizard is confusing me. I know in a regular form, how to remove radio buttons, but in this case, I can't seem to locate the source of the Token Generator.
The SetupView...
#class_view_decorator(never_cache)
#class_view_decorator(login_required)
class SetupView(IdempotentSessionWizardView):
"""
View for handling OTP setup using a wizard.
The first step of the wizard shows an introduction text, explaining how OTP
works and why it should be enabled. The user has to select the verification
method (generator / call / sms) in the second step. Depending on the method
selected, the third step configures the device. For the generator method, a
QR code is shown which can be scanned using a mobile phone app and the user
is asked to provide a generated token. For call and sms methods, the user
provides the phone number which is then validated in the final step.
"""
success_url = 'two_factor:setup_complete'
qrcode_url = 'two_factor:qr'
template_name = 'two_factor/core/setup.html'
session_key_name = 'django_two_factor-qr_secret_key'
initial_dict = {}
form_list = (
('welcome', Form),
('method', MethodForm),
('generator', TOTPDeviceForm),
('sms', PhoneNumberForm),
('call', PhoneNumberForm),
('validation', DeviceValidationForm),
('yubikey', YubiKeyDeviceForm),
)
condition_dict = {
'generator': lambda self: self.get_method() == 'generator',
'call': lambda self: self.get_method() == 'call',
'sms': lambda self: self.get_method() == 'sms',
'validation': lambda self: self.get_method() in ('sms', 'call'),
'yubikey': lambda self: self.get_method() == 'yubikey',
}
idempotent_dict = {
'yubikey': False,
}
def get_method(self):
method_data = self.storage.validated_step_data.get('method', {})
return method_data.get('method', None)
def get(self, request, *args, **kwargs):
"""
Start the setup wizard. Redirect if already enabled.
"""
if default_device(self.request.user):
return redirect(self.success_url)
return super(SetupView, self).get(request, *args, **kwargs)
def get_form_list(self):
"""
Check if there is only one method, then skip the MethodForm from form_list
"""
form_list = super(SetupView, self).get_form_list()
available_methods = get_available_methods()
if len(available_methods) == 1:
form_list.pop('method', None)
method_key, _ = available_methods[0]
self.storage.validated_step_data['method'] = {'method': method_key}
return form_list
def render_next_step(self, form, **kwargs):
"""
In the validation step, ask the device to generate a challenge.
"""
next_step = self.steps.next
if next_step == 'validation':
try:
self.get_device().generate_challenge()
kwargs["challenge_succeeded"] = True
except Exception:
logger.exception("Could not generate challenge")
kwargs["challenge_succeeded"] = False
return super(SetupView, self).render_next_step(form, **kwargs)
def done(self, form_list, **kwargs):
"""
Finish the wizard. Save all forms and redirect.
"""
# Remove secret key used for QR code generation
try:
del self.request.session[self.session_key_name]
except KeyError:
pass
# TOTPDeviceForm
if self.get_method() == 'generator':
form = [form for form in form_list if isinstance(form, TOTPDeviceForm)][0]
device = form.save()
# PhoneNumberForm / YubiKeyDeviceForm
elif self.get_method() in ('call', 'sms', 'yubikey'):
device = self.get_device()
device.save()
else:
raise NotImplementedError("Unknown method '%s'" % self.get_method())
django_otp.login(self.request, device)
return redirect(self.success_url)
def get_form_kwargs(self, step=None):
kwargs = {}
if step == 'generator':
kwargs.update({
'key': self.get_key(step),
'user': self.request.user,
})
if step in ('validation', 'yubikey'):
kwargs.update({
'device': self.get_device()
})
metadata = self.get_form_metadata(step)
if metadata:
kwargs.update({
'metadata': metadata,
})
return kwargs
def get_device(self, **kwargs):
"""
Uses the data from the setup step and generated key to recreate device.
Only used for call / sms -- generator uses other procedure.
"""
method = self.get_method()
kwargs = kwargs or {}
kwargs['name'] = 'default'
kwargs['user'] = self.request.user
if method in ('call', 'sms'):
kwargs['method'] = method
kwargs['number'] = self.storage.validated_step_data\
.get(method, {}).get('number')
return PhoneDevice(key=self.get_key(method), **kwargs)
if method == 'yubikey':
kwargs['public_id'] = self.storage.validated_step_data\
.get('yubikey', {}).get('token', '')[:-32]
try:
kwargs['service'] = ValidationService.objects.get(name='default')
except ValidationService.DoesNotExist:
raise KeyError("No ValidationService found with name 'default'")
except ValidationService.MultipleObjectsReturned:
raise KeyError("Multiple ValidationService found with name 'default'")
return RemoteYubikeyDevice(**kwargs)
def get_key(self, step):
self.storage.extra_data.setdefault('keys', {})
if step in self.storage.extra_data['keys']:
return self.storage.extra_data['keys'].get(step)
key = random_hex(20).decode('ascii')
self.storage.extra_data['keys'][step] = key
return key
def get_context_data(self, form, **kwargs):
context = super(SetupView, self).get_context_data(form, **kwargs)
if self.steps.current == 'generator':
key = self.get_key('generator')
rawkey = unhexlify(key.encode('ascii'))
b32key = b32encode(rawkey).decode('utf-8')
self.request.session[self.session_key_name] = b32key
context.update({
'QR_URL': reverse(self.qrcode_url)
})
elif self.steps.current == 'validation':
context['device'] = self.get_device()
context['cancel_url'] = resolve_url(settings.LOGIN_REDIRECT_URL)
return context
def process_step(self, form):
if hasattr(form, 'metadata'):
self.storage.extra_data.setdefault('forms', {})
self.storage.extra_data['forms'][self.steps.current] = form.metadata
return super(SetupView, self).process_step(form)
def get_form_metadata(self, step):
self.storage.extra_data.setdefault('forms', {})
return self.storage.extra_data['forms'].get(step, None)
Seems to reference a MethodForm...
class MethodForm(forms.Form):
method = forms.ChoiceField(label=_("Method"),
initial='generator',
widget=forms.RadioSelect)
def __init__(self, **kwargs):
super(MethodForm, self).__init__(**kwargs)
self.fields['method'].choices = get_available_methods()
I can't seem to track back to where the list of choices is defined, clearly in this case it is saying generator is the initial choice in setup, but I can't figure out how to remove the generator option as a list of valid choices. I also tried to remove generator from the form_list but this didn't seem to make a difference either.
If there's an easier way to remove the Token Generator option and a different approach that's altogether different, I'm open to that too.
Thanks in advance for any thoughts.
Found it. It was in the models.py....
def get_available_methods():
methods = [('generator', _('Token generator'))]
methods.extend(get_available_phone_methods())
methods.extend(get_available_yubikey_methods())
return methods
I removed the ('generator', _('Token generator')) reference from inside the brackets ( list ) and it removed the Token Generator option.

How to pass created object in createview right to updateview in django

I have a createview view in my django app:
### Create a Group
class GroupCreateView(CreateView): # {{{
model = Group
form_class = GroupForm
template_name = 'ipaswdb/group/group_form.html'
success_url = '/ipaswdb/group/'
def get_context_data(self, **kwargs):
..do stuff..
def post(self, request, *args, **kwargs):
if self.request.POST.has_key('submit'):
form = GroupForm(request.POST)
if form.is_valid():
### Save the group
self.object = form.save()
#### Adding a provider forces a default location
#if form['default_location'].value() == True:
### We are forcing the creation of a GroupLocation when a new Group is created
gl = GroupLocation(
group = Group.objects.get(pk=self.object.id),
doing_business_as = self.object.group_name,
default_group_location = True,
mailing_address_line_one = self.object.mailing_address_line_one,
mailing_address_line_two = "",
mailing_city = self.object.mailing_city,
mailing_state = self.object.mailing_state,
mailing_zip_code = self.object.mailing_zip_code,
mailing_phone = self.object.mailing_phone,
mailing_fax = self.object.mailing_fax,
contact = self.object.group_contact,
physical_address_line_one = self.object.billing_address_line_one,
physical_address_line_two = "",
physical_city = self.object.billing_city,
physical_state = self.object.billing_state,
physical_zip_code = self.object.billing_zip_code,
physical_phone = self.object.billing_phone,
physical_fax = self.object.billing_fax,
)
gl.save()
new_grploc = gl
self.object.default_location_id = new_grploc.id
self.object.save()
new_group_id = self.object.id
new_grploc_id = new_grploc.id
### Now check the list of providers to see what has changed
print "group_add_provider: ",
print request.POST.getlist('group_add_provider')
add_providers = request.POST.getlist('group_add_provider')
if add_providers:
for pro in add_providers:
add_grploc = GroupLocationProvider(
grouplocation=GroupLocation.objects.get(pk=new_grploc_id),
provider=Provider.objects.get(pk=pro)
)
add_grploc.save()
### Now check the list of insurances to see what has changed
print "group_add_insurance: ",
print request.POST.getlist('group_add_insurance')
add_insurances = request.POST.getlist('group_add_insurance')
if add_insurances:
for ins in add_insurances:
add_grpins = GroupInsurance(
group=Group.objects.get(pk=new_group_id),
insurance=Insurance.objects.get(pk=ins)
)
add_grpins.save()
#return HttpResponseRedirect(self.get_success_url()) #how it used to work, just fine but would go back to my list of groups
return HttpResponseRedirect('ipaswdb:group_detail', self.object.pk) #want it to call my edit view here.
My Url Patterns
app_name = 'ipaswdb'
urlpatterns = [
url(r'^group/(?P<pk>[0-9]+)/$', GroupUpdateView.as_view(), name='group_detail'),
url(r'^group/add/$', GroupCreateView.as_view(), name='group_add'),
..etc..
Got an error but I feel I am closer?
DisallowedRedirect at /ipaswdb/group/add/
Unsafe redirect to URL with protocol 'ipaswdb'
I really want to load the page with the created object but as an updateview
Anyway to do this from the create view?
It is highly recommended to return a redirect request from a successful POST request. Otherwise a user might accidentally create multiple objects by reloading the page. Something like this:
from django.shortcuts import redirect
...
return redirect('name-of-update-url', pk=obj.pk)
If you really do not want to use a redirect, it is a bit more involved. Class based views are not meant to be called directly. The as_view method you use in your urls.py creates a wrapper function which instantiates the class and calls dispatch, which selects the right handler method (get/post/...). But you can't use as_view, because you have a POST request, but probably want to call the get method.
So you have to create an instance of your UpdateView and directly call its get method. With a standard UpdateView, can try something like this:
class GroupCreateView(CreateView):
...
def post(self, request, *args, **kwargs):
...
obj = ... # create your object
update_view = UpdateView()
update_view.request = self.request
update_view.args = []
update_view.kwargs = {'pk': obj.pk}
return update_view.get(self.request)
If you heavily customized your UpdateView, you might have to adapt this.
My go-to resource how Django's class-based views look under the hood is https://ccbv.co.uk

Django Multiselect, how to override choices properly

this is my forms.py
CHOICES = []
class salDeptChartForm(forms.Form):
company = forms.CharField(max_length=2,label = 'Firma',help_text='A valid email address, please.')
date_validfrom = forms.DateField(label = 'Bu Tarihten',required=False)
date_validuntil = forms.DateField(label = 'Bu Tarihe Kadar',required=False)
saldept = forms.MultipleChoiceField(label = 'Satış Departmanları',choices=CHOICES, widget=forms.CheckboxSelectMultiple())
this is where I override the choices in my view.
form = salDeptChartForm(initial={'company':'01'})
saldeptlist = saleinstance.fetchSalDept()
form.fields['saldept'].choices = saldeptlist <this is where I override>
problem occurs when I select one of the options. form doesnt get validate.
Select a valid choice. * is not one of the available choices.
I think, even I override the choices in my view django still checks with previous choices itially I created. I get the correct html output tough.
How to overcome this?
thx
complete view code is there.
form initiates twice one for get and one for post, I dont know if its best either.
def salDept(request):
member_id = request.session['member_id']
saleinstance = sale(member_id)
chartinstance = charts(member_id)
if request.method == 'GET':
form = salDeptChartForm(initial={'company':'01'}) <first init>
saldeptlist = saleinstance.fetchSalDept() <its a list>
form.fields['saldept'].choices = saldeptlist <override choices>
print 'get worked'
return render(request, 'chart/sale/salDept.html',locals())
if request.method == 'POST':
form = salDeptChartForm(request.POST) <second init>
print 'post worked'
if form.is_valid(): <fails>
print 'valid'
company = form.cleaned_data['company']
vfr = form.cleaned_data['date_validfrom']
vun = form.cleaned_data['date_validuntil']
validfrom = formatDate(vfr)
validuntil = formatDate(vun)
selectedSalDepts = request.POST.getlist('saldept')
else:
print 'not valid'
print form.errors
resultdict = chartinstance.salesBySaldept(company,selectedSalDepts,validfrom, validuntil)
form = salDeptChartForm(initial={'company':company,'date_validfrom':request.POST['date_validfrom'], 'date_validuntil':request.POST['date_validuntil']})
domcache = 'true'
return render(request, 'chart/sale/salDept.html',locals())
Okay, you need override the init() of the form to do accomplish this.
class SomeForm(forms.Form):
email = forms.EmailField(label=(u'Email Address'))
users = forms.MultipleChoiceField(choices=[(x, x) for x in User.objects.all()]
)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(SomeForm, self).__init__(*args, **kwargs)
self.fields['users'].choices = [(x, x) for x in User.objects.filter(name__contains='Patel')]
def clean(self):
return self.cleaned_datas
Here in line number (3) you can see that I have provided all the possible choices and then in the init I have filtered the choices, this is important because Django validates your submitted request from the former and displays the choices from the latter
Your validation fails because you only overwrite the choices on the GET method. You don't do anything for the POST, so as far as Django knows, no choice is valid for the POST. Adding the choices to POST should fix your problem.

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