i can't figure our why i can't override the post . when i post the form i go to "/" directory and nothing post . i already know knows that the forms works fine because i have it working as a fbv
my view
class ProfileUpdateView(LoginRequiredMixin, View):
template_name = "accounts/update.html"
def get_object(self):
user = get_object_or_404(User, username=self.kwargs.get("username"))
return user
def get(self, request, *args, **kwargs):
user = get_object_or_404(User, username=self.kwargs.get("username"))
user_form = UserForm(instance=user)
if user.is_client:
print("client get is working")
profile = Client.objects.get(id=user.clients.id)
profile_form = ClientForm(instance=profile)
if user.is_artisan:
profile = Artisan.objects.get(id=user.artisans.id)
profile_form = ArtisanForm(instance=profile)
return render(
request,
self.template_name,
{"user_form": user_form, "profile_form": profile_form},
)
def post(self, request, *args, **kwargs):
print("post is working")
if user.is_client:
print("client post is working")
profile_form = ClientForm(
request.POST, request.FILES, instance=profile
)
user_form = UserForm(request.POST, request.FILES, instance=user)
if user.is_artisan:
profile_form = ArtisanForm(
request.POST, request.FILES, instance=profile
)
user_form = UserForm(request.POST, request.FILES, instance=user)
if profile_form.is_valid() and user_form.is_valid():
print("form validation is working")
created_profile = profile_form.save(commit=False)
user_form.save()
created_profile.save()
reverse("accounts:profile", kwargs={"username": self.user.username})
return render(
request,
self.template_name,
{"user_form": user_form, "profile_form": profile_form},
)
template
<form action="." method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ user_form.as_p }}
<p> client form</p>
------------------------------------------------
{{ profile_form.as_p }}
<button class="btn btn-primary btn-round" type="submit">update</button>
</form>
Your form action is set to ".", i.e. "this directory".
Instead just leave it out to POST to the current URL.
<form method="POST" enctype="multipart/form-data">
Related
I have following views and each time form is submitted, result is rendered in new tab which has empty form.
How to render result in same form (with data submitted) without opening new tab?
views.py
class contact(View):
def __init__(self, logger=None, **kwargs):
self.logger = logging.getLogger(__name__)
def get(self, request):
return render(request, 'test.html')
def post(self, request):
if request.method == 'POST':
form = ContactForm(request.POST, request.FILES)
if form.is_valid():
self.host = form.data['ip']
messages.success(request, "Successful")
else:
form = ContactForm()
else:
form = ContactForm()
return render(request, 'test.html', {'form':form})
forms.py
class ContactForm(forms.Form):
ip = forms.CharField()
urls.py
urlpatterns = [
path('', contact.as_view()),
]
html
<body>
<form action="/" method= "post" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<button type="submit">Submit</button>
</form>
</body>
if form.is_valid()
form.save()
messages.success(request, 'Contact request submitted successfully.')
return render(request, 'your_page.html', {'form': ContactForm(request.GET)})
I created a profile form in models.py for and form.py to update it but all thing got updated except profile picture
views.py
views.py
#login_required
def update_profile(request):
if request.method == 'POST':
profile_form = ProfileForm(request.POST, request.FILES, instance=request.user.profile)
if profile_form.is_valid():
profile_form.save()
messages.success(request, "Your profile updated.")
else:
status_code = 400
message = 'Please correct the error below.'
messages.error(request, "Please use correct information")
else:
profile_form = ProfileForm(instance=request.user.profile)
return render(request, 'profile.html', {
'profile_form': profile_form
})
forms.py
models.py
First of, you need to include request.FILES where you initialize your form in the POST request like this:
profile_form = ProfileForm(request.POST, request.FILES, instance=request.user.profile)
Then in your html you need to add enctype="multipart/form-data" attribute to your form:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ profile_form.as_p }}
<button type="submit" value="Submit"></button>
</form>
try using forward slash at the end of upload_to path like this: upload_to='profile_pics/'
Multiple files do not save in admin, only the first saved in admin.
class Image(models.Model):
imageuploader_profile = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, null=True, blank=True)
image = models.FileField(upload_to ='pictsagram/')
image_caption = models.CharField(max_length=700)
def upload(request):
form = PostForm(request.POST,request.FILES)
if request.method == "POST":
if form.is_valid():
for f in request.FILES.getlist('image'):
post = Image(image=f)
post = form.save(commit=False)
post.imageuploader_profile = request.user
print(request.user)
post.save()
form.save()
return redirect('/')
else:
form = PostForm()
return render(request, 'upload.html', {"form": form})
class PostForm(forms.ModelForm):
class Meta:
model = Image
fields = ('image_caption', 'image',)
<form action="{% url 'site:upload' %}" method="post" enctype="multipart/form-data">
{%csrf_token%}
<input type="file" name="file" multiple onchange="loadFile(event)" required="" id="id_file">
<button type="submit">Post</button>
</form>
It looks like your form is for an Image object, but you're trying to create multiple images from a single form submit.
You are creating the Image(), but it doesn't look like you're attaching it to the form. So you'll probably need to reorganize the view something like:
def upload(request):
if request.method == "POST":
for image_file in request.FILES.getlist('image'):
form = PostForm(request.POST, image_file)
if form.is_valid():
image = form.save(commit=False)
image.imageuploader_profile = request.user
image.save()
form.save()
return redirect('/')
else:
form = PostForm()
return render(request, 'upload.html', {"form": form})
Also, cut/paste can mess up formatting, but always double-check your indentation for intended flow.
use this code:-----------------------------
def upload(request):
form = PostForm(request.POST,request.FILES)
if request.method == "POST":
if form.is_valid():
for f in request.FILES.getlist('file'):
post = Image(image=f)
post = form.save(commit=False)
post.imageuploader_profile = request.user
print(request.user)
post.save()
form.save()
return redirect('/')
else:
form = PostForm()
return render(request, 'upload.html', {"form": form})
class PostForm(forms.ModelForm):
class Meta:
model = Image
fields = ('image_caption', 'image',)
<form action="{% url 'site:upload' %}" method="post" enctype="multipart/form-data">
{%csrf_token%}
<input type="file" name="file" multiple onchange="loadFile(event)" required="" id="id_file">
<button type="submit">Post</button>
</form>
I would like to use a model form on the django.auth user, but I want to be able to pass in the PK to the model to manage other users, not the logged in user.
Is there a way to do this or do I need to create a regular form?
Django admin site is not appropriate for my use case.
Something like (which doesn't work of course...):
View
def edit_user(request,pk):
if request.method == 'POST':
user_form = UserEditForm(queryset=User.objects.get(pk=pk),
data=request.POST)
if user_form.is_valid():
user_form.save()
messages.success(request, 'User updated successfully')
else:
messages.error(request, 'Error updating your profile')
else:
user_form = UserEditForm(queryset=User.objects.get(pk=pk))
return render(request, 'edit_user.html', {'user_form': user_form })
UserEdit Form
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
Template:
% block content %}
<h1>Edit User:</h1>
<p> </p>
<form action="." method="post" enctype="multipart/form-data">
{{ user_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Save changes" class="btn btn-primary"> Manage</p>
</form>
{% endblock %}
Example URL: profile/edit-user/3/
I want the form populated with the PK of the user (the 3 in this case) NOT like my edit your own profile which passes in instance=request.user:
View for profile
def user_profile(request):
if request.method == 'POST':
user_form = UserEditForm(instance=request.user,
data=request.POST)
profile_form = UserProfileEditForm(instance=request.user.profile,
data=request.POST,
files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, 'Profile updated successfully')
else:
messages.error(request, 'Error updating your profile')
else:
user_form = UserEditForm(instance=request.user)
profile_form = UserProfileEditForm(instance=request.user.profile)
return render(request, 'profile_edit.html', {'user_form': user_form,
'profile_form': profile_form})
Still very new to django...
Thanks for your help.
BCBB
You just need to get the user you want and then pass it in to the form as the instance argument, exactly as you did with the logged in user.
def edit_user(request, pk):
user = User.objects.get(pk=pk)
if request.method == 'POST':
user_form = UserEditForm(instance=user,
data=request.POST)
...
else:
user_form = UserEditForm(instance=user)
...
Its gonna eat my mind. I have created a formset :
TimingFormSet = modelformset_factory(Timing, form=TimingForm, extra=2)
I have a view :
class HospitalDoctorAddView(CreateView):
template_name = "hospital_doctor_add.html"
form_class = HospitalDoctorInfoForm
model = HospitalDoctor
success_url = "/hospital-profile/"
def get_context_data(self, **kwargs):
context = super(HospitalDoctorAddView, self).get_context_data(**kwargs)
context['formset'] = TimingFormSet
return context
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
print "hellooww"
formset = TimingFormSet(request.POST, prefix='timings')
print "wow"
if form.is_valid() and formset.is_valid():
print "this"
self.form_save(form)
self.formset_save(formset)
return render(request, self.template_name, {
'form': HospitalDoctorInfoForm,
'formset': formset})
def form_save(self, form):
info = HospitalDoctor()
info.hospital = self.request.user
info.full_name = form.cleaned_data['full_name']
info.expertization = form.cleaned_data['expertization']
info.nmc_no = form.cleaned_data['nmc_no']
info.save()
def formset_save(self, form):
frm = Timing()
frm.day = form.cleaned_data['day']
frm.mng_start = form.cleaned_data['mng_start']
frm.mng_end = form.cleaned_data['mng_end']
frm.eve_start = form.cleaned_data['eve_start']
frm.eve_end = form.cleaned_data['eve_end']
frm.save()
Now in my template:
<form method="post" action="">{% csrf_token %}
{{form}}
{{formset.management_form}}
<table>
{% for form in formset %}
{{form}}
{% endfor %}
</table>
When I do this it displays both the form. But when I try to save or create it throws ValidationError: u'ManagementForm data is missing or has been tampered with'.
I dont know whats wrong. Really need help...
class HospitalDoctorAddView(CreateView):
template_name = "hospital_doctor_add.html"
form_class = HospitalDoctorInfoForm
model = HospitalDoctor
success_url = "/hospital-profile/" # better override get_success_url like below and remove this
def get_success_url(self):
return reverse('app_name_namespace:url_name') # app_name_namespace in project.urls and url_name in your app.urls
def get_context_data(self, **kwargs):
context = super(HospitalDoctorAddView, self).get_context_data(**kwargs)
context['formset'] = TimingFormSet()
return context
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
formset = TimingFormSet(request.POST, request.FILES)
if form.is_valid() and formset.is_valid():
return self.form_valid(form, formset)
else:
return self.form_invalid(form, formset)
def form_valid(self, form, formset):
form.save()
formset.save()
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form, formset):
return self.render_to_response(
self.get_context_data(
form=form,
formset=formset,
)
)
template:
<form method="post" action="">{% csrf_token %}
{{form.as_table}}
<table>
{{ formset }}
</table>
</form>