I'm trying to add 'Share on Twitter' functionality on one of the pages of my Django-powered site. Here's the relevant portion of link_page.html:
<a class="tweet_link metaSpacing" data-link_id={{ link.id }}>Share on Twitter</a>
Here's the JavaScript portion responsible for listening for events:
// tweet_link
$('.tweet_link').click(function(e){
link_id = $(this).attr('data-link_id');
var target = $(this);
tweetLink(target);
});
function tweetLink(t){
link_id = t.attr('data-link_id');
$.ajax({
type: "POST",
data: { "link_id": link_id, "csrfmiddlewaretoken": csrfmiddlewaretoken},
url: "/tweet_link",
});
};
In Django I added the following line at the end of the urls.py:
url(r'^tweet_link/?$', 'portnoy.views.tweet_link'),
And here's the Django view itself:
# tweet the link
def tweet_link(request):
c = RequestContext(request)
twitter = Twython(
twitter_token = TWITTER_KEY,
twitter_secret = TWITTER_SECRET,
oauth_token = request.session['request_token']['oauth_token'],
oauth_token_secret = request.session['request_token']['oauth_token_secret']
)
twitter.updateStatus(status="See how easy this was?")
return HttpResponse('')
However, what happens when I click on the 'Share on Twitter' link, I get this error on Chrome Console:
POST http://127.0.0.1:8000/tweet_link 404 (NOT FOUND)
Any idea how to fix this? Thanks in advance!
Your url shouldn't have a ? in it:
url(r'^tweet_link/$', 'portnoy.views.tweet_link'),
You know that you can simply launch a link with this URL to tweet something:
https://twitter.com/intent/tweet?source=webclient&text=d+twitter+msg+goes+here
Related
Solution:
My mistake was that the url attribute doesn't just add the string given to 127.0.0.1 but to the current url, and so the url for the Like view was supposed to be 127.0.0.1/article/article_id/like-article-commm
I wrote a django app that has articles and im trying to add a like functionality, I added the code in the bottom and nothing happens. No error just nothing in the database or the html code changes. Any idea what is the problem?
The relevent part of the html/javascript code:
<head>
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
</head>
<button id='like-button' color = 'black'> Like </button>
<script type="text/javascript">
$('#like-button').click(function(){
var article_id = '{{ article.id }}';
var user_id = '{{ user.id }}';
var like_dislike = True;
$.ajax(
{
type:"GET",
url: "like-article-commm",
data:{
article_id: article_id,
user_id: user_id,
like_dislike: like_dislike
},
success: function( data )
{
$('#like-button').css('color', 'blue'); } }) });
</script>
The like-article-comm View:
def Like_Article_View(request):
if request.method == 'GET':
article_id = int(request.GET['article_id'])
likedarticle = Article.objects.get(id = article_id)
user_liked_id = int(request.GET['user_id'])
userliked = User.objects.get(id = user_liked_id)
like_dislike_0 = request.GET['like_dislike']
like_object_list = Like_Article.objects.filter(article_liked = likedarticle, user_liked = userliked)
if like_object_list.count() > 0:
existing_like = like_object_list.filter()
if existing_like.like_dislike == like_dislike_0:
return HttpResponse('success')
existing_like.like_dislike = like_dislike_0
existing_like.save()
like_new_object= Like_Article(article_liked=likedarticle, user_liked=userliked, like_dislike=like_dislike_0)
like_new_object.save()
return HttpResponse('success')
else:
return HttpResponse("unsuccesful")
urls.py file:
from django.urls import path
from . import views
from .views import ArticleListView, ArticleDetailView, ArticleCreateView, ArticleUpdateView, ArticleDeleteView
urlpatterns = [
path('', ArticleListView.as_view(), name="home-comm"),
path('article/<int:pk>/', ArticleDetailView.as_view(), name="article-comm"),
path('like_article/', views.Like_Article_View, name='like-article-commm'),
]
I can add like objects to the database manually.
--update--
After some discussion, we figure out that frontend ajax is not communicating with the backend properly. With chrome devtools we managed to pin point where the issue lies.
have you enabled CORS cross site resource sharing?
I'm attempting to use scrapy and splash to retrieve the Staff, job titles, and emails from a particular website's staff page. https://www.kennedaleisd.net/Page/3884. I'm using splash with docker since the emails are hidden behind dynamic javascript code.
The spider works on the first page of the staff however I can't seem to get it to work on the 2nd or 3rd pages. I opened up developer tools and have copied the request that is sent when you click on one of the pagination links and then attempted to replicate that request in the spider. The problem I appear to be having is that the response for that request only returns a sub-set of the code for the entire page (Just the staff for that page) instead of everything like the accompanying javascript. So when that is passed onto splash it doesn't have the necessary script to create the dynamic code. I also noticed that the request appeared to have a cookie entry of RedirectTo which goes back to the parent page. I had attempted including that cookie in the requests or passing cookies from the first request to the paginated pages, but it didn't seem to be working. I also attempted some lua scripts in the splash request but that didn't seem to be getting me what I wanted either. Below I've included the spider as I have it right now.
I'm not sure if there's some way to re-use the javascript with subsequent requests or to user that redict cookie in some way to get the rest of the needed code. Any help would be appreciated. I realize the pagination is probably not the proper way to loop through pages but I figured I could work on that once I get the reading of the data figured out.
import scrapy
from scrapy_splash import SplashRequest
class TestSpider(scrapy.Spider):
name = 'TestSpider'
start_urls = ['https://www.kennedaleisd.net/Page/3884']
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(url, self.parse, meta={
'splash': {
'endpoint': 'render.html',
'args': {'wait': 0.5}
}
})
def parse(self, response):
for item in response.css('div.staff'):
name = item.css('li.staffname::text').get()
title = item.css('li.staffjob::attr(data-value)').get()
email = item.css('li.staffemail a::attr(href)').get()
staffURL = response.request.url
yield {
'name': name,
'title': title,
'email': email,
'staffURL': staffURL
}
if response.css('a.ui-page-number-current-span::text').get() == '1':
pagination_results = response.css(
'li.ui-page-number a:not([class^="ui-page-number-current-span"])::text').getall()
base_url = 'https://www.kennedaleisd.net//cms/UserControls/ModuleView/ModuleViewRendererWrapper.aspx?DomainID=2042&PageID=3884&ModuleInstanceID=6755&PageModuleInstanceID=7911&Tag=&PageNumber='
# backend_url = '&RenderLoc=0&FromRenderLoc=0&IsMoreExpandedView=false&EnableQuirksMode=0&Filter=&ScreenWidth=922&ViewID=00000000-0000-0000-0000-000000000000&_=1584114139549'
for i in pagination_results:
next_page = base_url + str(i) # + backend_url
yield response.follow(next_page, callback=self.parse, meta={
'splash': {
'endpoint': 'render.html',
'args': {'wait': 3}
}
})
Well, after a bit of tinkering I figured out how to handle this with the lua script I had been toying with. I'd still much prefer a different method if there is something that is a bit more official rather than using scripting.
import scrapy
from scrapy_splash import SplashRequest
script_frontend = """
function main(splash)
splash:init_cookies(splash.args.cookies)
assert(splash:go{
splash.args.url,
headers=splash.args.headers,
http_method=splash.args.http_method,
body=splash.args.body,
})
assert(splash:wait(3))
assert(splash:select('#ui-paging-container > ul > li:nth-child("""
script_backend = """) > a'):mouse_click())
assert(splash:wait(3))
local entries = splash:history()
local last_response = entries[#entries].response
return {
url = splash:url(),
headers = last_response.headers,
http_status = last_response.status,
cookies = splash:get_cookies(),
html = splash:html(),
}
end
"""
class TestSpider(scrapy.Spider):
name = 'TestSpider'
start_urls = ['https://www.kennedaleisd.net/Page/3884']
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(url, self.parse, meta={
'splash': {
'endpoint': 'render.html',
'args': {'wait': 0.5}
}
})
def parse(self, response):
for item in response.css('div.staff'):
name = item.css('li.staffname::text').get()
title = item.css('li.staffjob::attr(data-value)').get()
email = item.css('li.staffemail a::attr(href)').get()
staffURL = response.request.url
yield {
'name': name,
'title': title,
'email': email,
'staffURL': staffURL
}
if response.css('a.ui-page-number-current-span::text').get() == '1':
pagination_results = response.css(
'li.ui-page-number a:not([class^="ui-page-number-current-span"])::text').getall()
for i in pagination_results:
script = script_frontend + str(i) + script_backend
yield SplashRequest(self.start_urls[0], self.parse,
endpoint='execute',
cache_args=['lua_source'],
args={'lua_source': script},
headers={'X-My-Header': 'value'},
session_id='foo'
)
I am currently dynamically loading various JSPs using an Ajax call. However, once a JSP is loaded none of the Javascript contained inside is working. I am assuming this is because the Script inside has not been parsed yet.
To that end I found the module "aui-parse-content" which, according to its description, should be able to parse the contained script.
The ParseContent Utility - Parse the content of a Node so that all of the javascript contained in that Node will be executed according to the order that it appears.
However, I can't get it to work. Here is my AUI:Script for reference.
<portlet:resourceURL var="viewContentURL">
<portlet:param name="jsp" value="<%= tmp %>"/>
</portlet:resourceURL>
<div id="<portlet:namespace />jspcontent"></div>
<aui:script use="aui-base, aui-io-request,aui-parse-content, aui-node">
var url = '<%= viewContentURL.toString() %>';
AUI().io.request(
url,
{
on:{
success: function(){
var message = this.get('responseData');
//alert(message);
AUI().one('#<portlet:namespace />jspcontent').html(message);
AUI().one('#<portlet:namespace />jspcontent').plug(AUI().Plugin.ParseContent);
},
failure: function(){
alert("An error occured");
}
}
}
);
</aui:script>
Thank you in advance!
-John
Edit:
Since I found a fix a while ago and others might have the same problem this is how I got aui-parse-content working:
on:{
success: function(){
var message = this.get('responseData');
var tmp = A.one('#<portlet:namespace />jspcontent');
tmp.html(message);
tmp.plug(A.Plugin.ParseContent);
tmp.ParseContent.parseContent(message);
},
}
I found a fix a while ago and others might have the same problem this is how I got aui-parse-content working:
on:{
success: function(){
var message = this.get('responseData');
var tmp = A.one('#<portlet:namespace />jspcontent');
tmp.html(message);
tmp.plug(A.Plugin.ParseContent);
tmp.ParseContent.parseContent(message);
},
}
I also amended my original post to reflect my findings
I am getting an error saying unexpected token while trying for passing id from django template to reatjs for uploading multiple images to its associated foreign key object. The error is shown as unexpected token }. In depth it is shown as
in console
var uploadUrl = {
url:
};
What i am trying to do is , I have created a listing page with multiple form and it is entirely developed using reactjs. I want user to fill the data about room and upload multiple images related to their room. There are two models one with room info and another gallery(multiple image is associated with one rent). I wanted the uploaded images be associated with its rent so i coded it as below
urls.py
urlpatterns = [
url(r'^add/$', AddView.as_view(), name="add"),
url(r'^add/space/$', AddSpaceView.as_view(), name="addSpace"),
url(r'^upload/image/(?P<pk>\d+)/$', ImageUpload, name="ImageUpload"),
]
views.py
def ImageUpload(request,pk=None): // for saving images only to its asscoiated rent
if request.POST or request.FILES:
rental = Rental.objects.get(id=pk)
for file in request.FILES.getlist('image'):
image = GalleryImage.objects.create(image=file,rental=rental)
image.save()
return render(request,'rentals/add.html')
class AddView(TemplateView): // for listing page
template_name = 'rentals/add.html'
class AddSpaceView(View): // for saving data to database except image
def post(self,request,*args,**kwargs):
if request.POST:
rental = Rental()
rental.ownerName = request.POST.get('ownerName')
rental.email = request.POST.get('email')
rental.phoneNumber = request.POST.get('phoneNumber')
rental.room = request.POST.get('room')
rental.price = request.POST.get('price')
rental.city = request.POST.get('city')
rental.place = request.POST.get('place')
rental.water = request.POST.get('water')
rental.amenities = request.POST.get('amenities')
rental.save()
return HttpResponseRedirect('/')
listing.js(ajax code for uploading multiple image)
var image = [];
image = new FormData(files);
$.each(files,function(i,file){
image.append('image',file);
});
$.ajax({
url:"/upload/image/", // want to used id over here that is passed from add.html script tag so that image will be uploaded to its associated foriegn key object
data:image,
contentType:false,
processData:false,
type:'POST',
mimeType: "multipart/form-data",
success: function(data) {
console.log('success');
}
});
}
add.html page
<div id="listing">
</div>
{% include 'includes/script.html'%}
<script type="text/javascript">
var uploadUrl = {
url: {% for rental in object_list %} { "id": {{ rental.id }} } {% endfor %} // here is an error
};
console.log('url is', url);
$(function() {
app.showListingSpaceForm("listing");
});
</script>
The code might explained what i was trying to achieve. If models.py is also required for more scrutiny then i will update it.
You're missing a fundamental piece: TemplateView has no concept of object_list, you have to populate it yourself. If your view is simple enough use ListView and set your model property. If not, you have to manually populate the object list, something like this:
def get_context_data(self, **kwargs):
context['object_list'] = MyModel.objects.all()
That was just an example to set you on the right path.
I am trying to use the Facebook Share in AngularJS. Below is my function that is called when the user clicks on the FB icon.
$scope.shareFB = function(){
// Get configuration ID from service
configuratorService.storeConfiguration($scope.modelCode, function(configID){
// Use saved configuration id to create share link
var base = $location.absUrl().replace($location.url(), '');
var byoUrl = base + "/" + $scope.modelCode + "/resume/" + configID;
console.log(byoUrl);
var fbpopup = window.open("https://www.facebook.com/sharer/sharer.php?u=" + byoUrl, "pop", "width=600, height=400, scrollbars=no");
});
}
This function works fine when I try to share a url like "https://www.google.com/"
the Facebook Popup then has the URL = "https://www.facebook.com/sharer/sharer.php?u=https://www.google.com/"
When I use the function above:
byoUrl = "http://localhost:8000/#/15K6/resume/9295316837"
and the resulting FB popup has URL = "https://www.facebook.com/15K6/resume/9295316837"
Why does the "/sharer/sharer.php?=http://localhost:8000/#/" get cut off?
You shouldn't even try to share a localhost URL, as Facebook will never be able to scrape it. That's very likely why your URL gets cut off. Facebook tries to resolve it and scrape it, but it will never find it, so it makes a best effort to redirect within itself. Example:
https://www.facebook.com/sharer/sharer.php?u=http://localhost:8000/#/coke
Try to put your share logic in the controller. Something along these lines.
// Share posts
$scope.fbShare = function(post){
FB.ui(
{
method: 'feed',
name: post.title,
link: 'http://www.cengkuru.com/'+post.slug,
picture: '',
caption: '',
description: $filter('limitTo')($scope.post.body, 150),
message: ''
});
}
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({appId: 'YOUR_APP_ID', status: true, cookie: true,
xfbml: true});
};
(function() {
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
}());
</script>