I have tried to use modelformset_factory(User) to create a form to add (and in next step edit) a user.
I'm confused, why it creates a form with my current user and an empty one for a new one?
Any Idea how i could remove the one with the current?
Here is my view.py code:
#login_required
def update_or_edit_user_profile(request, UserID = None, template_name='userprofile_form.html'):
#check when a userid is provided if its the personal or if the user is allowed to edit the profile
if UserID != None:
if (request.user.has_perm('change_user_profile') or request.user.pk == UserID):
pass
else:
raise PermissionDenied
# when user is allowed to continue:
UserFormSet = modelformset_factory(User)
if request.method == 'POST':
userformset = UserFormSet(request.POST, request.FILES)
if userformset.is_valid():
newUser=userformset.save()
else:
userformset = UserFormSet()
return render_to_response(template_name, {
"userformset": userformset,
})
and my template:
<form action="" method="post">{% csrf_token %}
{{ userformset.as_p }}
<input type="submit" value="Send message" />
</form>
You're confusing forms with formsets. A formset is a collection of forms, so Django is giving you exactly what you asked for. If you only want a single form, then that's what you should use:
class UserForm(forms.ModelForm):
class Meta:
model = User
def update_or_edit_user_profile...
user = User.objects.get(pk=UserID)
if request.method == 'POST':
form = UserForm(request.POST, instance=user)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
form = UserForm(instance=User)
return render(request, template_name, {'form': form})
Related
I am trying to upload image from form but whenever I submit everything got saved in database other than image field.But when I try to do samething from admin panel it works.
models.py
class Post(models.Model):
title = models.CharField(("Title"), max_length=100)
title_image = models.ImageField(
("Title Image"),
upload_to='static/Images/TitleImages/',
max_length=None,
blank = True,null = True)
Forms.py
class AddPostForm(ModelForm):
class Meta:
model = Post
fields = ['title','title_image']
Views.py
class AddPostView(LoginRequiredMixin,CreateView):
model = Post
template_name = 'MainSite/add_post.html'
fields = '__all__'
def dispatch(self, request, *args, **kwargs):
if request.user.is_anonymous:
messages.error(request,"You need to login to access this page")
return redirect('/')
elif request.user.is_superuser:
if request.method == "POST":
form = AddPostForm(request.POST)
if form.is_valid():
form.save()
messages.success(request,"POST added successfully")
return redirect('/')
else:
print("error")
else:
print("method is not post")
form = AddPostForm()
return render(request,'MainSite/add_post.html',{'form':form})
else :
messages.error(request,"You need to have superuser permission to access this page")
return redirect('/')
addpost.html
<form action= "" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.media }}
{{ form|crispy}}
<button class="btn btn-primary profile-button" style = "width:150px;"type="submit" >Add Post</button></div>
</form>
my model have 2 things title and title_image but whenever I submit only title is saved and when I do through admin panel it works.
I dont know what I am doing wrong here any advice will be helpful.
Thanks in advance
You've to pass request.FILES in order to save files
if request.method == "POST":
form = AddPostForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.success(request,"POST added successfully")
return redirect('/')
i have a form, and i want to pass the user to it to see which logged in user filled it.
this is my forms.py
from .models import UserInfo
from django import forms
class InfoForm(forms.ModelForm):
class Meta:
model = UserInfo
fields = ('name', 'age', 'male', 'female', 'height', 'weight',
'BMI', 'BFP', 'phone', 'r_g_weight', 'physical_ready', 'fitness',
'workour_sports', 'others', 'goal_expression', 'body_change',
'noob','low_pro','semi_pro','pro','motivation_level','goal_block',
'change_time','past_sports','injury','work','work_time','wakeup_time',
'work_start_time','sleep_time','daily','hard_to_wake','ready_to_work',
'life_situation','weight_feel','daily_jobs','health_ready','workout_period',
'what_sport','where_sport','home_sport','weekly_time','sport_dislike','daily_food',
'food_quantity','hunger','vitamins','rejims','vegetables','goal_rec',
'stop','rec','heart','chest','chest_month','dizzy','bones','blood','other_reason')
and this is my view, i asked for the user with request.user , but the field in db always is empty for username.
def userForm(request):
if request.method == "POST":
form = InfoForm(request.POST)
if form.is_valid():
form.user = request.user
form.save()
return redirect('profile')
else:
form = InfoForm()
context = {
'form':form
}
return render(request, 'fitness/user_form.html', context)
so i have user in my models which has foreign key to my account
user = models.ForeignKey(Account,on_delete=models.CASCADE, null=True, blank=True)
and this is my template:
<div class="container">
<form action="{% url 'user-form' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="submit">
</form>
</div>
The problem lies in the way you are saving your form. You set the user attribute on the form, instead of the actual model object. The following should fix your issue
def userForm(request):
if request.method == "POST":
form = InfoForm(request.POST)
if form.is_valid():
# dont commit the object to the database as we need to set the user
object = form.save(commit=False)
# set the user
object.user = request.user
# finally save the object now that the user has been set
object.save()
return redirect('profile')
else:
form = InfoForm()
context = {
'form':form
}
return render(request, 'fitness/user_form.html', context)
This is my view:
def my_view(request):
if request.method == 'GET':
form = MyForm(initial={'user': "my_user"})
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
print("form is valid")
else:
form = MyForm()
return render(request, 'my_template.html', {'form': form})
And this is the form
class MyForm(forms.Form):
my_field = forms.CharField(max_length=100)
user = forms.CharField(widget=forms.HiddenInput())
def clean(self):
cleaned_data = super(MyForm, self).clean()
my_field = cleaned_data.get('my_field')
if not my_field:
raise forms.ValidationError('error')
Nothing is printed on the console (print("form is valid")), so the form is not valid, and this problem comes from the hidden field.
When I work without the hidden fields, the form is valid
What's wrong with my code ? How to initialize the values of hidden fields from the view function (or another way to do it without including it in the HTML) ?
The solution was not really related to my view or form class but to the template. So I am posting this if anyone missed it out: Don't forget to include the hidden fields in the form:
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
I'm having difficulty uploading the following model with model form. I can upload fine in the admin but that's not all that useful for a project that limits admin access.
#Models.py
class Profile(models.Model):
name = models.CharField(max_length=128)
user = models.ForeignKey(User)
profile_pic = models.ImageField(upload_to='img/profile/%Y/%m/')
#views.py
def create_profile(request):
try:
profile = Profile.objects.get(user=request.user)
except:
pass
form = CreateProfileForm(request.POST or None, instance=profile)
if form.is_valid():
new = form.save(commit=False)
new.user = request.user
new.save()
return render_to_response('profile.html', locals(), context_instance=RequestContext(request))
#Profile.html
<form enctype="multipart/form-data" method="post">{% csrf_token %}
<tr><td>{{ form.as_p }}</td></tr>
<tr><td><button type="submit" class="btn">Submit</button></td></tr>
</form>
Note: All the other data in the form saves perfectly well, the photo does not upload at all. Thank you for your help!
You need to pass request.FILES to your form:
form = CreateProfileForm(request.POST, request.FILES, instance=profile)
Ref: Handling uploaded files with a model
Form initialization code have to be like this:
form = MemberSettingsForm(request.POST or None, request.FILES or None, instance=user)
I figured it out. It was a issue with my views.py. You need to set the request.method == POST to make sure you can still have the instance as a part of the form. Works perfectly though.
#Views.py
def create_profile(request):
try:
profile = Profile.objects.get(user=request.user)
except:
pass
if request.method == 'POST':
form = CreateProfileForm(request.POST, request.FILES)
if form.is_valid():
new = form.save(commit=False)
new.user = profile.user
new.save()
else:
form = CreateProfileForm(request.POST or None, instance=profile)
return render_to_response('profile.html', locals(), context_instance=RequestContext(request))
add this before save model instance :
new.profile_pic = request.FILES.get('profile_pic')
How to display two forms on the same page? I will be grateful for your help
This is my views.py:
def register_user(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(username=form.cleaned_data['username'], email=form.cleaned_data['email'], password=form.cleaned_data['password'])
user.save()
user_profil = UserProfil(user=user, name=form.cleaned_data['name'], last_name=form.cleaned_data['last_name'],city=form.cleaned_data['city'])
user_profil.save()
return HttpResponseRedirect('/profile/')
return render_to_response('access.html', {'formRegister':form}, context_instance=RequestContext(request))
else:
form = RegistrationForm()
return render_to_response('access.html', {'formRegister':form}, context_instance=RequestContext(request))
def login_user(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
form = LoginForm(request.POST)
if forml.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user_profil = authenticate(username= username, password=password)
if user_profil is not None:
login(request, user_profil)
return HttpResponseRedirect('/profile/')
else:
return HttpResponseRedirect('/login/')
return render_to_response('access.html', {'formLogin':form}, context_instance=RequestContext(request))
else:
form = LoginForm()
context = {'formLogin':form}
return render_to_response('access.html', context, context_instance=RequestContext(request))
This is my urls.py
url(r'^access/$','users.views.register_user'),
url(r'^access/$','users.views.login_user'),
access.html:
<form action="" method="post">{%csrf_token%}
{{ formRegister.as_p }}
<p><input type="submit" value="Rejestruj"/></p>
</form>
<hr>
<form action="" method="post">{%csrf_token%}
{{ formLogin.as_p }}
<input type="submit" value="Login"/>
</form>
There is one template(access.html) and two views
When I replace urls.py(order):
url(r'^access/$','users.views.login_user'),
url(r'^access/$','users.views.register_user'),
Display only loginform
What if you change the names of your form variable in the return statement i.e.
{'formRegister':form}
and the other one:
{'formLogin':form}
UPDATE:
In your url file, you could do the following:
url(r'^access/login/$','users.views.login_user'),
url(r'^access/register/$','users.views.register_user'),
The same template will still be used, but with different views to handle the forms.
Other alternatives include:
Putting different URLs in the action attribute of the two forms. Then you will have two different view functions to deal with the two different forms.
Reading the values of submit buttons from the POST data. You can tell which submit button was clicked, then handle the logic.