'QueryDict' object has no attribute 'caption' in django - django

I have written this simple image upload app, where users should be able to add caption to the uploaded image.
the views is:
#login_required
def upload(request):
thisuser =User.objects.get(username = request.user.username)
args= {}
if request.method == 'POST':
picform = PicForm(request.POST, request.FILES)
if picform.is_valid():
newpic = UserPic(picfile = request.FILES['picfile'])
newpic = picform.save(commit=False)
newpic.user_id = request.user.id
newpic.caption = request.POST.caption # <--problematic line
newpic.save()
message = "file %s is uploaded" % newpic
args['pic'] = newpic.picfile
args['caption'] = newpic.caption
else:
picform = PicForm()
args.update(csrf(request))
args['picform'] = picform
return render_to_response('pics/upload.html',args,
context_instance=RequestContext(request))
The model is:
class UserPic(models.Model):
user = models.ForeignKey(User, unique=False)
picfile = ImageWithThumbsField(upload_to= get_uplaod_file_name,sizes=((200,200),))
caption = models.TextField(max_length=200 , blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
And the template:
<div>
Upload New picture
<form action="/pics/upload/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<ul class="list-unstyled form-group">
{{picform.as_ul}}
</ul>
</p>
<p><input type="submit" value="Upload" /></p>
</form>
</div>
When I upload photo, fill the caption field and submit the form,, I get:
'QueryDict' object has no attribute 'caption'
I tried different things instead of newpic.caption = request.POST.caption but none worked. So appreciate your help.

Try this
request.POST['caption']
or
request.POST.get('caption', 'Default').
Both get the caption value from the form post data. The latter is just a safer way in my opinion by specifying a default value for caption.

Related

'NoneType' object has no attribute 'username'? What should i do?

I am extending User model of Django by following model
models.py
class Profile(models.Model):
user = models.OneToOneField(User, null=False, on_delete = models.CASCADE)
First_name = models.CharField(max_length = 128, null = True)
Last_name = models.CharField(max_length = 128, null = True)
email = models.CharField(max_length = 200, null = True)
phone = models.CharField(max_length = 200, null = True)
mod_date = models.DateTimeField(auto_now_add = True, null = True)
profile_pic = models.ImageField(null = True, blank = True)
def __str__(self):
return self.user.username
views.py
def userprofile(request):
form = Profile()
if request.method == 'POST':
form = Profile(request.POST)
if form.is_valid():
form.save()
context = {'form':form}
return render(request, 'cs14/profile.html', context)
forms.py
class Profile(ModelForm):
class Meta:
model = Profile
fields = ["First_name","Last_name","email", "phone"]
When I try to go profile page, it happened error
AttributeError at /profile/
'NoneType' object has no attribute 'username'
What is going wrong? After I change the User null = false, it shows RelatedObjectDoesNotExist at the profile. Profile has no user.
{% extends 'base.html' %}
{% load static %}
{% block body_block %}
<style>
.profile-pic{
max-width: 100%;
max-height: 100%;
border-radius: 50%;
}
</style>
<br>
<div class="row">
<div class="col-md-2">
<div class ="card card-body">
<a class="btn btn-warning" href="{% url 'home:index'%}"> ← Back to homepage</a>
<hr>
<h3 style="text-align: center">User profile</h3>
<hr>
<div>
<img class="profile-pic" src="">
</div>
</div>
</div>
<div class="col-md-9">
<div class="card card-body">
<form action="" method="post">
<table>
{{form}}
</table>
</form>
</div>
</div>
</div>
{% endblock %}
can you show what you have wrote in profile.html, btw, it's better to use the emailField in :
class Profile(models.Model):
user = models.OneToOneField(User, null=False, on_delete = models.CASCADE)
First_name = models.CharField(max_length = 128, null = True)
Last_name = models.CharField(max_length = 128, null = True)
email = models.EmailField(null=True)
and since the user attribute can't be null you have to specify the user in the view userprofil function like:
if request.method == 'POST':
form = Profile(request.POST)
if form.is_valid():
form.instance.user = request.user
form.save()
but if you are trying to get the username in profile page, your passing the profile object in the context which doesn't have the username attribute.
The error is coming from the __str__ method:
def __str__(self):
return self.user.username
As the user is None for the saved object, it is throwing the error from this method. You can update in your view to save the profile instance with current user like this(also addional errors might occur due to Form and Model having same name):
# form
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = ["First_name","Last_name","email", "phone"]
# view
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES)
if form.is_valid():
profile = form.save(commit=False) # returning an model instance which has not been saved to DB yet
profile.user = request.user
profile.save()
Finally, update the html form as well:
<form action="" method="post" enctype="multipart/form-data">
<table>
{{ form }}
</table>
</form>

Why isn't this creating the models in batch?

I am trying to create the object blank in a batch but it is only creating one object after I fill in the form, could anyone help me with what I am doing wrong?
html
{% block content %}
<form class="box" method = "post">
{% csrf_token %}
<h1>Air Ticket Sales</h1>
{{ form }}
batch size:
<input type="number" name="batch" value="{{ batch }}">
<input type="submit" name="" value="Create Blank">
</form>
{% endblock %}
model
class blank(models.Model):
#an integer field that automatically increments by itself as the object are created
number = models.AutoField(primary_key=True)
type = models.CharField(max_length=50, choices=type_choices, default='green')
is_sold = models.BooleanField(default=False)
is_refunded = models.BooleanField(default=False)
date = models.DateField(auto_now_add=True)
date.editable = True
advisor = models.ForeignKey(
User,
models.SET_NULL,
blank=True,
null=True,
)
view
def create_blanks(request):
if request.method == 'POST':
#initializes the data from the form to the value form
form = blank_form(data=request.POST)
batch = request.POST.get("batch", "")
if form.is_valid():
for b in batch:
form.save()
return render(request, "create_blanks.html")
else:
return render(request, "create_blanks.html")
else:
form = blank_form
return render(request, "create_blanks.html", {'form':form})
Yep just found the solution with your help I don't think it is the most efficient or the cleanest one but here you go
for b in range(int(batch)):
form.save()
form.instance = None
form = blank_form(data=request.POST)

Saving image fails without error in django model form

I want to try to save an image to my model:
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.user.id, filename)
class Leverandor(models.Model):
ID = models.AutoField(primary_key=True)
UserID = models.ForeignKey('Stamdata', on_delete=models.CASCADE)
Name = models.CharField('Name', max_length=200)
URL = models.URLField('URL', max_length=200)
ImageURL = models.ImageField('ImageURL',blank=True, null=True, upload_to=user_directory_path)
To this Form.py:
class EditLeverandorForm(forms.ModelForm):
Name = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'autofocus': True}))
URL = forms.URLField(widget=forms.TextInput(attrs={'class': 'form-control', 'autofocus': True}))
ImageURL = forms.ImageField
class Meta:
model = Leverandor
labels = {
'Name' : 'Leverandør',
'URL' : 'Webside',
'ImageURL' : 'Logo',
}
fields = ['UserID', 'Name', 'URL', 'ImageURL']
And rendererd to this view.py
def add_leverandorer(request):
user_id = request.user.id
# if this is a POST request we need to process the form data
if request.method == 'POST':
print (user_id)
form = EditLeverandorForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
form.save()
return HttpResponseRedirect('/backend/leverandorer')
else:
print ('somethin goes wrong')
print (user_id)
form = EditLeverandorForm()
return render(
request,
'backend/add_leverandorer.html',
{
'title':'WestcoastShop - Backend',
'form': form,
}
)
The problem is that before I add the instance=request.user part its saves the entry correct but without image. Now I add the part from Django documentation like provided for save to an variable path but nothing happened after i click to save button.
<form action="/backend/leverandorer/add" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label for="simpleinput">Leverandør</label>
{{ form.Name }}
</div>
<div class="form-group">
<label for="simpleinput">Webside</label>
{{ form.URL }}
</div>
<div class="form-group">
<label for="simpleinput">Logo</label>
{{ form.ImageURL }}
<!--<input type="file" name="ImageURL" accept="image/*" required="" id="id_ImageURL" class="form-control-file">-->
</div>
<input type="hidden" id="UserID" name="UserID" value="{{ user.id }}">
<button type="submit" class="btn btn-primary">Gem</button>
</form>
I didnt see an error but now its not saving the form in models also if ImageField is empty.
regards
Christopher.
You are using UserID as a hidden field. The hidden field will not pass the form-validation. So your following code will be false.
if form.is_valid():
form.save()
return HttpResponseRedirect('/backend/leverandorer')
One of the solutions is, remove the UserID field from your template and update your view as follows.
if form.is_valid():
user_form = form.save(commit=False)
user_form.UserID = request.user
user_form.save()
I I change the function in models.py to:
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.UserID, filename)
class Leverandor(models.Model):
ID = models.AutoField(primary_key=True)
UserID = models.ForeignKey('Stamdata', on_delete=models.CASCADE)
Name = models.CharField('Name', max_length=200)
URL = models.URLField('URL', max_length=200)
ImageURL = models.ImageField('ImageURL',blank=True, null=True, upload_to=user_directory_path)
its works, but the Path is Username and not user.id

How to partially update an object when using modelForm in Django?

I want to let users to add/update caption of their already updated photos without changing any other field of the photo.
Here is the model:
class UserPic(models.Model):
user = models.ForeignKey(User, unique=False)
picfile = ImageWithThumbsField(upload_to= get_uplaod_file_name, sizes=((648,648),(200,200),(1200,1200)))
caption = models.CharField(max_length=200 , blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
likes = models.IntegerField(default=0)
liked_by= models.ForeignKey(Liker, blank=True)
#models.permalink
def get_absolute_url(self):
return ('view_pirate', None, {'user': self.account.user})
def __unicode__(self):
return unicode(self.picfile.name)
views.py
def edit_photo(request, pic_id):
pic = UserPic.objects.get(id=pic_id)
if request.method == 'POST':
if pic.user== request.user:
picform = CaptionForm(request.POST)
if picform.is_valid():
edform = picform.save(commit=False)
edform.caption = request.POST['caption']
edform.save()
message = "caption is uploaded"
else:
edform = CaptionForm()
args = {}
args.update(csrf(request))
args['pic'] = pic
args['pic_id'] = pic_id
#args['form'] = edform
return render_to_response('userpics/photo.html', args,
context_instance= RequestContext(request))
photo.html
<div class="caption">
<form action="{% url "userpics.views.edit_photo" pic.id %}" method="POST">
{% csrf_token %}
{{form.as_ul}}
<input type="submit" value="SEND">
</form>
forms.py:
class CaptionForm(forms.ModelForm):
class Meta:
model= UserPic
fields = ('caption',)
However when I post the form, django still complain that:
MultiValueDictKeyError at /pics/edit/26
"'caption'"
I really got confused as I could not find any resources to deal with this particular problem. So appreciate your hints.
Ok I managed to solved the problem like this:
photo.html
<form action="{% url "userpics.views.edit_photo" pic.id %}" method="POST">
{% csrf_token %}
<input type="text" name="caption" value="{{pic.caption}}">
<input type="submit" value="SEND">
</form>
views.py
def edit_photo(request, pic_id):
pic = UserPic.objects.get(id=pic_id)
if request.method == 'POST':
if pic.user== request.user:
picform = CaptionForm(request.POST)
if picform.is_valid():
pic.caption = request.POST['caption']
pic.save()
message = "caption is uploaded"
else:
edform = CaptionForm(instance=pic)
args = {}
args.update(csrf(request))
args['pic'] = pic
args['pic_id'] = pic_id
return render_to_response('userpics/photo.html', args,
context_instance= RequestContext(request))

django hidden field error

i'm building a message system for a virtual community, but i can't take the userprofile id
i have in views.py
def save_message(request):
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.sender = request.user
u = UserProfile.objects.get(request.POST['userprofile_id'])
new_obj.owner = u
new_obj.save()
return HttpResponseRedirect('.')
else:
form = MessageForm()
return render_to_response('messages/messages.html', {
'form': form,
},
context_instance=RequestContext(request))
and the template:
{% block primary %}
<form action="." method="post">
{{ form.as_p }}
<p><input type="hidden" value="{{ userprofile.id }}" name = "owner" /></p>
<p><input type="submit" value="Send Message!" /></p>
</form>
{% endblock %}
forms.py:
class MessageForm(ModelForm):
class Meta:
model = Messages
fields = ['message']
models.py:
class Messages(models.Model):
message = models.CharField(max_length = 300)
read = models.BooleanField(default=False)
owner = models.ForeignKey(UserProfile)
sender = models.ForeignKey(User)
I don't figure out why i get this error,since i'm just trying to get the profileId of a user, using a hiddeen field.
the error is:
Key 'UserProfile_id' not found in <QueryDict: {u'owner': [u''], u'message': [u'fdghjkl']}>
and i'm getting it after i fill out the message text field.
Thanks!
it should be
u = UserProfile.objects.get(request.POST['owner'])
because the input's name is 'owner!!
Can you set raise(raise Exception,request.POST) before string: u = UserProfile.objects.get(request.POST['userprofile_id'])
And show me output.