I have a problem with creating a profile instance in Django. when I try to update a profile the images of the profile don't save in the database My guess is that the form.save(commit=False) does not upload the photo nor update the field as it should but I do not understand why :
here is my code:
models.py
class Profile(models.Model):
user = models.OneToOneField(User, primary_key =True, on_delete=models.CASCADE, related_name= 'profile')
image = models.OneToOneField(UserImage, on_delete=models.SET_NULL, null=True, blank=True)
phone_number = models.CharField(max_length=50, null = True, blank = True)
followers = models.ManyToManyField(User, related_name='follower', blank=True)
following = models.ManyToManyField(User, related_name='following', blank=True)
biography = models.TextField(max_length=250, null=True, blank=True)
class UserImage(models.Model):
avatar = models.ImageField(blank=True, null=True,upload_to='avatar_pic')
header_image = models.ImageField(blank=True, null=True,upload_to='header_pic')
forms.py
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = (
'phone_number',
'biography',
)
class ImageProfileForm(ModelForm):
class Meta:
model = UserImage
fields = (
'avatar',
'header_image',
)
views.py
#login_required
def CompleteSignUp(request):
if request.method == 'POST':
profile_form = ProfileForm(request.POST,request.FILES ,instance=request.user.profile)
image_profile_form = ImageProfileForm(request.POST, instance=request.user.profile.image)
if profile_form.is_valid() and image_profile_form.is_valid():
profile = profile_form.save(commit=False)
images = image_profile_form.save()
profile.user = request.user
profile.social = social
profile.image = images
profile_form.save()
return redirect('blog:Home')
else:
profile_form = ProfileForm(
initial={
'phone_number':request.user.profile.phone_number,
'biography':request.user.profile.biography
}
)
if request.user.profile.image:
image_profile_form = ImageProfileForm(
initial={
'avatar':request.user.profile.image.avatar,
'header_image':request.user.profile.image.header_image
}
)
else:
image_profile_form = ImageProfileForm()
return render(request, 'user/createprofile.html', {'form_p': profile_form, 'form_i': image_profile_form})
templates
{% block content %}
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div>
{{ form_p.biography }}
biography
</div>
<div>
{{ form_p.phone_number }}
phone_number
</div>
<div>
{{ form_i.avatar }}
avatar
</div>
<div>
{{ form_i.header_image }}
header
</div>
<br>
<input type="submit" value="Register">
</br>
</form>
{% for field in form_s %}
{% for error in field.errors %}
<p style="color: rgba(255, 0, 0, 0.678)">{{ error }}</p>
{% endfor %}
{% endfor %}
{% endblock %}
profile save but the image of the profile doesn't save what's my fault.
...
Change:
profile.user = request.user
profile.social = social
profile.image = images
profile_form.save()
To:
profile.user = request.user
profile.social = social
profile.image = images
profile.save() # Use this
You need to save profile instead of the form with commit=False, because you did custom stuff to profile.
Related
I have django app with authentication in it. I have forms.py file like this:
<form class="login_form" method="post" novalidate>
{% csrf_token %}
<div class="col-md-3 col-md-auto text-center">
<b>First Name:<b>
{{ form.first_name }}
{% if 'first_name' in error %}
<div style='color:red'>{{error.first_name.0.message}}</div>
{% endif %}
</div>
<div class="col-md-3 col-md-auto text-center">
<b>Last Name:<b>
{{ form.last_name }}
{% if 'last_name' in error %}
<div style='color:red'>{{error.last_name.0.message}}</div>
{% endif %}
</div>
<div class="col-md-3 col-md-auto text-center">
<b>username:<b>
{{ form.username }}
{% if 'username' in error %}
<div style='color:red'>{{error.username.0.message}}</div>
{% endif %}
</div>
<div class="col-md-3 col-md-auto text-center">
<b>Email:<b>
{{ form.email }}
{% if 'email' in error %}
<div style='color:red'>{{error.email.0.message}}</div>
{% endif %}
</div>
<div class="col-md-3 col-md-auto text-center">
<b>Password<b>
{{ form.password }}
{% if 'password' in error %}
<div style='color:red'>{{error.password.0.message}}</div>
{% endif %}
</div>
<div class="col-md-3 col-md-auto text-center">
<b>Confirm password:<b>
{{ form.confirm_password }}
{% if 'confirm_password' in error %}
<div style='color:red'>{{error.confirm_password.0.message}}</div>
{% endif %}
</div>
<button type="submit" class="submit_btn">Sign Up</button>
<span class="peder"><p>If you already have account<br>Login</p></span>
</form>
and forms.py:
class CustomerSignUpForm(UserCreationForm):
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
email = forms.EmailField(required=True)
username = forms.CharField(max_length=40)
password = forms.CharField(max_length=30)
confirm_password = forms.CharField(max_length=30)
class Meta(UserCreationForm.Meta):
model = User
#transaction.atomic
def save(self):
user = super().save(commit=False)
user.is_customer = True
user.save()
customer = Customer.objects.create(user=user)
customer.first_name = self.cleaned_data.get('first_name')
customer.last_name = self.cleaned_data.get('last_name')
customer.username = self.cleaned_data.get('username')
customer.email = self.cleaned_data.get('email')
customer.password = self.cleaned_data.get('password')
customer.confirm_password = self.cleaned_data.get('confirm_password')
customer.save()
return user
My model looks like this:
class User(AbstractUser):
is_customer = models.BooleanField(default=False)
is_employee = models.BooleanField(default=False)
# first_name = models.CharField(max_length=100)
# last_name = models.CharField(max_length=100)
signup_confirmation = models.BooleanField(default=False)
class Customer(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE, primary_key = True)
first_name = models.CharField(max_length=100, blank=True)
last_name = models.CharField(max_length=100, blank=True)
username = models.CharField(max_length=40, blank=True)
email = models.EmailField(max_length=40, blank=True)
password = models.CharField(max_length=30, blank=True)
confirm_password = models.CharField(max_length=30, blank=True)
So when user clicks submit button on signup form it should save the form and send him an email.
view
class customer_register(CreateView):
model = User
form_class = CustomerSignUpForm
template_name = 'authentication/customer_register.html'
def form_valid(self, form):
user = form.save()
# current_site = get_current_site(request)
current_site = '127.0.0.1:8000'
subject = 'Please Activate Your Account'
message = render_to_string('authentication/email/activation_request.html', {
'user': user,
'domain': current_site,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
send_mail(
subject,
message,
'from#example.com',
['to#example.com'],
fail_silently=False,
)
return redirect('/')
But when I click submit button on my page nothing happens. In my terminal I do get [13/Sep/2022 08:18:39] "POST /accounts/customer_register/ HTTP/1.1" 200 9660 but user is not created and email is not sent. Could someone explain why this is happening and present the solution? Thanks:)
First of all.
We need to install few dependencies.
1. pip install django-crispy-forms
2. add 'crispy_forms', to your INSTALLED_APPS in your projects settings.py
3. add CRISPY_TEMPLATE_PACK = 'bootstrap4' to your settings.py
authentication/customer_register.html
We simplify the form through crispy forms that gives us a bootstrap 4 result.
{% load crispy_forms_tags %}
<form class="login_form" method="post" novalidate>
{% csrf_token %}
{% crispy form %}
<button type="submit" class="btn btn-success mt-3 float-end">Submit</button>
</form>
forms.py
We create a modelForm taking the model User and its fields as Meta:
from django import forms
class CustomerSignUpForm(forms.ModelForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email',
'username', 'password', 'confirm_password']
views.py
#The generic view CreateView Polymorphism already benefits of the post method that will save the user
from django.views.generic import CreateView
from.forms import CustomerSignUpForm
class CustomerRegisterCreateView(CreateView):
model = User
form_class = CustomerSignUpForm
template_name = 'authentication/customer_register.html'
urls.py
We create a path so we can link it to a URL with not forgetting the .as_view() as it is a class based view ( function based views do not require this )
from .views import (
CustomerRegisterCreateView,
)
urlpatterns = [
path('customer-register/', CustomerRegisterCreateView.as_view(), name="customer-register"),
]
models.py
Once a user is created, we use a signal that will trigger on user creation.
from django.db.models.signals import post_save
def User_receiver(sender, instance, created, *args, **kwargs):
if created:
print('we went thought the User signal !')
subject = "Welcome"
email_template_name = "authentication/Register-email.txt"
user = User.objects.get(username=instance.username)
c = {
'username': user,
}
email = instance.email
email_1 = render_to_string(email_template_name, c)
send_mail(subject, email_1, 'your_email',
[email], fail_silently=False)
'''
post_save.connect(User_receiver, sender=User)
I want to make a register form, that contains user form and user profile form
my table user is from Django auth_user so it will contain primary column like id, user, email, password, started date, etc
and I have user profile form, that creates from forms.py and the model from model.py here, it has FK user_id which connected to ID in auth_user
the problem is, when I insert the data, it always said this field required, even though I already insert all the column
here's the code
forms.py
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form-control'}))
username = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
email = forms.CharField(widget=forms.EmailInput(attrs={'class': 'form-control'}))
class Meta():
model = User
fields = ('username', 'email', 'password')
class UserProfileInfoForm(forms.ModelForm):
ROLE_1 = 'Business Analyst'
ROLE_2 = 'Manager'
ROLE_3 = 'Segment Manager'
ROLE_4 = 'Admin'
ROLE_CHOICES = (
(ROLE_1, u"Business Analyst"),
(ROLE_2, u"Manager"),
(ROLE_3, u"Segment Manager"),
(ROLE_4, u"Admin")
)
role = forms.ChoiceField(choices=ROLE_CHOICES, widget=forms.Select(attrs={'class': 'form-control'}))
description = forms.CharField(widget=forms.Textarea(attrs={'class': 'form-control'}))
address = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
phone = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
cell = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
def __init__(self, disable_fields=True, *args, **kwargs):
super().__init__(*args, **kwargs)
if disable_fields:
self.fields['role'].disabled = True
models.py
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
role = models.CharField(max_length=250, blank=True)
description = models.TextField(max_length=250, blank=True)
address = models.CharField(max_length=250, blank=True)
phone = models.CharField(max_length=250, blank=True)
cell = models.CharField(max_length=250, blank=True)
profile_pic = models.ImageField(upload_to='profile_pics', blank=True)
def __str__(self):
return self.user.username
def register(request):
registered = False
if request.method == 'POST':
print("test")
user_form = UserForm(request.POST)
profile_form = UserProfileInfoForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password)
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()
registered = True
else:
print(user_form.errors, profile_form.errors)
else:
user_form = UserForm()
profile_form = UserProfileInfoForm(disable_fields=False)
return render(request, 'register.html',
{'user_form': user_form,
'profile_form': profile_form,
'registered': registered})
html
<section id="main-content">
<section class="wrapper">
<h3><i class="fa fa-angle-right"></i>Register User</h3>
<!-- row -->
<!-- FORM VALIDATION -->
<div class="row mt">
<div class="col-lg-12">
<div class="form-panel">
<div class=" form">
{% load staticfiles %}
{% block body_block %}
{% if registered %}
<h1>Thank you for registering!</h1>
{% else %}
<form class=" form-horizontal style-form" id="commentForm" enctype="multipart/form-data" method="POST" action="">
{% csrf_token %}
{{ user_form.as_p}}
{{ profile_form.as_p }}
<button class="btn btn-theme" type="submit" style="height:50px;width:200px;" value="Register">Register</button>
</form>
{% endif %}
</div>
</div>
{% endblock %}
</div>
</div>
<!-- /form-panel -->
</div>
<!-- /col-lg-12 -->
</div>
<!-- /row -->
</section>
</section>
can someone help me? i already try some way like remove the profile_form.isvalid() in the if condition, and it goes to the next step, but it is error ORA-01400: cannot insert NULL into ("ICB"."POLLS_USERPROFILEINFO"."USER_ID") which user_id is the fk
at first .. I make this module and it works fine, but 1 month later it errors, and I didn't change any code
Try edit this section in your html:
action="your_url_here"
I extended standart django user model by one-to-one field. Made news block, and added comments there. In comments i cant display user avatar from UserProfile model, cause dont understand how correctly ask database for it D;. Here my code:
main/models.py
from django.db import models
from django.utils import timezone
from django.contrib import auth
from django.contrib.auth.forms import User
from django.shortcuts import render, redirect
from profiles.models import UserProfile
# Create your models here.
class News(models.Model):
news_title = models.CharField(max_length=250)
news_body = models.TextField(max_length=2000, blank=True)
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
image = models.FileField()
published_date = models.DateTimeField(blank=True, null=True)
def publish(self, request):
self.published_date = timezone.now()
self.save()
return redirect('index')
def __str__(self):
return self.news_title
class Comment(models.Model):
news = models.ForeignKey('main.News', related_name='comments',
on_delete=models.CASCADE)
author = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
approved_comment = models.BooleanField(default=False)
def approve(self):
self.approved_comment = True
self.save()
def __str__(self):
return self.text
profiles/models.py
class UserProfile(models.Model):
JEW_CHOICE = (
('Да', 'Да'),
('Нет', 'Нет'),
)
MF_CHOICE = (
('М', 'М'),
('Ж', 'Ж')
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
country = models.CharField(max_length=100, default='', blank=True)
city = models.CharField(max_length=100, default='', blank=True)
description = models.CharField(max_length=500, default='', blank=True)
website = models.URLField(default='', blank=True)
avatar = models.ImageField(default='', blank=True)
gender = models.CharField(max_length=100, choices = MF_CHOICE, default = 'М', blank=True)
jew = models.CharField(max_length=100, choices = JEW_CHOICE, default = 'Да', blank=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.get_or_create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.userprofile.save()
#property
def avatar_url(self):
if self.avatar and hasattr(self.avatar, 'url'):
return self.avatar.url
main/views.py (meme_detail is the view, where should be comments with user info)
def meme_detail(request, pk):
news = get_object_or_404(News, pk=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.author = request.user
comment.news = news
comment.save()
return redirect('main:meme_detail', pk=news.pk)
else:
form = CommentForm()
return render(request, 'main/meme_detail.html', {'news': news, 'form': form,})
meme_detail.html (news template with comments)
{% extends 'main/base.html' %}
{% block body %}
<h2>{{news.news_title}}</h2>
<img src='{{news.image.url}}' name='image' width='500px;'><br>
{{news.news_body}} <br><br>
<div class="row">
<div class="col">
<b>{{news.author}}</b>
</div>
<div class="col">
<i>{{news.published_date}}</i>
</div>
</div>
<div class="underline"></div>
<h3>Комментарии:</h3><br>
{% for comment in news.comments.all %}
<div class="row">
<div class="col-"><img src="{{ userprofile.avatar.url }}" alt="user-avatar" width="100px" height="100px"></div>
<div class="col">{{ comment.text }}</div>
</div>
<div class="row">
<div class="col"><strong>{{ comment.author }}</strong></div>
<div class="col">{{ comment.created_date}}</div>
</div>
<div class="underline"></div>
<br>
{% empty %}
<p>Пока ещё нет комментариев :(</p>
{% endfor %}
{% if request.user.is_authenticated %}
<div class="row">
<form method="POST">
{% csrf_token %}
{{form.text}}<br><br>
<a class="btn btn-success" href="{% url 'main:meme_detail' pk=news.pk %}"><button class='btn btn-success'>Добавить коммент! </button></a>
</form>
</div>
{% else %}
<i>Вы не можете писать комментарии, необходимо зарегистрироваться!</i>
{% endif %}
{% endblock %}
So, in this template, where "userprofile.avatar.url" should be object reference on User avatar. I tryed a lot of things, but it always the same:not displaying
You should do:
<img src="{{ comment.author.userprofile.avatar.url }}" alt="user-avatar" width="100px" height="100px">
Your comment has a foreign key to User (author), and User has a one to one field to UserProfile, which is the one that has the avatar attribute.
Also another tip:
You shouldn't really reduce the image in CSS (width: 100px; height: 100px;), but instead use a tool that allows you to create thumbnails of images. I use sorl-thumbnail and can't recommend it enough.
The reason is that if every user uploads a 1000x1000 image, you are downloading those big images that you don't really need, hence your site will be slower.
Maybe you should try accesing the User object in the template, not the Userprofile.
<img src="{{ user.userprofile.avatar.url }}" ...
So I have these two models Lecture and FileUpload. I want that the user to be able to add a lecture to a specific course and also upload multiple files for that lecture. Thing is that after I submit the form the information gets saved except for the uploaded files, so I am guessing something is wrong with my formset. Please have a look:
FileFormset = inlineformset_factory(Lecture, FileUpload, exclude=[])
def classroom(request):
if request.method == 'POST':
form1 = LectureForm(request.POST)
if form1.is_valid():
lecture = form1.save()
formset = FileFormset(request.POST, request.FILES, instance=lecture, prefix='files')
if formset.is_valid():
formset.save()
else:
print(formset.errors)
formset.save()
return redirect('courses:index')
else:
form1 = LectureForm()
formset = FileFormset()
context = {'teacher_data': TeacherData.objects.all(),
'teachers': Teacher.objects.all(),
'courses': Course.objects.all(),
'form1': form1,
'formset': formset,
}
return render(request, 'courses/classroom.html', context)
<form method="post" action="">
{% csrf_token %}
{{ form1.as_p }}
{{ formset.management_form }}
{% for form in formset %}
{{ form }} <br>
{% endfor %}
<br>
<button type="submit">Add Lecture</button>
</form>
class LectureForm(forms.ModelForm):
class Meta:
model = Lecture
fields = ('course', 'lecture_title', 'lecture_category', 'content')
class FileForm(forms.ModelForm):
class Meta:
model = FileUpload
fields = ('files',)
class Lecture(models.Model):
LECTURE_CHOICES = (
('Courses', 'Courses'),
('Seminars', 'Seminars'),
)
course = models.ForeignKey('Course', on_delete=models.CASCADE, default='', related_name='lectures',)
lecture_category = models.CharField(max_length=10, choices=LECTURE_CHOICES, default='Courses',)
lecture_title = models.CharField(max_length=100, blank=True, null=True)
content = models.TextField(blank=True, null=True)
def __str__(self):
return str(self.lecture_title)
class FileUpload(models.Model):
files = models.FileField(upload_to='documents', null=True, blank=True)
lecture = models.ForeignKey('Lecture', related_name='files', on_delete=None, default=None)
def __str__(self):
return str(self.files)
add enctype attribute to you from widget like,
<form method="post" action="" enctype= multipart/form-data>
Try this
I am using Python 2.7, Django 1.9.
I'm trying to get an image from the user with this model/form pair:
models.py
from PIL import Image
class UserProfile(models.Model):
user = models.OneToOneField(User)
website = models.URLField(blank=True, null=True)
location = models.CharField(max_length=200, null=True)
longitude = models.FloatField(null=True)
latitude = models.FloatField(null=True)
credit = models.FloatField(default=0, null=True)
picture = models.ImageField(upload_to='media/images/profile_pictures', blank=True, null=True)
def __unicode__(self):
return self.user.username
forms.py
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = [
"website",
"location",
"picture",
]
widgets = {
'location': forms.TextInput(
attrs={'id': 'location', 'class': 'geo', 'required': True, 'placeholder': 'location'}
),
}
This is saved using the following view:
def register(request):
registered = False
if request.method == "POST":
user_form = UserForm(request.POST)
profile_form = UserProfileForm(request.POST, request.FILES)
if user_form.is_valid() and profile_form.is_valid():
print(request.POST['location'])
print(str(request.POST['location']))
user = user_form.save()
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
else:
print user_form.errors, profile_form.errors
else:
profile_form = UserProfileForm()
user_form = UserForm()
return render(request, "register.html", {'user_form' : user_form, 'profile_form' : profil
But upon execution, no pictures are saved to the folders. Here is the root of the image_urls:
project/static/media/images/profile_pictures
Any ideas?
Edit: Here's the html:
{% load static from staticfiles %}
{% block head %}
{% endblock %}
{% block content %}
{% if registered %}
<h1>Thank you for registering.</h2><br>
Start playing!
{% else %}
<form id="user_form" method="post" action="/register/" enctype="multipart/form-data">
{% csrf_token %}
{{ user_form.as_p }}
{{ profile_form.as_p }}
<input type="submit" name="submit" value="register" />
</form>
{% endif %}
{% endblock %}
I upgraded to the latest version of Pillow and it works now.