how to update model field data when Javascript event occurs - javascript

I'm doing on a Django Project.
There is a post model, and the post has 'likes' field. When a user clicks the Like button on a post, I want to increase the number of the Likes of the post.
I want to solve the problem only with Django without REST framework(DRF)
what can I do?

You have to make an endpoint that javascript can be directed to. Create a view that will do the process:
def add_like(request, post_id):
# here you can create process that will find Post object by provided id
return JSONResponse(...) # however not needed, you can create some response with status 201
Then obviously url pointing to that view:
urlpatterns = [
path('add_like/<int:post_id>', my_app.add_like),
]
Then anytime you will post to i.e. /add_like/1, it will activate the process in add_like view. You can put there more variables (like user who is liking).

Related

Sending query params forth to another page with POST in Node JS and Express

This is the issue I'm facing:
I have multiple consecutive web pages where I hold the same id in the query params and send it forth from one to the next due to various reasons. All is fine when passing this param with GET routes. However, the third page (which has the query param as well) has a short form and POST method, which redirects to the fourth page at the end. Something like this:
app.post("/third", function(req, res){
req.body.id //returns undefined, but should not
some code here
res.redirect("/fourth?id="+id); //how i want to pass the param on
});
Whichever I use, req.body or req.query or req.params, I can never access the id 'abcd' from
web-app/third?id=abcd
and add it to the fourth page query params, I always get undefined.
Am I doing this wrong? Still quite new to Node JS and Express and everything to do with web-apps, so my logic might be off. I've searched Google, but due to my inexperience most of the posts were unhelpful for me. How to send the params when I have a POST method and cannot access the param from anywhere except the page holding the form query itself?
Any help is appreciated!
Edit:
How the front-end looks like:
<form action="/third" method="post">
...
a few inputs here
....
<input type="submit" rel="next" value="To signing" class="button"
id="nextbutton">
<a onclick="setUrl();" rel="prev" class="button" id="cancelbutton">Previous page</a>
</form>
/third is the current page, /fourth the next
I see what you mean now. Your url which you are POST'ing the form from contains a query parameter in the URL. That's the parameter which you can't access to. Well - that parameter is not in the POST parameters, it's not in the form. So you have 2 options.
When you're outputting the /third view with your GET request you should add that query parameter as a hidden input value into the form, so you can post it as a parameter to the back-end.
If you're using Node.js you just need to modify your /third view (might be a Jade / Pug template)
to have
// Make sure this line is in the form that you're posting (syntax is jade - any other way of replacing the idFromServer value with a server value would work just as well.
input(name="id", type="hidden", value="#{idFromServer}")
and update your view render code to be like:
// It's read from query because we know this one is a get request.
res.render('third', {idFromServer: req.query.id});
After this req.body.id should work!
What we did here is whenever you're getting the third view with an id parameter, we'll put a hidden POST request field in the form.
When you POST you can access your id variable because your form has an id field with a value. This is a common solution, but one thing to watch out is validating your query parameter because now you allowed people to randomly pass values onto your page - which will be posted back, you can never be sure that people won't pass some malicious values over there.
Another way of doing this - which I'm not recommending but it's a way - is to look into the headers. Because your current solution doesn't have the hidden form field - you can look into the referrer header and your missing query parameter would be there.
You can just do a
console.log(req.headers.referer);
in your /third view and it should have the full previous URL which also contains the parameter you're looking for.

Redux - Remove object from store on http response error

Consider the following flow:
I have a page with a list of "products" and a modal to create a single "product". I open the modal, fill the form and submit the form.
At this point, I dispatch an action CREATING_PRODUCT, add the product to the store and send the http request to the server.
I close the modal and display the list of results with the new product.
Let's suppose I receive an error response from the server.
Desired behavior:
I would like to display an error, remove the project from the list, re-open the modal and display the form already filled.
Question
How can I find that project and remove it the list? I don't have an id (or a combination of unique properties) to find that project in the store. I don't see a clean way to link a request/response to that "product" object in the store.
Possible solution
The client adds a "requestId" into the project before adding it to the store. On response error, I dispatch a generic "CREATE_ERROR" and I remove the project with that requestId from the store.
Extra
Same problem with edit and delete. For example during a delete should I keep a reference to the deleted project with the requestId in the store, until the http request is successful?
I bet it is a problem with a common solution, but I can't find examples.
Thanks!
In general, your Redux store should be modeled somewhat like a relational database, in that every time you have a list of data models, each element of the list should have its own identifier. This helps a lot when dealing with more complex data schemes.
You should probably store your projects as an object, something like:
{
// ...other store properties
projects: {
"_0": { // ... project properties }
"_1": { // ... project properties }
// ...more projects...
},
}
This way, whenever you need to mess with an existing project, you can just reference its id and use projects[id] to access that project. This would also solve the edit and delete cases, as you could just pass the IDs around as handles.
I like this short piece on why your Redux store should be mostly flat and why data should always have identifiers very much. It also talks about using selectors to "hide" your IDs away, which may or may not be useful for you.
In your case, as you are getting IDs from a server, you could have an ID prefix which indicates unsaved values. So your projects object would become something like:
projects: {
"_0": { // ... }
"_1": { // ... }
"UNSAVED_2": { // ... }
}
This way, you could easily identify unsaved values and handle them when an error occurs, still get the benefits of generating temp IDs on the client-side in order to revert changes on error, and also warn your user if they try to leave your app while their data still hasn't been synchronized - just check if there are any "UNSAVED" IDs :)
When you get a response from the server, you could change the "UNSAVED_suffix" ID to an actual ID.

How to pass data between Django module/app functions without using database in asynchronous web service

I've got a web service under development that uses Django and Django Channels to send data across websockets to a remote application. The arrangement is asynchronous and I pass information between the 2 by sending JSON formatted commands across websockets and then receive replies back on the same websocket.
The problem I'm having is figuring out how to get the replies back to a Javascript call from a Django template that invokes a Python function to initiate the JSON websocket question. Since the command question & data reply happen in different Django areas and the originating Javascript/Python functions call does not have a blocking statement, the Q&A are basically disconnected and I can't figure out how to get the results back to the browser.
Right now, my idea is to use Django global variables or store the results in the Django models. I can get either to work, but I beleive the Django global variables would not scale beyond multiple workers from runserver or if the system was eventually spread across multiple servers.
But since the reply data is for different purposes (for example, list of users waiting in a remote lobby, current debugging levels in remote system, etc), the database option seems unworkable because the reply data is varying structure. That, plus the replies are temporal and don't need to be permanently stored in the database.
Here's some code showing the flow. I'm open to different implementation recommendations or a direct answer to the question of how to share information between the 2 Django functions.
In the template, for testing, I just have a button defined like this:
<button id="request_lobby">Request Lobby</button>
With a Javascript function. This function is incomplete as I've yet to do anything about the response (because I can't figure out how to connect it):
$("#request_lobby").click(function(){
$.ajax({
type: "POST",
url: "{% url 'test_panel_function' %}",
data: { csrfmiddlewaretoken: '{{ csrf_token }}', button:"request_lobby" },
success: function(response){
}
});
});
This is the Django/Python function in views.py . The return channel for the remote application is pre-stored in the database as srv.server_channel when the websocket is initially connected (not shown):
#login_required
def test_panel_function(request):
button = request.POST.get('button', '')
if button == "request_lobby" :
srv = Server.objects.get(server_key="1234567890")
json_res = []
json_res.append({"COMMAND": "REQUESTLOBBY"})
message = ({
"text": json.dumps(json_res)
})
Channel(srv.server_channel).send(message)
return HttpResponse(button)
Later, the remote application sends the reply back on the websocket and it's received by a Django Channels demultiplexer in routing.py :
class RemoteDemultiplexer(WebsocketDemultiplexer):
mapping = {
"gLOBBY" : "gLOBBY.receive",
}
http_user = True
slight_ordering = True
channel_routing = [
route_class(RemoteDemultiplexer, path=r"^/server/(?P<server_key>[a-zA-Z0-9]+)$"),
route("gLOBBY.receive" , command_LOBBY),
]
And the consumer.py :
#channel_session
def command_LOBBY(message):
skey = message.channel_session["server_key"]
for x in range(int(message.content['LOBBY'])):
logger.info("USERNAME: " + message.content[str(x)]["USERNAME"])
logger.info("LOBBY_ID: " + message.content[str(x)]["LOBBY_ID"])
logger.info("OWNER_ID: " + message.content[str(x)]["IPADDRESS"])
logger.info("DATETIME: " + message.content[str(x)]["DATETIME"])
So I need to figure out how to get the reply data in command_LOBBY to the Javascript/Python function call in test_panel_function
Current ideas, both of which seem bad and why I think I need to ask this question for SO:
1) Use Django global variables:
Define in globals.py:
global_async_result = {}
And include in all relevant Django modules:
from test.globals import global_async_result
In order to make this work, when I originate the initial command in test_panel_function to send to the remote application (the REQUESTLOBBY), I'll include a randomized key in the JSON message which would be round-tripped back to command_LOBBY and then global_async_result dictionary would be indexed with the randomized key.
In test_panel_function , I would wait in a loop checking a flag for the results to be ready in global_async_result and then retrieve them from the randomized key and delete the entry in global_async_result.
Then the reply can be given back to the Javascript in the Django template.
That all makes sense to me, but uses global variables (bad), and seems that it wouldn't scale as the web service is spread across servers.
2) Store replies in Django mySQL model.py table
I could create a table in models.py to hold the replies temporarily. Since Django doesn't allow for dynamic or temporary table creations on the fly, this would have to be a pre-defined table.
Also, because the websocket replies would be different formats for different questions, I could not know in advance all the fields ever needed and even if so, most fields would not be used for differing replies.
My workable idea here is to create the reply tables using a field for the randomized key (which is still routed back round-trip through the websocket) and another large field to just store the JSON reply entirely.
Then in test_panel_function which is blocking in a loop waiting for the results, pull the JSON from the table, delete the row, and decode. Then the reply can be given back to the Javascript in the Django template.
3) Use Django signals
Django has a signals capability, but the response function doesn't seem to be able to be embedded (like inside test_panel_function) and there seems to be no wait() function available for an arbitrary function to just wait for the signal. If this were available, it would be very helpful

How can I test in Django a view which has a form?

I am creating an application in Django and I have a view which receives a form from the html code, and searches in the database if there are any instances of a model whit the values specified in the form.
The problem is that I am new in Django and I don't really know how can I test the functionality of the view (i.e.: if the view's response has a list of values resulting the search of the values of the form in the request).
Here I put the example code of my view:
#login_required
def view(request):
# If it's a HTTP POST, we're interested in processing form data.
if request.method == 'POST':
form = Form(data=request.POST)
# If the form is valid
if (form.is_valid()):
resulting_of_search = ModelA.objects.filter(Q(att1=request.POST[attr1]) & ...)
else:
resulting_of_search = []
# Not a HTTP POST, so we render our form using two ModelForm instances.
# These forms will be blank, ready for user input.
else:
form = Form()
resulting_of_search= []
# Render the template depending on the context.
return render(request,
'url/url.html',
{'resulting':resulting_of_search} )
Have you tried the Django Testing Tutorial? Essentially, you just need to send a post to your view and test that the response returns what you'd expect.
For example..
def test_index_view_with_no_questions(self):
"""
If no questions exist, an appropriate message should be displayed.
"""
response = self.client.get(reverse('polls:index'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "No polls are available.")
self.assertQuerysetEqual(response.context['latest_question_list'], [])
Taken from the docs. You'd want to change that last line so that you assert that 'resulting' is in the context. Or check that it contains a specific list of results you're looking for. Like this..
def test_results(self):
response = self.client.get(reverse('ensaioak_bilatu'))
self.assertQuerySetEqual(response.context['resulting'], [...whatever you expect resulting to contain...])
From reading your answer, I think you are not asking about unit testing but just checking whether your view actually works. As a start, you can use the code snippet provided on the Django website at the following link: https://docs.djangoproject.com/en/1.8/topics/forms/#the-view.

How to save form record in client side while saving data with ajax POST?

I have created one form.
On click Submit button record is saving in database with ajax POST.
Then again for viewing those records on web page I am clearing existing html and adding new records.
In form I am having select list and text-boxes and textarea.
For example:
Following is my Form:
On Click Save FAQ button data from following form data is saving in database.
Quetion No. field is having unique no. for this I am generating number in backend.
Means when I do ajax POST Question No is blank but it is been assigned unique no. before putting in database.
Requirements:
Select list is present in that by default option value is Default Mode(New).
Question field value need to get append in select list after clicking Save FAQ.
For this I am getting all records with Ajax GET and clear previous html and add new data but this is not feasible.
I need to optimize this.
For this I need to save this record in array, ex :
saveFaqRecordT = []
saveFaqRecordT.push({faq_no: getRec, faq_quest: rec.faq_quest, faq_answer: rec.faq_answer});
getRec is counter as we are no passing any value for Question No from client side.
Or Please guide me with how to save record in client side also while saving doing Ajax POST, so that there is no need to do Ajax Get on each save?
Ajax Post -> Return appropriate response, let's say a JSON
On Success
{"status":"success","message":"added successfully"}
On Error
{"status":"error","message":"failed because of validation"}
Simply parse this JSON in the POST callback, to figure out where the saving was successful or not.
If the saving was successful, simply add the data to your saveFaqRecordT array.
$.ajax({
method:POST,
url:"http://someurl.com",
data:$("#myform").serialize(),
success:function(data){
var json=eval(data);
if(json.status=='success'){
//append to array
}
}
});
Above is just a sample un-tested code, to give you an idea on how it can be done.

Categories

Resources