I noticed that when I upload a profile picture the picture is not being saved in my media directory.
I have manually created the folder and referenced it in settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
urls.py:
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
models.py:
class User(AbstractUser):
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
...
class Mentor(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True)
linkedin = models.URLField(max_length=200,null=True,blank=True)
photo = models.ImageField(null=True, blank=True, upload_to='media')
forms.py
#basic form
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name','last_name','email')
# edit mentor profile
class MentorProfileForm(forms.ModelForm):
class Meta:
model = Mentor
fields = ('photo',)
and views.py:
def edit_user(request):
user = request.user
# form = MentorProfileForm(instance=user)
if request.method == 'POST':
form = UserForm(request.POST, request.FILES, instance=user)
mentorform = MentorProfileForm(request.POST, request.FILES, instance=user)
if form.is_valid() and mentorform.is_valid():
form.save()
mentorform.save()
messages.success(request, ('Your profile was successfully updated!'))
return HttpResponseRedirect('%s' % (reverse('teachers:edit_user')))
else:
messages.error(request, ('Please correct the error below.'))
else:
form = UserForm(request.POST, instance=user)
mentorform = MentorProfileForm(request.POST, request.FILES, instance=user)
return render(request, 'classroom/teachers/app-instructor-profile.html', {'form': form,
'mentor_form': mentorform})
EDIT
As requested here is the html template I am using to upload the picture and other profile info. I am convinced that the problem is with my html. I'm not sure what else I could be doing wrong
<form id="edit-mentor-profile" class="form-horizontal" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label for="photo" class="col-sm-2 control-label">Avatar</label>
<div class="col-md-6">
<div class="media v-middle">
<div class="media-left">
<div class="icon-block width-100 bg-grey-100">
<img id="image" style="width:99%;height:99%;">
</div>
</div>
<div class="media-body">
<input type="file" id="files" class="btn btn-white btn-sm paper-shadow relative" data-z="0.5" data-hover-z="1" data-animated/>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-md-2 control-label">Full Name</label>
<div class="col-md-8">
<div class="row">
<div class="col-md-6">
<div class="form-control-material">
{{ form.first_name }}
<label for="edit-mentor-profile-first_name"></label>
</div>
</div>
<div class="col-md-6">
<div class="form-control-material">
{{ form.last_name }}
<label for="edit-mentor-profile-last_name"></label>
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="email" class="col-md-2 control-label">Email</label>
<div class="col-md-6">
<div class="form-control-material">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-envelope"></i></span>
{{ form.email }}
<label for="edit-mentor-profile-email"></label>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-6">
<div class="checkbox checkbox-success">
<input id="checkbox3" type="checkbox" checked="">
<label for="checkbox3">Subscribe to our Newsletter</label>
</div>
</div>
</div>
<div class="form-group margin-none">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-primary paper-shadow relative" data-z="0.5" data-hover-z="1" data-animated>Save Changes</button>
</div>
</div>
</form>
As #schwobaseggl said, file should be stored in /media/media folder. But there is another problem in your code, here:
mentorform = MentorProfileForm(request.POST, request.FILES, instance=user) # <-- Here
Here it should be:
mentorform = MentorProfileForm(request.POST, request.FILES, instance=user.mentor)
Because MentorProfileForm is using Mentor model, not User model. Also you need to fix the code for handling GET request:
def edit_user(request):
user = request.user
# form = MentorProfileForm(instance=user)
if request.method == 'POST':
form = UserForm(request.POST, request.FILES, instance=user)
mentorform = MentorProfileForm(request.POST, request.FILES, instance=user.mentor)
if form.is_valid() and mentorform.is_valid():
form.save()
mentorform.save()
messages.success(request, ('Your profile was successfully updated!'))
return HttpResponseRedirect('%s' % (reverse('teachers:edit_user')))
else:
messages.error(request, ('Please correct the error below.'))
else:
form = UserForm(instance=user) # <-- Here
mentorform = MentorProfileForm(instance=user.mentor) # <-- Here
return render(request, 'classroom/teachers/app-instructor-profile.html', {'form': form,
Please use below code in your html template. Where you are using form tag.
<form enctype="multipart/form-data" method="post">
--------- --------
---------Your code-------
</form>
Related
In my registration page, I am able to input a file other than an image for example -.txt or .py then save it. Even though my model is an Imagefield it allows files other than images. I have other models with imagefield in them but they are working fine. When I try to save a txt or py file there it raises an error. But in my registration page it directly saves it. I have also added validators still does not work. Note that when I try to edit user from admin page there it raises an error.
models.py :
from django.contrib.auth.models import User
from django.core.validators import validate_image_file_extension
from django.db import models
from django.utils import timezone
from multiselectfield import MultiSelectField
# Create your models here.
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, help_text=False)
profile_pic = models.ImageField(upload_to="profile_pic/",validators=[validate_image_file_extension], null=True , blank=True)
def __str__(self):
return self.user.username
views.py
def register(request):
accounts = User.objects.all()
if request.method == "POST":
user_form = UserForm(data=request.POST)
profile_form = UserProfileInfoForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.is_active = False
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'profile_pic' in request.FILES:
profile.profile_pic = request.FILES['profile_pic']
profile.save()
messages.success(request, 'Your account has been created Sucessfully!!!!')
messages.success(request, 'You can use your account after it has been approved by the admins.')
return redirect("/")
else:
messages.error(request, user_form.errors, profile_form.errors)
else:
user_form = UserForm()
profile_form = UserProfileInfoForm()
return render(request, 'MyTestApp/registration.html', {
'user_form': user_form,
'profile_form': profile_form,
"accounts": accounts}
)
and template :
<div class="jumbotron ">
<form method="post" enctype='multipart/form-data' autocomplete="off">
{%csrf_token%}
<div class="form-group row">
{% if user.is_authenticated %}
<h2>LOGOUT TO CREATE A NEW ACCOUNT </h2>
{% else %}
<h2>Please Register Here: </h2>
</div>
<br>
<div class="form-group row">
<label >{{ user_form.username.label }}</label>
{{ user_form.username }}
{{user_form.username.errors}}
</div>
<div class="form-group row">
<label>{{ user_form.password.label }}</label>
{{ user_form.password }}
{{user_form.password.errors}}
</div>
<div class="form-group row">
<label >{{ user_form.email.label }}</label>
{{ user_form.email }}
{{user_form.email.errors}}
</div>
<div class="form-group row">
<label>Profile Picture: </label>
{{ profile_form.profile_pic }}
{{ profile_form.profile_pic.errors}}
</div>
<br>
<div class="form-group row">
<input type="submit" name="userregister" value="Register" class="btn btn-dark">
</div>
</form>
</div
Created a website with products. I need to make a window for editing them on the site in order to change the manufacturer and other characteristics. This must be done in a pop-up window. I have data displayed, I change it, but nothing changes when I save it. How can this problem be solved.
My vievs:
def parts(request):
added = ''
error = ''
PartAllView = Part.objects.order_by('-id')
if request.method == 'POST' and 'parts_add' in request.POST:
form = PartForm(request.POST, request.FILES)
if form.is_valid():
form.save()
added = 'Добавлено'
else:
error = 'Данная запчасть уже добавлена'
if request.method == 'POST' and 'parts_edit' in request.POST:
PartPost = int(request.POST['parts_edit'])
PartID = Part.objects.get(id=PartPost)
if PartID:
PartID.save()
added = 'Запчасть успешно отредактирована'
else:
error = 'Ошибка редактирования'
form = PartForm()
data = {
'added': added,
'error': error,
'form': form,
'PartAllView': PartAllView,
}
return render(request, 'kross/parts.html', data)
My HTML:
{% if PartAllView %}
{% for el in PartAllView %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="modal fade" id="partEdit{{ el.id }}">
<div class="modal-dialog modal-dialog-centered text-center" role="document">
<div class="modal-content modal-content-demo">
<div class="modal-header">
<h6 class="modal-title">Добавление запчасти</h6><button aria-label="Close" class="btn-close"
data-bs-dismiss="modal"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<div class="row row-sm">
<div class="col-lg-6">
<div class="form-group">
<input type="text" class="form-control" name="brand" value="{{ el.brand }}">
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<input type="text" class="form-control" value="{{ el.number }}">
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<input type="text" class="form-control" value="{{ el.name }}"><br>
<input type="textarea" class="form-control" rows="2" value="{{ el.description }}">
</div>
</div>
</div>
{{ el.analog }}
...
You can use updateView to edit an existing data in your website by simply:
from django.views.generic.edit import UpdateView
From MyApp models import #Model
class editview(UpdateView):
model = #Your Model You want to edit
fields = [#Add the fields you want to edit]
template_name = 'edit.html'
success_url = ('Home')
In your edit Template add:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update">
I hope it help.
I am trying to submit a Message form for my Django Project but I keep receiving an error:
AttributeError at /
'MessageForm' object has no attribute 'cleaned_data'
I am not sure what is the reason for getting this error although I revised the https://docs.djangoproject.com/en/3.1/topics/forms/
Here is my views.py
def home(request):
if request.method == 'POST': #Check Post
form = MessageForm(request.POST)
if form.is_valid():
data = MessageForm() #Create Relationship with Model
data.name= form.cleaned_data['name']
data.email= form.cleaned_data['email']
data.message= form.cleaned_data['message']
data.ip = request.META.get('REMOTE_ADDR')
data.save()
messages.success(request,'Your Message has been sent, Thank you!')
return HttpResponseRedirect('base:home')
template_name = 'base/home.html'
form = MessageForm()
----------------------other unrelated contexts--------------------
context = {
'form': form,
}
return render(request, template_name, context)
Here is the urls.py
urlpatterns = [
path('', views.home,name='home')
]
Here is the template.html
<form class="form" id="form" method="post">
{% csrf_token %}
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input name="name" id="form-name" type="text" placeholder="Your Name" class="form-control input" autocomplete="off"/>
<div id="name-error"></div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input name="email" id="form-email" type="email" class="form-control input" placeholder="Your E-Mail" autocomplete="off">
<div id="email-error"></div>
</div>
</div>
</div>
<div class="form-group">
<textarea name="message" id="form-message" class="form-control input" rows="7" placeholder="Your Message here ..." autocomplete="off"></textarea>
<div id="message-error"></div>
</div>
<!-- Messages -->
{% if messages %}
{% for message in messages %}
<div class="container">
<div class=" alert alert-{{ message.tags }}">
{{ message }}
</div>
</div>
{% endfor %}
{% endif %}
<!-- Messages -->
<input id="form-submit" type="submit">
<div class="send-message" >
Send <i class="ni ni-send"></i>
</div>
</form>
You are constructing a new form, but that does not make much sense. Once your orignal form is validated, you can save that form, so:
def home(request):
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
form.instance.ip = request.META.get('REMOTE_ADDR')
form.save()
messages.success(request,'Your Message has been sent, Thank you!')
return redirect('base:home')
# …
I am trying to use a ModelForm to save objects to the database. I have also added an ImageField. Through the admin panel, I am easily able to add objects with an image but every time I submit the ModelForm with the same image it doesn't get saved and returns an error saying "This field is required" (screenshot and code attached).
How do I fix this?
Here's a screenshot of the error:
The models file:
from django.db import models
from django.conf import settings
class Book(models.Model):
rel_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name="Posted By")
image = models.ImageField(verbose_name="Image", upload_to="static/Books/img")
title = models.CharField(max_length=256, verbose_name="Title")
description = models.TextField(verbose_name="Description")
price = models.IntegerField(verbose_name="Price")
state = models.CharField(max_length=256, verbose_name="State")
city = models.CharField(max_length=256, verbose_name="City")
neighbourhood = models.CharField(max_length=256, verbose_name="Neighbourhood")
phone = models.IntegerField(verbose_name="Phone Number")
def __str__(self):
return self.title + f" ({self.rel_user.username})"
The forms file:
from django.forms import ModelForm
from Books.models import Book
class BookForm(ModelForm):
class Meta:
model = Book
fields = ['image', 'title', 'description', 'price', 'state', 'city', 'neighbourhood', 'phone']
The views file:
from django.shortcuts import render, redirect
from Books.forms import BookForm
from django.contrib import messages
from Books.models import Book
def sell(request):
if request.method == "GET":
form = BookForm()
else:
form = BookForm(request.POST)
form.instance.rel_user = request.user
if form.is_valid():
form.save()
messages.success(request, "Successfully added!")
return redirect('sell')
else:
messages.error(request, "Please fill in all the fields.")
return render(request, 'Books/sell.html', {"form": form})
The HTML code:
<div class="container" style="padding: 2%">
<div class="row">
<div class="col-md-4 col-sm-4 col-xs-12"></div>
<div class="col-md-4 col-sm-4 col-xs-12" style="background-color: rgba(256, 256, 256, 0.8);">
{% if messages %}
{% for message in messages %}
<div class="alert alert-primary" role="alert" style="margin-top: 2%;">
{{ message }}
</div>
{% endfor %}
{% endif %}
<form method="POST" action="{% url 'sell' %}">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Sell A Book</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Submit
</button>
</div>
</form>
</div>
<div class="col-md-4 col-sm-4 col-xs-12"></div>
</div>
</div>
from Books.forms import BookForm
from django.contrib import messages
from Books.models import Book
def sell(request):
if request.method == "GET":
form = BookForm()
else:
form = BookForm(request.POST,request.FILES)
form.instance.rel_user = request.user
if form.is_valid():
form.save()
messages.success(request, "Successfully added!")
return redirect('sell')
else:
messages.error(request, "Please fill in all the fields.")
return render(request, 'Books/sell.html', {"form": form})```
<div class="container" style="padding: 2%">
<div class="row">
<div class="col-md-4 col-sm-4 col-xs-12"></div>
<div class="col-md-4 col-sm-4 col-xs-12" style="background-color:rgba(256, 256, 256, 0.8);">
{% if messages %}
{% for message in messages %}
<div class="alert alert-primary" role="alert" style="margin-top: 2%;">
{{ message }}
</div>
{% endfor %}
{% endif %}
<form method="POST" action="{% url 'sell' %}"enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Sell A Book</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Submit
</button>
</div>
</form>
</div>
<div class="col-md-4 col-sm-4 col-xs-12"></div>
</div>
</div>
I am trying to create a registration form using django, when I submit my form the is valid() function fails and I am not sure why. I have my registration and login page all on one html page, although, I have called all the field names different names, eg login_username.
forms.py
class SignUpForm(forms.Form):
username = forms.CharField(label='Username', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter Username'}))
conUsername = forms.CharField(label='Confirm Username', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Confirm Username'}))
firstName = forms.CharField(label='First Name', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter Firstname'}))
lastName = forms.CharField(label='Last Name', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter LastName'}))
email = forms.CharField(label='Email', max_length=220,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter Email','type':'email'}))
conEmail = forms.CharField(label='Confirm Email', max_length=220,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Confirm Email','type':'email'}))
password = forms.CharField(label="Confirm Password", max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','type':'password','placeholder':'Enter Password'}))
conPassword = forms.CharField(label="Confirm Password", max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','type':'password','placeholder':'Confirm Password'}))
views.py
def SignUp(request):
regForm = SignUpForm()
form = LoginForm()
if request.method == 'POST':
if regForm.is_valid():
username = regForm.cleaned_data('username')
print username
confirm_username = regForm.cleaned_data('conUsername')
first_name = regForm.cleaned_data('firstName')
last_name = regForm.cleaned_data('lastName')
email = regForm.cleaned_data('email')
confirm_email = regForm.cleaned_data('conEmail')
password = regForm.cleaned_data('password')
confirm_password = regForm.cleaned_data('conPassword')
#try:
#user = User.objects.get(username=request.POST['username'])
#return render(request, 'index.html',{'error_message':'username must be unique'})
#except User.DoesNotExist:
#user = User.objects.create_user(request.POST['username'], password=request.POST['password'])
#login(request, user)
#return render(request, 'index.html')
else:
return render(request,'index.html',{'username_error':'usernames didnt match','form':form,'regForm':regForm})
else:
return render(request, 'index.html',{'form':form,'regForm':regForm})
index.html
<form class="regForm" method="POST" action="{% url 'signup' %}">
{% csrf_token %}
{{username_error }}
<div class="row">
<div class="col-md-2 col-md-offset-8">
<div class="form-group">
{{regForm.error_message.username}}
{{ regForm.username }}
</div>
</div>
<div class="col-md-2 ">
<div class="form-group">
{{error_message.conUsername}}
{{ regForm.conUsername }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 col-md-offset-8">
<div class="form-group">
{{ regForm.firstName }}
</div>
</div>
<div class="col-md-2">
<div class="form-group">
{{ regForm.lastName }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 col-md-offset-8">
<div class="form-group">
{{ regForm.email }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 col-md-offset-8">
<div class="form-group">
{{ regForm.conEmail }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 col-md-offset-8">
<div class="form-group">
{{ regForm.password }}
</div>
</div>
<div class="col-md-2">
<div class="form-group">
{{ regForm.conPassword }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-3 col-md-offset-9">
<div class="form-group">
<button type="submit" id="regBtn" class="btn btn-default">Submit</button>
</div>
</div>
</div>
</form>
Right now your form is always empty and therefore invalid. You forgot to add the request POST content to the form.
def SignUp(request):
# ...
if request.method == 'POST':
regForm = SignupForm(request.POST) # form needs content
if regForm.is_valid():
# ...
If you get stuck when calling .is_valid(), you can print(regForm.errors) to see what's up.
You have two main problems. Firstly, you are never passing the POST data to the form, so it can never be valid.
Secondly, for some reason you are ignoring everything that the form could tell you about why it is not valid, and always returning "usernames didn't match". What's more, you're not even doing anything to compare usernames, so that error message will never be accurate.
You should rework your view to follow the pattern as described in the documentation:
def SignUp(request):
if request.method == 'POST':
regForm = SignUpForm(request.POST)
if regForm.is_valid():
...
return redirect(somewhere)
else:
regForm = SignUpForm()
return render(request, 'index.html', {'regForm':regForm})
and in your template make sure you include {{ form.errors }} to show what the validation failures are.