django url how to use questions mark? (class based views) - django

in my URL for the createview, I want there to be a '?', from where I can pass an argument to the nect page. I am using class based views. For example:
www.site.com/appname/appointment/add/?Name=1
And my HTML would be:
href={% url 'People:appointment-create' Patient.id %}
Currently my URL is like so:
re_path(r'appointment/add/$', views.appointmentCreate.as_view(), name='appointment-create'),
and my view is:
class appointmentCreate(LoginRequiredMixin, CreateView):
model = appointment
form_class = AppointmentForm
def get_initial(self):
patient = self.request.GET.get('patient')
return {
'Patient': patient,
}
How would i go about doing this?

You can try something like this:
href={% url 'People:appointment-create' %}?patient_id={{ Patient.id }}
(so just pass the query arguments after the url as normally).
Also, if you want a more general solution on this problem (automatically generate the form's initial values from query parameters) take a look at this section https://spapas.github.io/#configure-the-form-s-initial-values-from-get-parameters from by article on CBVs.

So here's the basics:
first of all I would like to let you know about below line you just wrote:
{% url 'People:appointment-create' Patient.id %}
to match above url you will need to include below url:
path(r'appointment/add/<int:patient>', views.appointmentCreate.as_view(), name='appointment-create'),
This is the difference between request parameters and kwargs here you pass patient id as kwargs and access in Class base view in self.kwargs
The constructed url will be like below:
www.site.com/appname/appointment/add/1/
Next thing is that if you want to post request parameter (which don't require to add any additional url in your urls.py) you can use as below:
href="{% url 'People:appointment-create' %}?patient={{Patient.id}}"
Note that the parameter you use here will be available in view if you use name in request parameter then you need to access it as self.request.GET.get('name') and if you want to use patient as request parameter then you can access it as self.request.GET.get('patient').

Related

Django get url variables within get_context data?

Say I have a url likes this
path(
'foo/<int:foo_id>/edit/',
views.FooView.as_view(),
name='foo',
),
and a view likes this:
def get(self, request, foo_id):
I find a common idiom is getting the URL variable foo_id into the context.
The only thing context has access to be default is request. I tried checking request and request.GET and could not see anything.
Is there a better way than:
Manually adding url variables to the context_data after get_context_data()
or passing it into get_context_data from a custom call from get? (ugly because class based views expect the same get_context_data signature)
The url parameters are stored in the .kwargs of the view. You thus can access and render these with:
{{ view.kwargs.foo_id }}
There is a reference with the name view that is passed which is the View object that is constructed when handling a request. We thus access the .kwargs attribute of that View object, and in the kwargs, we look for kwargs['foo_id'].
A peculiarity in Django is that a TemplateView [Django-doc] passes all it kwargs items as context data, if your view is thus a TemplateView, then you can render this with
<!-- only a TemplateView -->
{{ foo_id }}

How to get an object with a form and then send it to the next view using urls?

I'm trying to send an object obtained with a ModelChoiceField into a view via urls and views parameters by I don't think that's the right method. I don't know if I have to use POST or GET method.
When I use the GET method, the object is displayed in the url but the view stay the same.
With the POST method, django send errors messages about parameters.
EDIT : I don't remeber the exact messages, I can't recover them for now but as I remember they said something like Reverse for argument not found
My form
class IndividuForm(forms.Form):
individu = forms.ModelChoiceField(queryset=Individu.objects.all()
Here's the view with the form
def index(request):
individu_form = IndividuForm(request.GET or None)
if individu_form.is_valid():
individu_id = individu_form.cleaned_data['individu'].id
HttpResponseRedirect('%i/raison/' % individu_id)
return render(request, 'derog_bv/index.html', {'individu_form':individu_form})
The template where the form is displayed
<form action="{% url 'index' <!-- Errors when I put parameters here --> %} method="<!-- GET or POST -->">
{% csrf_token %}
{{ form }}
<input type="submit">Suivant</input>
</form>
The view where I want to get my object
def raison(request, """ error with this parameter : individu_id"""):
individu = get_object_or_404(Individu, pk=individu_id)
URLs
urlpatterns = [
path('', views.index, name='index'),
path('<int:individu_id>/raison/', views.raison, name='raison'),
]
Ok, so:
1/ you definitly want to use the GET method for your form (you're not submitting data for processing / server state change)
2/ I don't know why you'd want to pass parameters (nor which parameters FWIW) to the {% url %} tag in your index template - you're submitting the form to the index view, which doesn't expect any additional param. Actually you could just remove the action attribute of the HTML form tag since the default (submitting to the current url) is what you want.
3/ your views.raison prototype must match the url definition, so it has to be:
def raison(request, individu_id):
# code here
4/ in your index view:
HttpResponseRedirect('%i/raison/' % individu_id)
you want to build the url using django.core.urlresolvers.reverse instead :
from django.core.urlresolvers import reverse
def index(request):
# code here
if ...:
next = reverse("raison", kwargs={"individu_id": individu_id})
return HttpResponseRedirect(next)
or - even easier - just use the redirect shortcut:
from django.shortcuts import redirect
def index(request):
# code here
if ...:
return redirect("raison", individu_id=individu_id)
There might be other issues with your code but from the infos you posted, those hints should at least put you back on tracks.

Add query string to url in Django

I have a form which sends a POST request and returns a page. The url of this page is defined like this
(r'^result/', 'main.views.eval_form'),
and in the browser the url looks like
mysite.com/main/result
But I also have the url working with a Get Request so the user could save the url and not have to use the form, ie:
mysite.com/main/result?name=Tom&color=blue&etc=etc
Now is there a way to alter the url in the browser after the user uses the form, to include the query string by default? So that the user can copy the url and always return to result?
Thank you!
Change the method attribute of the <form> tag:
<form action="/main/result/" method="GET">
...
</form>
You could do a HttpResponseRedirect to the url with the prefilled querystring from the Post view.
Make sure you don't submit it twice or create an infinite loop.
return HttpResponseRedirect("/result?name={}&color={}&etc={}".format(name, color, etc))
Another way would be to fill your querystring with jQuery or Javascript from the template.
Myself I would take catavaran's approach
If you want to achieve this, you should alter your view to deal with both post and get request.
code may be like this:
def result(request):
name = request.REQUEST.get("name")
but request.REQUEST is deprecated since django 1.7
def result(request):
if request.method == "GET":
name = request.GET.get("name")
if request.method == "POST":
name = request.POST.get("name")

Retrieving ID from URL

Django question here. So in my base.html, I have a header. The header has links that go to user specific pages. That is, URL's like: /1234/home, /1234/about, etc. where 1234 is the id of a user. My question is, if I want to create a url pointing to a django view method called home with signature home (request, user=0) where user is a different user from the logged in user, how would I do this in the template? To clarify, I am using Django's {% url ... %} template tag and I can't just do {% url [view_name] request.user.id %} because I want the user id from the url, not the id of the logged in user. Additionally, I would prefer avoiding passing a template variable to get the id of the user in the url because then I would have to do that on every page.
Get the id you want as a kwarg to your view, and pass it as a variable to your template through the context to use in the {url ...}.
If you want to persist a variable across all your templates, look at context processors. They are added to each RequestContext so they are accessible to all templates assuming you use the render shortcut or pass the RequestContext to your template.render.
https://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext
https://github.com/django/django/blob/stable/1.5.x/django/core/context_processors.py
There are some default ones that django uses. It's fairly simple to add your own.
I imagine your context processor will look something like
context_processors.py
def id_from_url(request):
# Find url id component in request.path
return { 'url_id' : url_id }
Then just add to your settings file appname.context_processors.id_from_url

django {% url %} tag without parameters

I have a url defined as follows:
url(r'^details/(?P<id>\d+)$', DetailView.as_view(), name='detail_view'),
In my templates, I want to be able to get the following url: /details/ from the defined url.
I tried {% url detail_view %}, but I get an error since I am not specifying the id parameter.
I need the url without the ID because I will be appending it using JS.
How can I accomplish this?
Just add this line to your urls.py:
url(r'^details/$', DetailView.as_view(), name='detail_view'),
or:
url(r'^details/(?P<id>\d*)$', DetailView.as_view(), name='detail_view'),
(This is a cleaner solution - thanks to Thomas Orozco)
You'll need to specify that id is optional in your view function:
def view(request, id=None):