django-form show form data after saving it - python

I want to show same data to user as posted by him using form after saving it in database.
I am not getting the logic for it.
I am trying to do something like this:
def CreateDeal(request):
if request.method == "POST":
form = DealForm(request.POST)
if form.is_valid():
form.save(commit = True)
data = form.data
return render(request, '/path_to/deal_detail.html',data=data)
Is it ok ?
Is there any better way to do it?

If you do it this way, a redirect of the "detail" page will resubmit the form. This is generally not desired behaviour.
A better way would be to create a detail view for you saved object (if you haven't already) and redirect the user to the detail view of that particular object:
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
def CreateDeal(request):
if request.method == "POST":
form = DealForm(request.POST)
if form.is_valid():
obj = form.save(commit=True)
return HttpResponseRedirect(reverse('deal-detail-view', args=(obj.id,)))
# or return HttpResponseRedirect(obj.get_absolute_url())
# if `get_absolute_url` is defined

Related

Problems with Django URL routing

I'm building a website, to be used in dental practices, however I'm having trouble with the URL routing. I'm wanting af URL pattern like: Denthelp/kartotek/#nameofclinic#/opretpatient.
My suggestion looks like this:
urls.py:
path('kartotek/<str:kl_id>/', views.kartotek, name="kartotek"),
path('kartotek/<str:kl_id>/opretpatient/', views.opretpatient, name="opret_patient"),
Views. py:
def kartotek(request, kl_id):
kliniknavn = Klinik.objects.get(navn=kl_id)
E_patient = kliniknavn.patient_set.all()
context = { 'kliniknavn':kliniknavn, 'E_patient':E_patient}
return render(request,'DentHelp/kartotek.html', context )
def opretpatient(request, kl_id):
kliniknavn = Klinik.objects.get(navn=kl_id)
form = PatientForm()
if request.method == 'POST':
form = PatientForm(request.POST)
if form.is_valid():
form.save()
return redirect('kartotek/<str:kl_id>/')
context = {'form':form, 'kliniknavn':kliniknavn}
return render(request,'DentHelp/kartotek/<str:kl_id>/opretpatient.html', context)
When running code I get an OSError for the last line of code shown here.
Have you guys have any advise for this to work?
You are mixing up render with redirect. render renders a template dynamically with attributes from context, where redirect redirects the user to a different view. To call render, you need to provide template name and context. For redirect, you need to provide url name and parameters (if required). Here is how you should do in your code:
def opretpatient(request, kl_id):
kliniknavn = Klinik.objects.get(navn=kl_id)
form = PatientForm()
if request.method == 'POST':
form = PatientForm(request.POST)
if form.is_valid():
form.save()
return redirect('kartotek', kl_id) # url name and parameter
context = {'form':form, 'kliniknavn':kliniknavn}
return render(request, 'DentHelp/kartotek/opretpatient.html', context) # template name and context

Unable to get or create object within a form

I am trying to get or create an object when another one is created with a form :
def index(request, log_id, token):
log = get_object_or_404(LogBook, pk=log_id)
logmessages = LogMessage.objects.filter(logbook=log_id)
form = CreateLogMessage(request.POST)
if request.method == "POST":
if form.is_valid():
instance = form.save(commit=False)
instance.reported_by = request.user
instance.logbook = log
instance.save()
logdone = LogDone.objects.get_or_create(logmessage=logmessages, done_status=False)
I am trying to figure out a way to get the id of the logmessage created to pass it to my logdone instance.
I don't find a way to do it so far, any help will be appreciate it.
The object that is created is the instance, you thus can implement this as:
from django.shortcuts import redirect
def index(request, log_id, token):
log = get_object_or_404(LogBook, pk=log_id)
if request.method == 'POST':
form = CreateLogMessage(request.POST)
if form.is_valid():
form.instance.reported_by = request.user
form.instance.logbook = log
instance = form.save()
logdone = LogDone.objects.get_or_create(
logmessage=instance,
done_status=False
)
return redirect('name-of-some-view')
else:
form = CreateLogMessage(request.POST)
…
Since your form creates a new object every time, this however always create an object.
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].

how to display login_required_message in django

I want to display login_required message like you have to login first to give the review while redirecting to the login page. How can i achieve this.
views.py
#login_required(redirect_field_name='next',login_url='shop:users_signin')
def review(request,slug):
if request.method == "POST":
form = ReviewForm(request.POST)
if form.is_valid():
review = form.save(commit=False)
review.product = Product.objects.get(slug=slug)
review.user = request.user
review.save()
messages.success(request, 'Review Saved.')
return redirect('shop:detail', slug)
else:
return redirect('shop:detail',slug)
#login_required decorator is for convenience but doesn't make it easy to customise the behaviour. If you use CBVs, the LoginRequiredMixin makes it easier, because you can override handle_no_permission() to add a message to the request before the redirect occurs.
So the best alternative you have if you use simple function based views it to write the authentication check yourself:
def review(request, slug):
if not request.user.is_authenticated:
messages.info("You need to be logged in in order to give a review")
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
# rest of your view here
And then in your login template make sure you display the message.

Django - best practice for getting ID from querystring into edit view

I'm wondering what the acceptable best practice is for pulling an id from a url for use in the edit view. Most example code I see uses slugs, which I don't need to deal with because SEO is not a concern.
Say I have something like:
def article_edit(request):
if request.method == 'POST': # If the form has been submitted...
#a = get_object_or_404(Article, **?XXX?**)
#a = Article.objects.get(pk=**?XXX?**)
form = ArticleForm(request.POST, instance=a) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
form.save()
return redirect('/articles/') # Redirect after POST
else:
form = ArticleForm() # An unbound form
return render(request, 'article_form.html', {'form': form})
Where I have commented out two possible options for populating a with an Article object based on the ID submitted in the POST. The ?XXX? indicates that I'm not sure how to reference the passed in id.
Any input on those two options, as well as alternative options are appreciated.
Passed in id should go in the url itself, like:
url(r'^articles/(?P<id>\d+)/edit/$', 'views.article_edit', name = 'article_edit'),
Then, in the view you can reference it from the view argument id:
def article_edit(request, id):
if request.method == 'POST': # If the form has been submitted...
article = get_object_or_404(Article, pk=id)
Also, take a look at Writing a simple form chapter of django "polls" tutorial - the same approach is used.
Hope that helps.
try this:
urls.py :
url(r'^articles/(?P<article_id>\d+)/edit/$', 'views.article_edit', name = 'article'),
views.py:
def article_edit(request, id):
if request.method == 'POST':
article = get_object_or_404(Article,id=article_id)

Django form submit again on refresh

Hello I am working on a simple form. The form submits fine but if I refresh the page it resubmits the data. Seems the form is holding the data after submit and I assume since after the submit the request method is post. Question is what is the best way after the submit to clear the form in Django. After the submit the form variables should not be holding the values anymore. Thanks
def testimonials(request, template_name="testimonials.html"):
reviews = Reviews.objects.all()
if request.method == 'POST':
form = forms.ReviewsForm(data = request.POST)
# create a new item
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
if form.is_valid():
nameIn = form.cleaned_data['name']
reviewIn = form.cleaned_data['review']
newReview = Reviews(name = nameIn, review = reviewIn)
newReview.save()
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
else:
# This the the first page load, display a blank form
form = forms.ReviewsForm()
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
Typically, you would issue a redirect after processing a form/POST request (this is common web development practice to avoid the resubmission issue you mentioned). So instead of a render_to_response, you might issue a HttpResponseRedirect like so:
if form.is_valid():
# Process form as desired here
# Simple example; use reverse() to avoid hard-coding URLs
return HttpResponseRedirect('/success/')
Check out the using a form in view for a skeleton of how forms are typically processed.
use reverse instead of render to response
if form.is_valid():
nameIn = form.cleaned_data['name']
reviewIn = form.cleaned_data['review']
newReview = Reviews(name = nameIn, review = reviewIn)
newReview.save()
return HttpResponseRedirect(reverse('app_name:url'))
You could also use the 'redirect' shortcut:
from django.shortcuts import redirect
...
return redirect(newReview)
This is assuming you have get_absolute_url defined in your Review Model.
See the docs for more info.

Categories

Resources