UnboundField object error with dynamic forms - python

I have a dynamic form:
class CollectionRequestParamForm(Form):
param_human_name = StringField(validators=[DataRequired()])
param_request_name = StringField()
class CollectionRequestParamCombinedForm(FlaskForm):
params = FieldList(FormField(CollectionRequestParamForm), min_entries=2)
submit = SubmitField('Submit')
And I want to set min_entries from code in view, like:
collection_request_params_form = CollectionRequestParamCombinedForm(min_entries=5)
I do this:
class CollectionRequestParamCombinedForm(FlaskForm):
def __init__(self, min_entries, *args, **kwargs):
FlaskForm.__init__(self, *args, **kwargs)
self.params = FieldList(FormField(CollectionRequestParamForm), min_entries=min_entries)
submit = SubmitField('Submit')
But: TypeError: 'UnboundField' object is not iterable
What is causing this error?

do this if you want to make it dynamic
for i in range(min_entries):
form.params.append_entry()
more for details https://stackoverflow.com/a/48710958/9218468

Related

Django testing: post request with a Form with paramters

I want to test that my view redirects after I send it correct data. The problem is that I'm using a form that needs parameters while initializing. I have a method that builds me a response that I later use in the tests. The method works for my other views but I can't make it work with views that use Forms that need parameters to initialize them.
In my forms.py I have:
class SupportIssueForm(forms.ModelForm):
class Meta:
model = SupportIssue
fields = ('user', 'property', 'title', 'text', 'is_urgent', 'is_service')
def __init__(self, person_company, properties, is_property, *args, **kwargs):
super(SupportIssueForm, self).__init__(*args, **kwargs)
self.fields['is_service'].widget.attrs['class'] = 'custom-control-input'
...
My method for generating the response I'm later using in my test looks like this:
def generate_logged_in_user_post_response(self, data):
request = self.factory.post(self.url, data={**self.form_class_args[0], **data})
request.user = self.logged_in_user
return new_support_issue_view(request)
I also tried this:
def generate_logged_in_user_post_response(self, data):
form = SupportIssueForm(**self.form_class_args[0], data=data)
request = self.factory.post(self.url, form)
request.user = self.logged_in_user
return new_support_issue_view(request)
the self.form_class_args[0] is some dictionary I declare elsewhere:
{
"person_company": person_company, # <query object>
"properties": properties, # <query object>
'is_property': False
}

some troubles with CreateView in the Django

class Biochemical_analysis_of_blood(CreateView):
model = BiochemicalAnalysisOfBlood
form_class = BiochemicalAnalysisOfBloodForm
template_name = "biochemical_analysis_of_blood.html"
success_url = reverse_lazy("patients")
def get_context_data(self, **kwargs):
context = super(Biochemical_analysis_of_blood, self).get_context_data(**kwargs)
patient = Patient.objects.get(id=1)
context["patient"] = patient
return context
def post(self, request, *args, **kwargs):
analysis = Analyzes()
sid = transaction.savepoint()
analysis.name = request.POST["name"]
analysis.patient_id = Patient.objects.get(id=1)
analysis.who_send = request.POST["who_send"]
analysis.who_is_doctor = request.POST["who_is_doctor"]
analysis.lab_user_id = Doctor.objects.get(id=request.POST["lab_user_id"])
analysis.additional_lab_user = request.POST["lab_user_add"]
analysis.date = '2017-06-18'
analysis.type = 3
analysis.date_analysis = '2017-06-18'
analysis.save()
return super(Biochemical_analysis_of_blood, self).post(request, *args, **kwargs)
I have next algorithm:
Render BiochemicalAnalysisOfBloodForm to the user
When he fills fields and presses button "save" I create a new instance of Analyzes() and fill it programmatically and when in the post method I call super().post() then users data will be written to the model BiochemicalAnalysisOfBlood automatically? But I have next error:
NOT NULL constraint failed:
laboratory_biochemicalanalysisofblood.analysis_id
How can I in hand mode add to the model to the field "analysis" the early created instance of Analyzes()? I don't understand this class to the end where I can find information about all it's opportunities
The main part of your algorithm should reside in your form, because you want to pass the analysis_id to the instance being saved
class BiochemicalAnalysisOfBloodForm(ModelForm):
def save(self, commit=True):
analysis = Analyzes()
sid = transaction.savepoint()
analysis.name = self.data["name"]
analysis.patient_id = Patient.objects.get(id=1)
analysis.who_send = self.data["who_send"]
analysis.who_is_doctor = self.data["who_is_doctor"]
analysis.lab_user_id = Doctor.objects.get(id=self.data["lab_user_id"])
analysis.additional_lab_user = self.data["lab_user_add"]
analysis.date = '2017-06-18'
analysis.type = 3
analysis.date_analysis = '2017-06-18'
analysis.save()
# Your analysis is created, attach it to the form instance object
self.instance.analysis_id = analysis.id
return super().save(commit)
Before doing the super().post you can modify the request.POST data to include your analysis id:
request.POST['analysis_id'] = analysis.id
that might help.
Also note that if the form validation fails in super().post, you will still have created an Analysis object which might not be useful. You could use override the form_invalid method of the CreateView to handle this.

On django admin why is django adding ?_changelist_filters to url?

Why django adds on url ?_changelist_filters=user%3D5275 when I click on add? My url on change_list was ?user=5275 initially.
The issue is that the user should be selected in the select input and it isn't. If i change it in ?user=5275 is working.
How can I make django to 'read'?_changelist_filters=user%3D5275 or to change it in ?user=5275
You can add in AdminForm something like this:
class UsersAdminForm(forms.ModelForm):
#staticmethod
def parse_filter_kwargs(**kwargs):
if 'initial' in kwargs:
if u'_changelist_filters' in kwargs['initial']:
filters = kwargs['initial'][u'_changelist_filters']
var, value = filters.split('=')
if var == u'user':
return {'initial': {var: value}}
return kwargs
def __init__(self, *args, **kwargs):
kwargs = self.parse_filter_kwargs(**kwargs)
super(UsersAdminForm, self).__init__(*args, **kwargs)
solution for all _changelist_filters params
class ProductForm(forms.ModelForm):
#staticmethod
def parse_filter_kwargs(**kwargs):
if 'initial' in kwargs:
if u'_changelist_filters' in kwargs['initial']:
filters = kwargs['initial'].pop('_changelist_filters')
for key, value in [p.split('=') for p in filters.split('&')]:
kwargs['initial'][key] = value
return kwargs
def __init__(self, *args, **kwargs):
kwargs = self.parse_filter_kwargs(**kwargs)
super(ProductForm, self).__init__(*args, **kwargs)
from urllib.parse import parse_qsl
query_params = dict(parse_qsl(request.GET['_changelist_filters']))
print(query_params.get('user'))

Django - Getting parameters from URL

I am passing the parameters in URL to my view like this:
127.0.0.1:8000/cars/?model_number=13375
and getting it like this:
class GetCarDetails(View):
def get(self, *args, **kwargs):
model_number = "";
if request.GET.get('model_number'):
model_number = request.GET.get('model_number')
But I want to pass it now like this:
127.0.0.1:8000/cars/13375/
And I want Django to treat the 13375 like model number
You need to define it at the url's:
url(r'^cars/(?P<pk>[0-9]+)/$', views.GetCarDetails.as_view(), name="getcardetails"),
And in your views:
class GetCarDetails(View):
...
def get_context_data(self, **kwargs):
context = super(GetCarDetails, self).get_context_data(**kwargs)
context["model_number"] = self.kwargs['pk'];
return context
As told by #Anentropic in comments, more detailed info here

django - how to replace startElement in XML?

I'm trying to generate a custom HTML and I have a value I want to pass into xml.startElement (or root if you're thinking in generic terms). How do I go about doing this?
I'm currently using django rest framework a class view and a custom renderer -
This is the beginning of the renderer -
class TESTRenderer(renderers.BaseRenderer):
media_type = 'application/xml'
format = 'xml'
charset = 'utf-8'
def render(self, data, accepted_media_type=None, renderer_context=None):
"""
Renders *obj* into serialized XML.
"""
if data is None:
return ''
stream = StringIO()
xml = SimplerXMLGenerator(stream, self.charset)
xml.startDocument()
xml.startElement(header.data, {})
So as you can see I'm trying to pass a variable called header into the xml.startElement
Here's the view where that data lies -
class TestDetail(APIView):
permission_classes = (AllowAny,)
"""
Retrieve, update or delete a snippet instance.
"""
def get(self, request, pk, format=None):
jobmst_name = queryset1
nodmst_alias = queryset2
sysval_integer = queryset3
mst = queryset4
dtl = queryset5
dep = queryset6
trg = queryset7
name = str(jobmst_name)
master = str(nodmst_alias)
dbversion = str(sysval_integer)
header = 'job id="%s" name="%s" master="%s" dbversion="%s" xmlversion="1"' % (pk, name, master, dbversion)
jobmststring = JobmstSerializer(mst)
jobdtlstring = JobdtlSerializer(dtl)
jobdepstring = JobdepSerializer(dep, many=True)
trgjobstring = TrgjobSerializer(trg, many=True)
jobmst_serialized = {'jobmst': jobmststring.data}
jobdtl_serialized = {'jobdtl': jobdtlstring.data}
jobdep_serialized = [{'jobdep':item} for item in jobdepstring.data]
trgjob_serialized = [{'trgjob':item} for item in trgjobstring.data]
jobgroup = header, jobmst_serialized, jobdtl_serialized, jobdep_serialized, trgjob_serialized
return TestResponse(jobgroup)
The response it's using is here -
class TestResponse(HttpResponse):
"""
An HttpResponse that renders its content into XML.
"""
def __init__(self, data, **kwargs):
content = TESTRenderer().render(data)
kwargs['content_type'] = 'application/xml'
super(TestResponse, self).__init__(content, **kwargs)
Is there something I'm missing with the TestDetail where I should separate the header from the data?
maybe like this?
return TestResponse (header, jobgroup)
and then alter TestResponse to include?
def __init__(self, header, data, **kwargs):
I don't know python/django. but it seems the "Value" you are talking about are actually attributes you want to assign to the element node. I posted the same on your /r/django thread about this.

Categories

Resources