How to passing a value from one Django view to another view? - django

I have a value - obtained after saving a Django form.
After saving the form - I redirect the Django application to another view.
Along with redirecting to another view, I want to pass the value that was in the previous view.
How can this be done - passing a value from one Django view to another view?
I'm trying to do this one by one, but I'm getting an error.
If you have the opportunity, I would be grateful for any information or help.
view_1
def form_1(request):
context = {}
form_2 = Form_new_form1_1(request.POST or None)
if form_2.is_valid():
model_instance = form_2.save(commit=False)
values_name = model_instance.name
nm_kot = values_name
request.session['nm_kot'] = nm_kot
return redirect("form_1_2")
context['form_2'] = form_2
return render(request, "form_1.html", context)
view_2
def form_1_2(request):
context = {}
nm_kot = request.session['nm_kot']
nomer = nm_kot
name = nomer
return redirect("tabl_1")
error
response = self.process_response(request, response)
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Model_Model is not JSON serializable
[05/Feb/2023 18:00:20] "POST /zamer_form_1 HTTP/1.1" 500 114735

Django session uses by defaut json serialization and therefore you will need to serialize your data to json.
I don't recommend switching to pickle which will solve your issue but is not recommended.
You can use json.dumps and json.loads to serialize and deserialize the data.
https://docs.djangoproject.com/en/4.1/topics/http/sessions/#session-serialization
https://docs.djangoproject.com/en/4.1/topics/http/sessions/#examples

Related

What is the difference between using Django form and manually setting date fields?

I am getting date/time info from ajax to Django. I am using 2 different views. event_edit is working fine, but event_edit_new does not work. It return an error Enter a valid date/time.
My question is what is making difference. They are getting exactly same information but one is ok while other one is not.
Javascript code making ajax request:
var ajax_test = function(event){
$.ajax({
url: '/scheduler/event/' + event.eventId + '/edit2/',
method: 'POST', // 'POST' or 'PUT'
data: {
'Note': event.title,
'OpNum': event.resourceId,
'StartTime' : event.start.format(),
'StopTime' : event.end.format(),
'ScheduleNum': event.eventId,
}
}).done(function(res) {
console.log("done", res)
}).fail(function(error) {
console.error("error", error)
console.log(event.start.format());
});
}
2 views
def event_edit(request, pk):
schedule = get_object_or_404(Schedule, pk=pk)
schedule.OpNum = request.POST.get('OpNum')
schedule.Note = request.POST.get('Note')
schedule.StartTime = request.POST.get('StartTime')
schedule.StopTime = request.POST.get('StopTime')
schedule.ScheduleNum =request.POST.get('ScheduleNum')
schedule.save()
return HttpResponse('ok')
def event_edit_new(request, pk):
schedule = get_object_or_404(Schedule, pk=pk)
if request.method =='POST':
form = ScheduleForm(request.POST, request.FILES, instance = schedule)
if form.is_valid():
form.save()
return HttpResponse('ok')
else:
return HttpResponse('error')
else:
return HttpResponse('done')
In your first view, there is no validation applied to user data input:
schedule.StartTime = request.POST.get('StartTime')
schedule.StopTime = request.POST.get('StopTime')
request.POST does not validate any data so that will grab user data exactly as submitted and set it on a model. Note that it might work but it is not guaranteed to work if user will ever send datetime format the application does not understand. For example try submitting something like "invalid date" and you should get 500 error.
Your second view on the other hand uses a Django Form to validate user input. By using a form you are validating user input before processing it in any way. You did not paste how your form is structured however if you are getting Enter a valid date/time. this means Django form did not validate one of the datetime fields. There are couple of reasons why that might be:
submitted datetime does is not one of input_formats for a DateTimeField. You can customize the formats with:
class MyForm(forms.Form):
datetime_field = forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M:%SZ', ...])
submitted datetime is not one of Django's default supported datetime formats.
You can customize them with DATETIME_INPUT_FORMATS setting.

Update Existing Document : Mongo Alchemy

I need some help with MongoAlchemy. I'm trying to create a web application with python, flask, Mongo DM and Mongo Alchemy (as an object document mapper) and I'm struggling with updating existing documents.
My problem is that I cannot update an existing document through it's object Id. Below I'm attaching my def for updating
#app.route('/update', methods =[ 'GET', 'POST' ])
def update():
if request.method == 'POST':
id = request.form['object_id'] # Getting values with html
patientzero = BloodDoonor.query.get_or_404(id)
first_name = request.form['name']# Getting values with htmlform
last_name = request.form['surname']# Getting values with html form
blood_type = request.form['blood_type']# Getting values with html
update_record = BloodDoonor.patientzero.update(BloodDoonor.last_name = last_name)
return render_template('update.html', result = result)
And flask gives me that error:
AttributeError AttributeError: type
object 'BloodDoonor' has no attribute 'patientzero'
I'm very new to Python and not very good in code. Please forgive me for the sloppy description I gave above. Any help would be appreciated.
To update an existing document just change the value of the object which you queried from db with form values and then just save that object:
#app.route('/update', methods =[ 'GET', 'POST' ])
def update():
if request.method == 'POST':
id = request.form['object_id']
patientzero = BloodDoonor.query.get_or_404(id)
patientzero.first_name = request.form['name']
patientzero.last_name = request.form['surname']
patientzero.blood_type = request.form['blood_type']
patientzero.save()
return render_template('update.html')

get a variables by GET in method get in DetailView django

Im trying to get the variable "segundos" by GET in the Detail View, im trying to get it by the method get:
the js file:
$(document).ready(function(){
var segundos=340;
console.log(segundos);
$.ajax({
data : {'segundos':segundos},
url : '/ajax/puzzle-1/',
type : 'GET',
});
});
views.py
class PuzzleView(DetailView):
model = Puzzle
template_name = 'puzzle.html'
def get (self,request,*args,**kwargs):
seconds = request.GET["segundos"]
self.object = self.get_object()
ranking = Ranking.objects.create(puzzle_id=self.object.id,usuario=self.request.user,segundos=seconds,puesto=89)
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
class RankingView(ListView):
model = Ranking
template_name = 'ranking.html'
queryset = Ranking.objects.filter(puzzle_id=1).order_by('segundos')[:3]
class PuzzleAjaxView(TemplateView):
template_name = 'ranking.html'
But i get the famous error "MultiValueDictKeyError". If i try the same method "get" but with a TemplateView, i can get the variable, but not with DetailView
Just in case, my urls.py:
urlpatterns = patterns('puzzle.views',
url(r'^actividad/puzzle/(?P<slug>[-_\w]+)/$',PuzzleView.as_view(),name='puzzle'),
url(r'^ajax/puzzle-1/.*$', PuzzleAjaxView.as_view(),name='ajax'),
url(r'^ranking/.*$', RankingView.as_view(),name='ranking'),
)
seconds = request.GET("segundos")
You can't just call the GET MultiValueDict. You must access by dictionary lookup. It is a subclass of a dict.
request.GET.get('segundos')
request.GET['segundos']
Update
For future reference, your exception traceback would have explained all of this, but the error message should be pretty clear: something along the lines of segundos not being a valid key in the MultiValueDict.
I assume your PuzzleView (what you are calling the DetailView) never gets passed any GET parameters because your example shows GET params only with your AJAX call, which is mapped to your PuzzleAjaxView (what you are calling the TemplateView
What is determining whether or not your get function works or not isn't based on the fact that your view class is a TemplateView or DetailView, it's the fact that segundos is only passed to your AJAX view.
In other words.. any view (TemplateView, DetailView, doesn't matter) accessing a GET dict via direct lookup request.GET['foobar'] will fail if that get parameter isn't passed in.

Is it possible to return an HttpResponse in django with text & a json object?

In my view function, I'd like to return a json object (data1) and some text/html (form). Is this possible?
Here is part of my views.py:
if request.is_ajax() and request.method == 'POST':
...
if form.is_valid():
answer = form.cleaned_data['answer'] # Answer extracted from form is also a string
a1 = ques1.correct_answer
if a1 == answer:
test1 = question_list.get(id=nextid)
form = AnswerForm(test1)
ques1 = question_list.filter(id=nextid) # Filter next question as <qs>
data1 = serializers.serialize("json",ques1) # Json-ize
# ********EDITED HERE **********
variables1 = Context({
'form' : form,
'q1' : data1,
})
#response = HttpResponse()
#response['data1'] = response.write(data1)
#response['form'] = response.write(form)
if nextid <= qsnlen:
return HttpResponse(variables1, mimetype="application/json")
#return HttpResponse(response)
else:
...
I'd like to send back both the form html and the ques1 json object. How can I do this? Thanks in advance.
Just put both pieces of data in a JSON container, one key with the form data and one with the HTML as a rendered string. In the browser, you can just pull both keys out & do your thing.
In your view:
form_json_data = get_form_json_data()
rendered_html = get_the_html()
return HttpResponse(json.dumps({
"formdata": form_json,
"html": rendered_html}),
content_type="application/json")
In js:
$.post(foo, postdata, function(data){
var formdata = data.formdata
var html = data.html;
$(".html-target").replaceWith(html);
do_whatever(formdata);
})
Use JsonResponse
from django.http import JsonResponse
response_data = {put your data into a dict}
return JsonResponse(response_data, status=201)
To do this with one response; you need to send the JSON as a plain text in the context of your template response (HTML).
If you need to send JSON as as a separate JSON object, with its own mime type, then you need to write two views; one that sends back the JSON as application/json and the other that sends back the form (HTML).
EDIT:
You are not returning JSON objects, but you are turning a dictionary that has two items of two different types. As I explained in the comments, in one request/response cycle; you can only return one response which has a specific mime type that is based on the content and how you want the browser to handle it. Most of the time the content type is 'text/html'.
In your scenario, if you want to return both the HTML (which is your form), and the JSON response (which is a string), you need to return HTML.
If you want to return JSON to Jquery as a JSON object; you need to detect the request type. In your front end (the templates), you will initiate two requests - one from the browser, which will return back the form. The other from jQuery, which will return the appropriate JSON object.
Here is a possible approach to this:
def foo(request):
if request.is_ajax():
ctx = dict()
ctx['hello'] = 'world'
return HttpResponse(json.dumps(ctx),content_type='application/json')
else:
return HttpResponse('hello world')

Storing user's avatar upon registration

I have an extended UserProfile for registering new users. My user_created function connects to signals sent upon registering basic User instance and creates new UserProfile with extended fields from my form. Here's the code :
from registration.signals import user_registered
from accounts.forms import ExtendedRegistrationForm
import accounts
from accounts.models import UserProfile
def user_created(sender, user, request, **kwargs):
form = ExtendedRegistrationForm(request.POST, request.FILES)
data = UserProfile(user=user)
data.is_active = False
data.first_name = form.data['first_name']
data.last_name = form.data['last_name']
data.pid = form.data['pid']
data.image = form.data['image']
data.street = form.data['street']
data.number = form.data['number']
data.code = form.data['code']
data.city = form.data['city']
data.save()
user_registered.connect(user_created)
Problem is that on this form I have an image field for avatar. As you can see from the code, I'm getting data from form's data list. But apparently imageField does not send it's data with POST request(as I'm getting MultiValueDictKeyError at /user/register/, Key 'image' not found in <QueryDict...) so I can't get it from data[] .
alt text http://img38.imageshack.us/img38/3839/61289917.png
If the usual variables are inside 'data', where should I look for files ? Or is the problem more complicated ? Strange thing is that my form doesn't have attribute cleaned_data... I was using dmitko's method here : http://dmitko.ru/?p=546&lang=en . My :
forms : http://paste.pocoo.org/show/230754/
models : http://paste.pocoo.org/show/230755/
You should be validating the form before using it, which will create the "cleaned_data" attribute you're used to. Just check form.is_valid() and the "cleaned_data" attribute will be available, and should contain the file.
The form's "data" attribute is going to be whatever you passed in as its first initalization argument (in this case, request.POST), and files are stored separately in the "files" attribute (whatever you pass in as the second argument, in this case, request.FILES). You don't want to be accessing the form's "data" or "files" attributes directly, as, if you do, you're just reading data straight from the request and not getting any benefit from using forms.
Are you sure the <form enctype="..."> attribute is set to multipart/form-data ? Otherwise the browser is not able to upload the file data.