I created a date range form to use in my Django views. In some of the views I use it in the date range is required, but not in others so I need the form to accept a required key word. I'm having trouble getting my form to recognize required=False.
The Django form:
class DateRangeForm(forms.Form):
def __init__(self, *args, **kwargs):
initial_start_date = kwargs.pop('initial_start_date')
initial_end_date = kwargs.pop('initial_end_date')
required_val = kwargs.pop('required')
input_formats = kwargs.pop('input_formats')
super(DateRangeForm,self).__init__(*args,**kwargs)
self.fields['start_date'].initial = initial_start_date
self.fields['start_date'].required = required_val
self.fields['start_date'].input_formats = input_formats
self.fields['end_date'].initial = initial_end_date
self.fields['end_date'].required = required_val
self.fields['end_date'].input_formats = input_formats
start_date = forms.DateTimeField(widget=forms.DateInput(attrs={'class':"form-control text-center"}))
end_date = forms.DateTimeField(widget=forms.DateInput(attrs={'class':"form-control text-center"}))
It's used in my Django view like this:
def Nominal_Request(request):
initial_end = Utils.addToDatetime(datetime.today().strftime("%Y/%m/%d"),weeks=6)
form_dict = {}
arg_dict = {}
message = message = {'last_url':'Nominal_Request'}
if request.method == 'POST':
daterange_form = DateRangeForm(request.POST,required=False,initial_start_date=None,initial_end_date=initial_end,input_formats=dateFormats)
if 'Range' in request.POST:
if daterange_form.is_valid():
#process the dates here....
WS = daterange_form.cleaned_data['start_date']
WE = daterange_form.cleaned_data['end_date']
#date processing continues....
args = {'Start':WS,'End':WE}
return Request_Results(request,args)
else:
daterange_form = DateRangeForm(required=False,initial_start_date=None,initial_end_date=initial_end,input_formats=dateFormats)
form_dict.update({'daterange_form':daterange_form})
return render(request,'InterfaceApp/Request_Nominal.html',form_dict)
It displays fine, but Django still thinks that both of the date range fields are required and won't let me submit the form with one or both of the fields empty.
Why is it not picking up on my required arg?
Related
I have an update form with 4 fields to display
3 of them are related to a class to which the form is bound
the last field (country) is only for information and I would like that field to be display in first position
currently, it is displayed at the end of my form...
I tryed to use field_order but country field is ignored...
form.py
class ParametrageForm(forms.ModelForm):
def __init__(self, request, *args, **kwargs):
super(ParametrageForm, self).__init__(*args, **kwargs)
self.request = request
self.language = request.session.get('language')
self.user = request.user.id # id de l'utilisateur
self.user_pays = request.session.get('user_pays') # pays de l'utilisateur
self.user_site_type = request.session.get('user_site_type')
self.user_site = request.session.get('user_site')
instance = Parametrage.objects.get(asp_par_cle = kwargs['instance'].asp_par_cle)
SITE_CONCERNE = Site.option_list_sites(self.language)
if self.language == 'en':
country= Site.objects.get(sit_abr = instance.asp_par_loc).reg.pay.pay_nom_eng
elif self.language == 'fr':
country= Site.objects.get(sit_abr = instance.asp_par_loc).reg.pay.pay_nom_fra
else:
country= Site.objects.get(sit_abr = instance.asp_par_loc).reg.pay.pay_nom_eng
self.fields["country"] = forms.CharField(label = _("Country"),widget=forms.TextInput,initial=country, disabled=True)
self.fields["asp_par_loc"] = forms.ChoiceField(label = _("Site concerned by settings"), widget=forms.Select, choices=SITE_CONCERNE,)
self.fields["asp_par_ale"] = forms.IntegerField(label = _("Stock alert value for this site"), widget=forms.TextInput,)
self.fields["asp_par_con"] = forms.IntegerField(label = _("Stock confort value for this site"), widget=forms.TextInput,)
class Meta:
model = Parametrage
fields = ('asp_par_loc','asp_par_ale','asp_par_con',)
field_order = ['country','asp_par_loc','asp_par_ale','asp_par_con',]
Replace
self.fields["country"] = forms.CharField(label = _("Country"),widget=forms.TextInput,initial=country, disabled=True)
with
country = forms.CharField(label = _("Country"),widget=forms.TextInput,initial=country, disabled=True)
I found how to solve my issue:
I defined 'country' field outside of the init
and then filed_order works
but doing that, I do not have access to my initial country value, set in init (country= Site.objects.get(sit_abr = instance.asp_par_loc).reg.pay.pay_nom_eng)
I must improve my Python understanding...
I'm trying to update all the values of a queryset with a for, I found this method :
queryset = Query.objects.filter(version=XXX)
field1 = ModelForm.cleaned['field1']
...
fieldN = ModelForm.cleaned['fieldN']
queryset.update(['field1'=field1, ... , 'fieldN'=fieldN])
but I fell like it's not a very clean method, is there a more efficient one ?
I finally did it using this method :
in forms.py:
class UpdateAll(forms.Form):
field_1 = forms.FloatField()
field_2 = forms.FloatField()
field_3 = forms.FloatField()
in views.py :
def update_all(request):
queryset = Model.objects.filter(filter=filter)
if request.method == 'POST':
form = UpdateAll(request.POST)
if form.is_valid():
data = form.cleaned_data
queryset.update(**data)
There is no update() method for model objects. you need to add form data manually to your model.
def update_all(request):
queryset = Model.objects.filter(filter=filter)
if request.method == 'POST':
form = UpdateAll(request.POST)
if form.is_valid():
data = form.cleaned_data
queryset.field_1 = data['field1']
queryset.field_2 = data['field2']
queryset.field_3 = data['field3']
This is my Model class
class SubJobs(models.Model):
id = models.AutoField(primary_key = True)
subjob_name = models.CharField(max_length=32,help_text="Enter subjob name")
subjobtype = models.ForeignKey(SubjobType)
jobstatus = models.ForeignKey(JobStatus, default= None, null=True)
rerun = models.ForeignKey(ReRun,help_text="Rerun")
transfer_method = models.ForeignKey(TransferMethod,help_text="Select transfer method")
priority = models.ForeignKey(Priority,help_text="Select priority")
suitefiles = models.ForeignKey(SuiteFiles,help_text="Suite file",default=None,null=True)
topofiles = models.ForeignKey(TopoFiles,help_text="Topo file",default=None,null=True)
load_image = models.NullBooleanField(default = True,help_text="Load image")
description = models.TextField(help_text="Enter description",null=True) command = models.TextField(help_text="Command",null=True)
run_id = models.IntegerField(help_text="run_id",null=True)
pid_of_run = models.IntegerField(help_text="pid_of_run",null=True)
hold_time = models.IntegerField()
created = models.DateTimeField(default=timezone.now,null=True)
updated = models.DateTimeField(default=timezone.now,null=True)
finished = models.DateTimeField(null=True)
The user might want to update a entry and may choose to update only few fields among these. How do I write a generic update statement that would update only the fields that were passed?
I tried this.
def update_subjob(request):
if (request.method == 'POST'):
subjobs_subjobid = request.POST[('subjob_id')]
post_data = request.POST
if 'subjob_name' in post_data:
subjobs_subjobname = request.POST[('subjob_name')]
if 'subjob_type' in post_data:
subjobs_subjobtype = request.POST[('subjob_type')]
if 'rerun_id' in post_data:
subjobs_rerun_id = request.POST[('rerun_id')]
if 'priority_id' in post_data:
subjobs_priority_id = request.POST[('priority_id')]
if 'transfer_method' in post_data:
subjobs_transfermethod = request.POST[('transfer_method')]
if 'suitefile' in post_data:
subjob_suitefile = request.POST[('suitefile')]
if 'topofile' in post_data:
subjob_topofile = request.POST[('topofile')]
try:
subjobinstance = SubJobs.objects.filter(id=subjobs_subjobid).update(subjob_name=subjobs_subjobname,
updated=datetime.now())
except Exception as e:
print("PROBLEM UPDAING SubJob!!!!")
print(e.message)
How do I write a generic update to update only those fields which are sent in request.POST?
You'd better use Forms. But if you insist on your code it could be done like this.
Suppose you have variable field_to_update where every field that you are waiting in request is listed.
subjobs_subjobid = request.POST[('subjob_id')]
field_to_update = ('subjob_name','subjob_type', 'rerun_id', 'priority_id', 'transfer_method', 'suitefile', 'topofile')
post_data = request.POST
to_be_updated = {field: post_data.get(field) for field in field_to_update if field in post_data}
# then you need to get the object, not filter it
try:
subjobinstance = SubJobs.objects.get(id=subjobs_subjobid)
subjobinstance.update(**to_be_updated, updated=datetime.now())
except ObjectDoesNotExist: # from django.core.exceptions
print('There is no such object') # better to use logger
except Exception as e:
print("PROBLEM UPDAING SubJob!!!!")
print(e.message)
Here are my lines dealing with the two forms :
user = request.user
user_liked = user_liked_form.save(commit = False)
user_liked.user = user
user_liked.save()
user_disliked = user_disliked_form.save(commit = False)
user_disliked.user = user
user_disliked.save()
The data submitted in second form is being saved in both liked and disliked.
I have used User foreignkey in both the liked and disliked models.
Here is the complete function :
def collect(request):
context = RequestContext(request)
submitted = False
if request.method == 'POST':
data = request.POST
user_liked_form = UserLikedForm(data = request.POST)
user_disliked_form = UserDislikedForm(data = request.POST)
# user_id = data["user_id"]
user = request.user
if user_liked_form.is_valid() and user_disliked_form.is_valid():
# user_liked_form.save(commit = True)
# user_disliked_form.save(commit = True)
user_liked = user_liked_form.save(commit = False)
user_liked.user = user
user_liked.save()
user_disliked = user_disliked_form.save(commit = False)
user_disliked.user = user
user_disliked.save()
submitted = True
else:
print user_liked_form.errors, user_disliked_form.errors
else:
user_liked_form = UserLikedForm()
user_disliked_form = UserDislikedForm()
return render_to_response(
'collect.html',
{'user_liked_form': user_liked_form, 'user_disliked_form': user_disliked_form, 'submitted': submitted},
context)
It sounds like your UserLikedForm and UserDislikedForm have the same field names and when the form is submitted, only the second value comes through in request.POST. To fix this, you will need to add a prefix to the forms:
user_liked_form = UserLikedForm(prefix='liked')
user_disliked_form = UserDislikedForm(prefix='disliked')
That way when the forms are rendered, each form will have unique field names.
another django question. I have a edit form like this. Look at current_status in the code.
It has been updated:
def edit_item(request, client_id = 0, item_id = 0):
client = None
item = None
status = None
contact = None
status_id = request.POST.get('status_id', None)
contact_id = request.POST.get('contact_id', None)
save_item = request.POST.get('save_item', None)
save_status = request.POST.get('save_status', None)
try:
client = models.Client.objects.get(pk = client_id)
item = models.StorageItem.objects.get(pk = item_id)
except:
return HttpResponseNotFound()
try:
status = models.Status.objects.get(pk = status_id)
contact = models.Contact.objects.get(pk = contact_id)
except:
pass
if request.method == 'POST':
form = forms.ItemForm(request.POST, instance = item)
if form.is_valid() and save_item is not None:
form.save(True)
request.user.message_set.create(message = "Item {0} has been updated successfully.".format(item.tiptop_id))
return HttpResponse("<script language=\"javascript\" type=\"text/javascript\">window.opener.location = window.opener.location; window.close();</script>")
if status is not None and contact is not None and save_status is not None:
current_status = models.ItemStatusHistory(item = item, contact = contact, status = status,
user = request.user)
item.current_item_status_date = date.today()
item.save()
current_status.save()
request.user.message_set.create(message = "Item status has been updated successfully.")
else:
form = forms.ItemForm(instance = item)
title = str(client) + ' : Edit Item'
status_list = models.Status.objects.all()
return render_to_response('edit_item.html', {'form':form, 'title':title, 'status_list':status_list, 'item':item}, context_instance = RequestContext(request))
current_status save's the latest date of when the form is edited. What I ALSO want to do is to save this value into this models field.
class StorageItem(models.Model):
current_item_status_date = models.DateField()
Is ItemForm a ModelForm (see Django Model Forms)?
If so form.save() will return a model instance. Then you can edit its fields if you need to. For example.
my_obj = form.save()
my_obj.current_item_status_date = datetime.date.today()
my_obj.save()
If not, then simply create a new instance of your model and save the field value.
my_obj = StorageItem(current_item_status_date=datetime.date.today())
my_obj.save()