I'm developing a web application where I'm stuck with a problem in one feature. You can check it out here http://qlimp.com You can also use this for username/password: dummy/dummy
After login, please click the link Go to cover settings You will see a palette where you can upload images, enter some text.
When you upload the image, I've written an ajax request in jQuery which uploads the image to the server and shows fullpage background preview of that image.
JQuery
$('#id_tmpbg').live('change', function()
{
$("#ajax-loader").show();
$("#uploadform").ajaxForm({success: showResponse}).submit();
});
function showResponse(responseText, statusText, xhr, $form) {
$.backstretch(responseText)
$("#ajax-loader").hide();
}
So the problem here is, when I upload the image, it shows
ValueError at /cover/
The view cover.views.backgroundview didn't return an HttpResponse object.
Request Method: POST Request URL: http://qlimp.com/cover/
I'm actually returning HttpResponse object in views.
Views.py:
#login_required
def backgroundview(request):
if request.is_ajax():
form = BackgroundModelForm(request.POST, request.FILES)
if form.is_valid():
try:
g = BackgroundModel.objects.get(user=request.user)
except BackgroundModel.DoesNotExist:
data = form.save(commit=False)
data.user = request.user
data.save()
else:
if g.tmpbg != '' and g.tmpbg != g.background:
image_path = os.path.join(settings.MEDIA_ROOT, str(g.tmpbg))
try:
os.unlink(image_path)
except:
pass
data = BackgroundModelForm(request.POST, request.FILES, instance=g).save()
return HttpResponse(data.tmpbg.url)
else:
form = BackgroundModelForm()
return render_to_response("cover.html", {'form': form}, context_instance=RequestContext(request))
Models.py:
class BackgroundModel(models.Model):
user = models.OneToOneField(User)
background = models.ImageField(upload_to='backgrounds', null=True, blank=True)
tmpbg = models.ImageField(upload_to='backgrounds', null=True, blank=True)
class BackgroundModelForm(ModelForm):
class Meta:
model = BackgroundModel
exclude = ('user','background')
But these things are working on my computer(save the image and shows the background preview) but not in the production server. Why is it so?
I've uploaded the same code to the server.
Could anyone help me? Thanks!
You are not returning a response if the form is valid.
Related
I am having a problem after I restarted my project from scratch
I can add a value manually to my django model, but when it comes from a variable the user entered, it only pass a blank string..
Some pictures of the logs to be more explicit:
Process:
So, I am having a simple model Tech and I have a page where you can add a new name to Tech model.
I enter the name (here i entered the name ede dede), click add, then i send it to the backend using AJAX.
In the shell in VSCODE I see I received the element, but when I add it to my django model Tech, and then print the new object in Tech, it has an ID, everything, but the name is a blank string ""
Moreover, When i print it in my python code, it doesnt even give me the queryset, i have nothing.
How come?
Here is a piece of my code
VIEWS.PY:
#ajax_required
#require_http_methods(["POST"])
def AddNewEmployee(request):
newtechname = request.POST.get('new_employee').title()
response_data = {}
print('new employee: '+newtechname)
print(type(newtechname))
if Tech.objects.filter(name=newtechname).exists():
response_data['success'] = False
response_data['result'] = 'This name already exists'
return HttpResponse(
json.dumps(response_data),
content_type="application/json"
)
else:
techname = Tech(name=newtechname)
techname = Tech(selected=True) #add new tech to model
techname.save() #save new name to model
response_data['success'] = True
response_data['result'] = 'Added a new teammate successfully!'
response_data['tech_id'] = techname.id #get new name id from model
response_data['tech_name'] = techname.name
response_data['tech_selected'] = techname.selected
print(techname)
return HttpResponse(
json.dumps(response_data),
content_type="application/json"
)
MODELS.PY
class Tech(models.Model):
name = models.CharField(max_length=200)
selected = models.BooleanField(default=False)
def __str__(self):
return self.name
JS:
$('#add-employee').on('submit',function(e){
e.preventDefault();
if(e.target.getAttribute('id')==('add-employee')){
console.log('form submitted!'); //sanity check
AddNewEmployee();
}
});
function AddNewEmployee(){
console.log('AddNewEmployee is working!');
console.log($('#addtech_id').val()); //get the input value from input id
const addemployee_form_url = $('#add-employee').attr('action'); //get the form url
new_employee = $('#addtech_id').val(); // data sent with the post request
console.log(typeof new_employee);
let request_data = {
'new_employee': new_employee,
'csrf_token':csrftoken
}
$self = $(this)
$.ajax({
url : addemployee_form_url, //endpoint
type : "POST", //httpmethod
data : request_data,
//handle a successful response
success : function(response){
$('#addtech_id').val(''); //remove the value from the input
console.log(response); // log the returned json to the console
console.log("A connexion to the backend has been established with success!"); // sanity check
//Add to selected list
if (response['success']){
AddToSelectedList(response['tech_id'], response['tech_name']);
$('#results').html("<h5><div class='alert-box alert radius' data-alert style='color:green;'>"+response['result']+"</div><h5>");
}
else{
$('#results').html("<h5><div class='alert-box alert radius' data-alert style='color:red;'>This name is already in the list!</div><h5>");
}
},
// handle a non-successful response
error : function(xhr,errmsg,err) {
$('#results').html("<div class='alert-box alert radius' data-alert>Oops! We have encountered an error: "+errmsg+
" <a href='#' class='close'>×</a></div>"); // add the error to the dom
console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
}
});
}
What I dont understand is, why is it printing (in views.py) newtechname correctly, which i can even see its type is a string so no problem, then, it passes an empty string to Tech model when techname = Tech(name=newtechname)
Thanks for your help!
The problem is here
else:
techname = Tech(name=newtechname)
techname = Tech(selected=True) #add new tech to model
techname.save() #save new name to model
You are trying to create an object that does not exist as Tech(name=newtechname) doesn't create the object, you can use that after using Tech.objects.create()
So in your case changing that with the traditional objects.create() has resolved the issue.
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 have a django project where a user has a profile and can upload a profile picture. The models.py is:
`class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=64,blank=True)
profilePic = models.ImageField(blank=True, null=True, upload_to= "profile/")
phoneNumber = models.CharField(max_length=12,blank=True)
streetAddress = models.CharField(max_length=64,blank=True)`
On my site, the user can edit his profile including the profile picture. To do so, I have a form, where the initial values are the ones initially stored. The forms.py is:
class EditProfile(forms.ModelForm):
def __init__(self, profile, *args, **kwargs):
self.profile = profile
super(EditProfile, self).__init__(*args, **kwargs)
self.fields['name'] = forms.CharField(label='Name:', initial= profile.name,required=False)
self.fields['phoneNumber'] = forms.CharField(label= "Phone Number:", initial= profile.phoneNumber,required=False)
self.fields['streetAddress'] = forms.CharField(label='Street Address and/or Postal Code:', initial= profile.streetAddress,required=False)
self.fields['profilePic'] = forms.ImageField(label='Profile Picture:', initial= profile.profilePic,required=False)
class Meta:
model = Profile
fields = ("name", "phoneNumber","streetAddress", "profilePic")
This part works great, and on my site I can see the stored values. The problem is when I try to edit them and submit the form.
My views.py is:
def settings(request):
user= request.user
if request.method == 'GET':
userProfile = Profile.objects.get(user=user)
f1= UserProfile(user=request.user)
f2= EditProfile(profile=userProfile)
return render(request, 'listings/settings.html', {'form': f1,'form2': f2})
elif request.method == 'POST':
userProfile = Profile.objects.get(user=user)
f1= UserProfile(user=request.user)
f2= EditProfile(profile=userProfile)
name= request.POST["name"]
phoneNumber = request.POST["phoneNumber"]
streetAddress = request.POST["streetAddress"]
Profile.objects.filter(user=user).update(name= name, phoneNumber = phoneNumber, streetAddress = streetAddress)
if "profilePic" in request.FILES:
image1=request.FILES["profilePic"]
fs1=FileSystemStorage()
fs1.save(image1.name, image1)
userProfile.profilePic = image1
userProfile.save()
else:
userProfile.profilePic.delete()
messages.success(request, 'Your profile has been updated!')
return redirect("/settings")
Everything gets edited with no issues except for the imageFile. If I upload the file, it works and the image is updated. However, if I make no changes to the imageFile (i.e. I want to keep the same image), the request.FILES is empty, and then the code goes to the else statement and deletes the existing profilePic.
My question is that the I can see the initial profile picture on my site, so the forms.py is working, but why isn't it being submitted along with the rest of the form?
Your question is a bit confusing, but it seems that you are trying to reinvent the wheel. If you want to have the "initial" data reinserted into the form, you should use the native instance parameter. You can use it as such:
profile = Profile.objects.get(user=user)
# This can be in your GET
profile_form = EditProfile(instance=profile)
# This can be in your POST
profile_form = EditProfile(request.POST, request.FILES, instance=profile)
profile_form.save()
I'm currently sending posts with ajax to a django form, but I need to do this without JQuery.
Here's the working JQuery version.
$.ajax({
url : "/platform/post-tracking/",
type : "POST",
async: true,
data : {
account : 229829623,
width : pageWidth
}
});
How would I send this post request without JQuery?
I've tried this
data = {
account : 229829623,
width : pageWidth
}
var request = new XMLHttpRequest();
request.open('POST', '/platform/post-tracking/', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send(data);
But the form isn't valid.
Django Form:
class TrackingForm(forms.ModelForm):
class Meta:
model = TrackedSession
fields = ('account', 'width')
Django Model:
class TrackedSession(models.Model):
account = models.IntegerField(default=0)
width = models.IntegerField(default=0)
Django View:
def TrackDataView(request):
if request.method == 'POST':
form = TrackingForm(request.POST)
if form.is_valid():
print "Form is valid."
temp = form.save(commit=False)
session = TrackedSession()
session.account = temp.account
session.trackedIp = trackingip
session.width = temp.width
session.save()
print("Session Created")
else:
print "Form isn't valid."
print form.errors
response_data = "Success"
return HttpResponse(
json.dumps(response_data),
content_type="application/json"
)
The data argument to request.send() needs to be a URL-encoded string. jQuery converts an object to a string, but if you don't use jQuery you have to do it yourself.
data = 'account=229829623&width=' + encodeURIComponent(pageWidth);
request.send(data);
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.