I have a profile model for the User which has fields like "bio" and "cover" representing the General information about the profile of the user etc..
I want those two things to be able to be edited by the User. I did everything from urls.py to forms.py to views.py to template etc and it looks like I can submit the data and it looks like its validating but the data isnt being saved.. i dont know how..
here are my files, i've included more code than neeeded just to see if maybe the code somewhere else is in fault.
note, the code that is not working is the one with "general" somewhere included in the name
urls.py
from django.conf.urls import include, url
from . import views
app_name = 'profili'
urlpatterns = [
#profile
url(r'^$', views.ProfilePage, name='profile'),
url(r'^edit/$', views.EditProfile, name='edit_profile'),
url(r'^edit/general/$', views.EditGeneralProfile, name='edit_general_profile'),
url(r'^edit/password$', views.EditPassword, name='edit_password'),
url(r'^edit/delete/$', views.DeleteProfile, name='delete_profile'),
]
views.py
def EditProfile(request):
if request.method == 'POST':
form = EditProfileForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
form.save()
return redirect('/profile')
else:
form = EditProfileForm(instance=request.user)
formpw = PasswordChangeForm(user=request.user)
generalform = EditGeneralProfileForm(instance=request.user)
args = {
'form': form,
'formpw': formpw,
'generalform': generalform,
}
return render(request, 'profili/editprofile.html', args)
#login_required
def EditGeneralProfile(request):
generalform = EditGeneralProfileForm(request.POST, request.FILES, instance=request.user)
if generalform.is_valid():
generalform.save()
return redirect('/profile')
else:
print('THIS IS NOT WOOORRKIINNGGG')
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
followall = models.ManyToManyField(User, related_name='followfriend')
bio = models.TextField(max_length=100, default='', blank=True)
cover = models.FileField(blank=True)
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
forms.py
class EditGeneralProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('bio', 'cover')
template where the form actually appears in GET request
<form class="form-self general-form" method="post" action="{% url 'profili:edit_general_profile' %}" enctype="multipart/form-data">
{% csrf_token %}
{% for item in generalform %}
<div class="full-part">
<div class="label-par">
<span class="label-part">{{ item.label }}:</span>
</div>
<div class="original-part">{{ item }}</div>
</div>
{% endfor %}
<div class="full-part-btn">
<button type="submit" class="fpartbtn">Save</button>
</div>
</form>
This is a form for the Profile model, so you should pass that as the instance.
generalform = EditGeneralProfileForm(request.POST, request.FILES, instance=request.user.profile)
Related
In my app, I have created a context_proccessors.py to show the form to base.html file.
I am able to show the form in the base.html file. But the problem I am facing is I have no idea how to save that form data from base.html since there is no view for the base.html. Below is my code:
models.py
class Posts(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_posts')
post_pic = models.ImageField(upload_to='post_pic', verbose_name="Image")
post_caption = models.TextField(max_length=264, verbose_name="Caption")
created_date = models.DateTimeField(auto_now_add=True)
edited_date = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.user.username}"
forms.py
from django import forms
from post_app.models import Posts
class PostForm(forms.ModelForm):
class Meta:
model = Posts
exclude = ('user',)
context_proccessors.py
from post_app.forms import PostForm
def post_form(request):
form = PostForm
return {
'post_form': form,
}
base.html
<form method="POST" enctype="multipart/form-data">
{{ post_form|crispy }}
{% csrf_token %}
<button type="submit" class="btn btn-primary">Post</button>
</form>
I want the form to be displayed on every page so that the user can submit data from anywhere
def PostView(request):
form = PostForm()
if request.method == 'GET':
return render(request, 'base.html', {form:form})
elif request.method == 'POST':
form.save(request.data)
In the views.py of your app you can define this view, and the you have to provide it an url in the urls.py of the root directory. So evere time there is a request on that url, if the method is GET, the form will be rendered on base.html file, if the method is POST, the post will be saved.
By following the answer by N T I have implemented this. So, I had to make a URL pattern for the view and use that URL pattern in the action in the form of base.html.
view.py
#login_required
def postsaveview(request):
form = PostForm()
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
user_obj = form.save(commit=False)
user_obj.user = request.user
user_obj.slug = str(request.user) + str(uuid.uuid4())
user_obj.save()
return HttpResponseRedirect(reverse('profile_app:profile'))
urls.py
urlpatterns = [
path('post-save/', views.postsaveview, name='post-save'),
]
base.html
<form action="{% url "post-save" %}" method="POST" enctype="multipart/form-data">
{{ post_form|crispy }}
{% csrf_token %}
<button type="submit" class="btn btn-primary">Post</button>
</form>
i have registration and login forms that work well, but I am trying to edit the user profile but i don't seem to make it work, below are my codes, can you please point me the mistake i am making?
/views.py
#login_required()
def profile(request):
if request.method == 'POST':
# current_user = UserProfile.objects.get(username=request.user)
form = UserDetailsUpdate(request.POST, instance=request.user)
if form.is_valid():
form.save(commit=True)
return redirect('profile')
form = UserDetailsUpdate(instance=request.user)
return render(request, 'profile.html', {'form': form})
/models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
sex = models.CharField(max_length=20, blank=True)
website = models.URLField(blank=True)
image = models.ImageField(blank=True)
def __str__(self):
return self.user.username
/forms.py
class UserDetailsUpdate(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('image', 'website', 'sex')
/template/profile.html
{% if form %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="container">
{{ form.as_p }}
<input type="submit" value="Submit">
</div>
</form>
{% endif %}
looking at your model, i think you have some few things you missed,
there is no way to associate the UserProfile model to the onetoone relationship you have with the User model.
secondly the instance been passed to UserDetailsUpdate form should have reference to the UserProfile model.
Lastly in order to get the update fields populated with current data use also have to use the answer to my second point.
below is your solution.
Create your models here.
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
sex = models.CharField(max_length=20, blank=True)
website = models.URLField(blank=True)
image = models.ImageField(blank=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
the above code will create a corresponding userprofile model anytime a new user is created.
/views.py
#login_required()
def profile(request):
if request.method == 'POST':
# current_user = UserProfile.objects.get(username=request.user)
form = UserDetailsUpdate(request.POST, instance=request.user.userprofile)
if form.is_valid():
form.save(commit=True)
return redirect('profile')
form = UserDetailsUpdate(instance=request.user.userprofile)
return render(request, 'profile.html', {'form': form})
I am trying to update a userprofile model that i used to save additional information over the inbuilt User model, now when i am trying to update it , the image does not gets saved. I need help to resolve this issue
# In views.py
#login_required(login_url=LOGIN_REDIRECT_URL)
def update_user_profile(request):
userobj = get_object_or_404(UserProfile, user=request.user)
form = UserProfileForm(data = request.POST or None,files= request.FILES or None, instance=userobj)
if request.method=='POST':
print(form.is_valid())
if form.is_valid():
profile = form.save(commit=False)
profile.picture = form.cleaned_data['picture']
profile.about = form.cleaned_data['about']
profile.save()
else:
print("NO picure")
return HttpResponseRedirect("/blog/profile/")
return render(request, "blog/post_update.html", {'form':form})
#models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
about = models.CharField(max_length=200, null=True, blank=True)
picture = models.ImageField(upload_to="profile_images/", blank=True)
def __str__(self):
return str(self.user)
#In forms.py
class UserProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
self.fields['about'].widget.attrs.update({'class': 'form-control '})
self.fields['picture'].widget.attrs.update({'class': 'form-control-file'})
class Meta:
model = UserProfile
fields = ('about', 'picture')
# userprofileform.html
{% extends 'base.html' %}
{% block content %}
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-primary" value="Create Profile">
</form>
{% endblock %}
please take a look at the code and help. while registering if the image was uploaded it get's saved , but when i try to update the userprofile directly in profile section image does not get changed and shows the same as one saved while user registration else it shows None.
I did some changes on templates in settings.py and got my project runnning. Issue was that i was not mentioning the Templates directory properly
List item
Hello I am django beginner having tough time could someone please help me I don't know what am I doing wrong ?
I am trying to create a form and saving some data through it by using form.save(). And I am new to here also so don't mind any mistakes.
Here is my model:
from django.db import models
from stores.models import Store
class Category(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class Product(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30)
price = models.DecimalField(max_digits=5, decimal_places=5)
image = models.ImageField(upload_to='upload_to/')
category = models.ForeignKey(Category, default='Default', on_delete=models.CASCADE, blank=False, null=False)
store = models.ForeignKey(Store, on_delete=models.CASCADE, blank=False, null=False)
Here is my view:
from django.shortcuts import render, redirect
from .forms import NewPro
def pro(request):
if request.method == 'POST':
form = NewPro(request.POST)
if form.is_valid():
form.save()
return redirect('stores_list')
else:
form = NewPro()
return render(request, "default/add_product.html", {'form': form})
def product_list(request):
return render(request, 'default/product_list.html')
Here is my form:
from django import forms
from .models import Product
class NewPro(forms.ModelForm):
class Meta:
model = Product
fields = ('name', 'price', 'image','category', 'store',)
default/add_product.html :
{% extends 'default/base.html' %}
<html>
<head><title>E-Commerce App</title></head>
{% block content %}
<h1>Add Product details</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Add Product</button>
</form>{% endblock %}
</html>
Settings.py settings
MEDIA_ROOT = '/home/saifi/Saif_project/final_project/MEDIA_ROOT/upload_to'
I can see some indentation issues in the view - but I'll guess that's just formatting when copying into Stackoverflow.
the form.is_valid() check will validate all your form fields and will only write to the database if all the input fields are valid. If it's not saving, the first place I'd check would be for form errors.
In your template you can render the errors with {{form.errors}} and it will list each field and error.
You forgot request.FILES in your pro view function, you have an image file after all.
def pro(request):
if request.method == 'POST':
form = NewPro(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('stores_list')
else:
form = NewPro()
return render(request, "default/add_product.html", {'form': form})
Try using the form this way:
<form action="YOUR_URL_HERE" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Add Product</button>
</form>
I hope this will help. Welcome aboard ;)
Your indentation is wrong, the else should be for first 'if'
def pro(request):
form = NewPro()
if request.method == 'POST':
form = NewPro(request.POST)
if form.is_valid():
form.save()
return redirect('stores_list')
else:
form = NewPro()
return render(request, "default/add_product.html", {'form': form})
I've seen similar types of problems on here but I still haven't been able to work out my problem. When I save PhotographerProfileForm in my view, the form is rendered correctly but after clicking update/submit nothing is actually saved.
No errors are shown either.
What I have now are the fields are prepopulated and I would like the ability to save over these in the database, but nothing happens and at the moment you can only update it from the admin panel.
models.py
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.db import models
# Create your models here.
class PhotographerProfile(models.Model):
user = models.OneToOneField(User)
location = models.CharField(max_length=200)
bio = models.TextField(max_length=500)
def __str__(self):
return self.user.username
User.profile = property(lambda u: PhotographerProfile.objects.get_or_create(user=u)[0])
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=User)
def create_profile(sender,instance,created,**kwargs):
if created:
profile, new = PhotographerProfile.objects.get_or_create(user=instance)
urls.py
urlpatterns = [
url(r'^profile/$', 'photoprofile.views.photographer_profile', name = 'photographer_profile'),
url(r'^profile/portfolio/$', 'photoprofile.views.photographer_portfolio', name='photographer_portfolio'),
]
views.py
#login_required
def photographer_profile(request):
photographerProfile = PhotographerProfile.objects.get(user=request.user)
form = PhotographerProfileForm(initial={'bio':photographerProfile.bio, 'location':photographerProfile.location})#This means you can prepoulate it
return render_to_response('photographerprofile.html',{'form':form}, RequestContext(request))
if request.method == 'POST':
form = PhotographerProfileForm(request.POST, instance = request.user.profile,)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/profile')
else:
user = request.user
profile = user.profile
form = PhotographerProfileForm()
return render(request, 'photographerprofile.html', {'form':form})
def photographer_portfolio(request):
photographerProfile = PhotographerProfile.objects.get(user=request.user)
return render_to_response('photographerportfolio.html', {'photographerProfile':photographerProfile}, RequestContext(request))
forms.py
class PhotographerProfileForm(forms.ModelForm):
class Meta:
model = PhotographerProfile
exclude = ('user',)
photographerprofile.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h2> Profile</h2>
{% for field in form %}
{{ field.error}}
{% endfor %}
<form action='/accounts/profile/' method='post'>
{% csrf_token %}
{{form|crispy}}
<input type='submit' value='Update'/>
<p>Click <a href='/accounts/profile/portfolio/'>here</a> to view portfolio. </p>
</form>
{% endblock %}
You return in the third line of your view, before the form has been processed. Remove that line.