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
Related
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
}
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
My urls.py has an entry:
urlpatterns = [
url(r'^results/(?P<query>).+', views.ResultsView.as_view(), name="results"),
]
which matches to the corresponding Class Based View:
class ResultsView(TemplateView):
template_name = os.path.join(APPNAME, "results.html")
def dispatch(self, request, *args, **kwargs):
query = kwargs['query']
print("HERE: " + str(json.dumps(kwargs, indent=1)))
print(self.kwargs['query'])
print(self.kwargs.get('query'))
print(kwargs['query'])
print(kwargs.get('query'))
if query is None:
return redirect('/')
return super(ResultsView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(ResultsView, self).get_context_data(**kwargs)
print("HERE: " + str(json.dumps(kwargs, indent=1)))
print(self.kwargs['query'])
print(self.kwargs.get('query'))
print(kwargs['query'])
print(kwargs.get('query'))
...
# This is just here to test if 'query' is set
def get(self, request, query):
print(query)
I'm trying to get the value of the query variable that is set in urls.py. However, after trying various solutions I found on other SO posts (as you can see from all the print statements), nothing is working.
I'm fairly sure my urls.py is set up properly, because the request resolves to the correct page (results/), but all attempts to print the query entry of the dict return an empty string, and json.dumps(kwargs, indent=1)) prints this:
HERE: {
"query": ""
}
What am I doing wrong?
Just copy my comment as an answer. You missed pattern part in url's regular expression. Try to change url to this:
url(r'^results/(?P<query>[\w.-]+)', views.ResultsView.as_view(), name="results")
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.
I am trying to amend my get_success_url so that if any kwargs have been passed to it, I can build the returned url using them.
Heres what I have so far:
class CalcUpdate(SuccessMessageMixin, UpdateView):
model = Calc
template_name = 'calc/cru_template.html'
form_class = CalcForm
def archive_calc(self, object_id):
model_a = Calc.objects.get(id = object_id)
model_b = Calc()
for field in model_a._meta.fields:
setattr(model_b, field.name, getattr(model_a, field.name))
model_b.pk = None
model_b.save()
self.get_success_url(idnumber = model_b.pk)
def form_valid(self, form):
#objects
if self.object.checked == True:
object_id = self.object.id
self.archive_calc(object_id)
#save
def get_success_url(self, **kwargs):
if kwargs != None:
return reverse_lazy('detail', kwargs = {'pk': kwargs['idnumber']})
else:
return reverse_lazy('detail', args = (self.object.id,))
So far this just gives a keyerror detailing 'idnumber'.
I have printed kwargs['idnumber'] and it returns the pk as expected however I just cant seem to see where I am going wrong with this.
Thanks in advance.
form_valid should return a HttpResponseRedirect https://github.com/django/django/blob/master/django/views/generic/edit.py#L57 which in your case, you never do. I dont know if you have any code after #save, but take a look at the comments I made in your code
class CalcUpdate(SuccessMessageMixin, UpdateView):
model = Calc
template_name = 'calc/cru_template.html'
form_class = CalcForm
def archive_calc(self, object_id):
model_a = Calc.objects.get(id = object_id)
model_b = Calc()
for field in model_a._meta.fields:
setattr(model_b, field.name, getattr(model_a, field.name))
model_b.pk = None
model_b.save()
return self.get_success_url(idnumber = model_b.pk) # you never return this value
def form_valid(self, form):
#objects
if self.object.checked == True:
object_id = self.object.id
return HttpResponseRedirect(self.archive_calc(object_id)) # you never return a `HttpResponse`
#save -- If this is where you are saving... you can store the value from archive and return it after saving
def get_success_url(self, **kwargs):
if kwargs != None:
return reverse_lazy('detail', kwargs = {'pk': kwargs['idnumber']})
else:
return reverse_lazy('detail', args = (self.object.id,))
Also you don't need to manually copy the fields, just do (assuming there are no unique constraints because if there were, your version would fail too):
def archive_calc(self, object_id):
c = self.model.objects.get(id = object_id)
c.pk = None
c.save()
return self.get_success_url(idnumber = c.pk)
After playing around with #Ngenator's answer and various other posts on here I have the following working code. However its not very nice to look at :(
def get_success_url(self):
if self.pknumber != None:
return reverse_lazy('pstdetail', args = (self.pknumber,))
else:
return reverse_lazy('pstdetail', args = (self.object.id,))
I have this self.pknumber = model_b.pk in the necessary place within the view and self.pknumber = None else where to enable the if statement to build the required url. Hope this helps anyone and feel free to point out any errors/improvements.
https://ccbv.co.uk/projects/Django/4.0/django.views.generic.edit/UpdateView/
You cannot pass parameters in get_success_url(self) method. You can only refer to self parameter. For example self.kwargs['pk'].