edit and update user model in django - python

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})

Related

Why does this work?? Class Meta, model = User

Can someone please explain this?? I'm in the process of trying my first post-tutorial project.
I've made a model called Profile with 4 attributes (given_name, surname, bio, image). I've made a form called ProfileForm which inherits from UserCreationForm and i've added the 4 attributes of my model into the form as form attributes.
MY Question is:
Why does it only work like this
class Meta:
model = User
This is my models.py file
class Profile(models.Model):
given_name = models.CharField(max_length=255)
surname = models.CharField(max_length=255)
bio = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to='uploads/', blank=True, null=True)
def __str__(self):
return self.given_name
class Meta:
ordering = ['given_name']
This is my forms.py file
class ProfileForm(UserCreationForm):
firstName = forms.CharField(max_length=255)
lastName = forms.CharField(max_length=255)
bio = forms.CharField(widget=forms.Textarea)
image = forms.ImageField()
class Meta:
model = User
fields = ['firstName', 'lastName', 'username', 'password1', 'password2', 'bio', 'image']
This is my views.py file
def sign_up_view(request):
if request.method == "POST":
form = ProfileForm(request.POST, request.FILES)
if form.is_valid():
user = form.save()
login(request, user)
profile = Profile.objects.create(
given_name=form.cleaned_data['firstName'],
surname = form.cleaned_data['lastName'],
bio = form.cleaned_data['bio'],
image = form.cleaned_data['image'])
return redirect('home')
else:
form = ProfileForm()
return render(request, 'core/sign_up.html', {"form": form})
This is my admin page for a profile.
This is my admin page for a User
Note : I'm able to achieve my desired outcome, but I'm having trouble in understanding how its working.
**Also if i wanted to link the Profile model with the User such that, if the User is deleted in admin then the respective profile would also get deleted??
It only works with model = User, because your fields, like username, etc. are fields of the User model, not of the Profile model.
What you can do is process the view with two forms. We thus make a form for the Profile model, and use the UserCreationForm for the User.
Furthermore the Profile needs to link to the user model, such that it is clear what Profile belongs to what user. We thus add a ForeignKey with:
from django.conf import settings
class Profile(models.Model):
# &vellip;
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
editable=False
)
# &vellip;
then we can define a Profile form with:
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = '__all__'
then we can work with two forms, the view looks like:
from django.contrib.auth.forms import UserCreationForm
def sign_up_view(request):
if request.method == 'POST':
user_form = UserCreationForm(request.POST, request.FILES)
profile_form = ProfileForm(request.POST, request.FILES, prefix='profile')
if user_form.is_valid() and profile_form.is_valid():
user = form.save()
profile_form.instance.user = user
profile_form.save()
login(request, user)
return redirect('home')
else:
user_form = UserCreationForm()
profile_form = ProfileForm(prefix='profile')
context = {'user_form': user_form, 'profile_form': profile_form}
return render(request, 'core/sign_up.html', context)
and in the template render it with:
<form action="{% url 'name-of-the-signup-view' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ user_form }}
{{ profile_form }}
</form>
we thus use two Django forms in the same HTML form, and prefix the ProfileForm with profile for the input fields.

Django ModelForm not saving data to database, Form.save is not working?

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})

Django: create a comment form when user is authenticated

I'm creating a simple blog application. A user is logged in this application while He/She can comment any post on my blog application. But cant impletement that idea.
This is my models.py file
from django.db import models
# Create your models here.
from user.models import CustomUser
from django.conf import settings
from django.db import models
from django.urls import reverse
class BlogPost(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
blog_title=models.CharField(max_length=200)
blog_description=models.TextField()
blog_pub=models.DateTimeField(auto_now_add=True)
blog_update=models.DateTimeField(auto_now=True)
def __str__(self):
return self.blog_title
def get_absolute_url(self):
return reverse('blog:blog_post', kwargs={'pk': self.pk})
class Comment(models.Model):
blogpost=models.ForeignKey(BlogPost, on_delete=models.CASCADE)
comment=models.CharField(max_length=300)
author=models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,blank=True, null=True)
author_name = models.CharField(max_length=50, default='anonymous', verbose_name=("user name"))
comment_pub = models.DateTimeField(auto_now_add=True)
comment_update = models.DateTimeField(auto_now=True)
def get_absolute_url(self):
return reverse('blog:home', kwargs={'pk':self.pk})
def __str__(self):
return self.comment
This is views.py file
class BlogPostSingle(DetailView, FormView):
model=BlogPost
template_name='blog/blog_post_single.html'
#fields = ['blog_title']
form_class = CreateCommentForm
success_url = '/blog/'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
this is my forms.py file
class CreateCommentForm(ModelForm):
class Meta:
model=Comment
fields = ('comment', 'blogpost')
and this is my html file and forms section
{% if user.is_authenticated %}
<h5>Hi, {{user.name}} leave your comment now</h5>
<form action="" method="post">
{% csrf_token %} {{form.as_p}}
<input type="submit" value="Submit comment">
</form>
{% else %}
<p>You're not logged in this site, please log in for comment </p>
{% endif %}
My target Idea: Just user logged on my blog application. He can be able to comment any post on my blog application. And my Comment Models contain two forignkey field.
You should pass the user to your view's context, so it will be available in the template:
class BlogPostSingle(DetailView, FormView):
...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['user'] = self.request.user
return context
on get_context_data see https://docs.djangoproject.com/en/2.0/ref/class-based-views/generic-display/#detailview
on self.request see
https://docs.djangoproject.com/en/2.0/topics/class-based-views/generic-display/#dynamic-filtering

(HELP) Django Model Form does not recognize Image file

I created a Form using one of my models i.e (Post), for my blog website. The form is meant for writers to post articles. In that form there is an Image attribute where the writer can upload an image. However, when i try to upload an image and post it, i get a feedback saying "field required", i think the form is not recognizing the image am trying to upload onto the the database. please help:
this is the form view from views.py:
def formview(request):
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return render(request, 'form.html', {'form':form})
this is from forms.py:
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
image = forms.FileField
class Meta:
model = Post
fields = ['category', 'title', 'body', 'image', 'author']
this from my models.py:
class Post(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=100)
pub_date = models.DateTimeField(auto_now_add=True)
body = models.TextField()
image = models.FileField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.IntegerField(default=1)
def __str__(self):
return self.title
this is my forms.html template:
<form method="POST" action="">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Post</button>
this is my urls.py:
from django.conf.urls import url
from . import views
app_name = 'posts'
urlpatterns = [
url(r'^$', views.homeview, name='homeview'),
url(r'^(?P<pk>[0-9]+)$', views.postview, name='postview'),
url(r'^category/(?P<pk>[a-zA-Z0-9]+)/$', views.categoryview,
name='categoryview'),
url(r'^author/(?P<pk>[a-zA-Z0-9]+)/$', views.authorview, name='authorview'),
url(r'^add_post/$', views.formview, name='formview'),
]
these are the pics might help explain what am trying to say:
Filling the form and selecting the picture
Error message after trying to post
Thank you
def formview(request):
if request.method == 'POST':
form = PostForm(request.POST,request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
else:
form = PostForm()
return render(request, 'form.html', {'form':form})
this form = PostForm(request.POST,request.FILES),you need add FILES to PostForm

Django model form data not being saved

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)

Categories