In my project as soon as user signup it is redirected to update view where he has to fill this information.Since the user has also logged in automatically after signup I want that user field to be filled automatically and can't be edited.
models.py
class Userpro(models.Model):
user = models.OneToOneField(User)
dob = models.DateField(default=datetime.date.today)
country = models.CharField(max_length=50, default='')
qualification = models.CharField(max_length=10, choices=CHO,
default='No')
university = models.CharField(max_length=100, default='')
location = models.CharField(max_length=100, default='')
def __str__(self):
return str(self.user)
forms.py
class UserProForm(forms.ModelForm):
class Meta:
model = Userpro
fields = '__all__'
views.py
def update(request):
if request.method == 'POST':
form = UserProForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('/')
else:
redirect('/')
else:
form = UserProForm()
return render(request, 'app/update.html', {'form': form})
All the required libraries are imported.
I was with the same problem. The solution I've found is very simple.
First remove the "user" field in your forms.py
them in views:
if form.is_valid():
obj = form.save(commit=False)
obj.user = request.user
obj.save()
by making this the obj is a saved form (but not commited in database) and them you can manage it like puting the user as the request.user; them save.
notice that obj."the name you put in your models"
You can use widgets for your form. Something like this(code below is not tested).
from django.forms import TextInput
class UserProForm(forms.ModelForm):
class Meta:
model = Userpro
fields = '__all__'
widgets = {
'user': TextInput(attrs={'readonly': 'readonly'})
}
def update(request):
instance = Userpro.objects.filter(user=request.user).first()
if request.method == 'POST':
form = UserProForm(request.POST, instance=instance)
if form.is_valid():
form.save()
return redirect('/')
else:
return redirect('/')
else:
form = UserProForm(instance=instance)
return render(request, 'app/update.html', {'form': form})
Edited: we should pass user inside dict like this:
form = UserProForm({'user': request.user})
Edited 2: You should find profile object first and then pass it to the form
instance = Userpro.objects.filter(user=request.user).first()
form = UserProForm(request.POST, instance=instance)
I think it will be better if you will use ModelForm with fields that you want to modify and in template show object instance values like that.
from django.forms import TextInput
class UserProfileForm(forms.ModelForm):
class Meta:
model = Userprofile
fields = ('field1', 'field2')
def update(request):
if request.method == 'POST':
form = UserProfileForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('/')
else:
redirect('/')
else:
form = UserProfileForm(user=request.user)
return render(request, 'app/update.html', {'form': form})
# template
<form method="post">
{% csrf_token %}
<div class="form-row">
{{ form.field1.errors }}
{{ form.field1.label_tag }} {{ form.field1 }}
</div>
<div class="form-row">
{{ form.field2.errors }}
{{ form.field2.label_tag }} {{ form.field2 }}
</div>
<div class="form-row">
{{ form.instance.field3.errors }}
{{ form.instance.field3.label_tag }} {{ form.instance.field3 }}
</div>
</form>
Related
When I send an image to the bank to save, it always returns this message "This field is required." but I fill the field with an image but it always returns this error.
Views
def criar (request):
form = forms_user()
if request.method == 'GET':
return render(request, 'create.html', {'form': form})
if request.method == 'POST':
form = forms_user(request.POST, request.FILES )
if form.is_valid():
form.save()
messages.add_message(request, constants.SUCCESS, 'Cadastro realizado com sucesso.')
form_clean = forms_user()
return render(request, 'create.html', {'form': form_clean})
else:
print(form.errors)
messages.add_message(request, constants.ERROR, f'{form.errors}')
return render(request, 'create.html', {'form': form})
Models
class items(models.Model):
titulo:models.CharField(max_length=30, blank=False)
descricao = models.TextField(max_length=50, blank=False)
usuario = models.CharField(max_length=20, blank=False)
Preco = models.BooleanField(blank=False)
royalties = models.PositiveIntegerField(blank=False)
image = models.ImageField(upload_to='image/', null=True, blank=True)
Forms
class forms_user (forms.ModelForm):
class Meta:
model = items
fields = '__all__'
HTML
<form id="contact" action="" method="post" enctype="multipart/form-data">
<fieldset>
<label for="file">Seu arquivo</label>
{% render_field form.image type="file" id="file" name="myfiles[]" %}
</fieldset>
</form>
Here in the forms I just put the form and the IMG field so it doesn't get too big but the other fields I put everything right.
At first there's a typo in model field titulo it should be = not :.
Secondly, you should always return an HttpResponseRedirect after dealing with POST data, the tip is not specific to Django, it's a good web practice in general, so use following view:
def criar(request):
if request.method == 'GET':
return render(request, 'create.html', {'form': forms_user()})
else:
form = forms_user(request.POST, request.FILES )
if form.is_valid():
form.save()
messages.add_message(request, constants.SUCCESS, 'Cadastro realizado com sucesso.')
return redirect("success")
else:
print(form.errors)
messages.add_message(request, constants.ERROR, f'{form.errors}')
return render(request, 'create.html', {'form': forms_user()})
If you have created modelform then render image field as below, and you can also remove the action attribute as Django by default takes current page route.
Html:
<form id="contact" method="POST" enctype="multipart/form-data">
<fieldset>
<label for="file">Seu arquivo</label>
{{form.image}}
</fieldset>
</form>
urls.py
urlpatterns=[
path("success/", views.success, name="success")
...
]
success.html:
<body>
<h1> The form has been successfully submitted </h1>
</body>
I am following the guide to create comment given by Django central, https://djangocentral.com/creating-comments-system-with-django/ and it is working. However I am using the {{ form.as_p }} Which will give 3 fields, as the form say, with name, email and the body. But i wanted to have predefined name, which would be your username you are logged inn with and the email attached to that account. How would i go ahead to create that?
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['name', 'email', 'body']
models.py
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
email = models.EmailField()
body = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-date_added']
def __str__(self):
return self.name
views.py
def post_detail(request, category_slug, slug, status=Post.ACTIVE):
post = get_object_or_404(Post, slug=slug)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail', category_slug=category_slug, slug=slug)
else:
form = CommentForm()
return render(request, 'blog/post_detail.html', {'post': post, 'form': form})
in the html template
{% if user.is_authenticated %}
<h2 class="subtitle is-4">Comments</h2>
<form method="post" class="mb-6">
{% csrf_token %}
{{ form.as_p }}
<div class="field">
<div class="control">
<button class="button is-success">Submit comment</button>
</div>
</div>
</form>
{% endif %}
If you want to pre-set the username and email fields, you can use the initial form parameters like this:
views.py
def post_detail(request, category_slug, slug, status=Post.ACTIVE):
post = get_object_or_404(Post, slug=slug)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail', category_slug=category_slug, slug=slug)
else:
user = request.user
form = CommentForm(initial={"name": user.username, "email": user.email})
return render(request, 'blog/post_detail.html', {'post': post, 'form': form})
forms.py
class CommentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].disabled = True
self.fields['email'].disabled = True
# OR set readonly widget attribute.
# self.fields['name'].widget.attrs['readonly'] = True
# self.fields['email'].widget.attrs['readonly'] = True
class Meta:
model = Comment
fields = ['name', 'email', 'body']
This is function for updating user's info.
views.py
def UpdateProfile(request):
context = {}
user = request.User
if not user.is_authenticated:
return redirect('login')
if request.POST:
form = PersonalInfo(request.POST, instance=user)
if form.is_valid():
obj = form.Save(commit=False)
user = user.id
obj.user = user
obj.save()
return redirect('profile')
else:
#messages.error(request, ('Please correct the error below.'))
context['personal_form'] = form
else:
form = PersonalInfo(instance=user)
context['personal_form'] = form
return render(request, 'admission/signup.html', context)
This is the model I have created for storing user info.
models.py:
class ApplicantInfo(models.Model):
infield = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
profile_pic = models.ImageField(upload_to='media/', blank= True, null= True)
father_name = models.CharField(max_length=30)
user = models.OneToOneField(User, on_delete=models.CASCADE)
This is the form class I have created.
forms.py:
from .models import Applicant, ApplicantInfo
from django import forms
class PersonalInfo(forms.ModelForm):
class Meta:
model = ProfileInfo
fields = [
'first_name',
'last_name',
'profile_pic',
#'date_birth',
'father_name',
'street_adr',
'city',
'zip_code',
]
This is the frontend template which I have created, this is working fine.
Template
{%block content%}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form method="POST">
{% csrf_token %}
{% for field in personal_form %}
<p>
{{field.label_tag}}
{{field}}
{% if field.help_text %}
<small style="color:gray">{{field.help_text}}</small>
{% endif %}
</p>
{% endfor %}
{% for field in personal_form %}
<p>
{% for error in field.errors %}
<p style="color:red">{{error}}</p>
{% endfor %}
</p>
{% endfor %}
<button type="submit">Submit</button>
</form>
</body>
</html>
{% endblock content %}
The app has been able to load the form without any trouble but it just not throwing data to the backend.
Updated function for UpdateProfile
views.py
def UpdateProfile(request, id=None):
context = {}
user_obj = request.user
if not user_obj.is_authenticated:
return redirect('login')
if request.method == "POST":
form = PersonalInfo(request.POST)
if form.is_valid():
obj = form.save()
user_id = Applicant.objects.filter(app_id = user_obj.app_id).first()
obj.user = user_id
obj.save()
return redirect('profile')
else:
#messages.error(request, ('Please correct the error below.'))
context['personal_form'] = form
elif request.method == 'GET':
form = PersonalInfo(instance=user_obj)
context['personal_form'] = form
return render(request, 'admission/signup.html', context)
Updated code for forms method, only add #def cleaned_data function
forms.py
class PersonalInfo( forms.ModelForm):
class Meta:
model = ProfileInfo
fields = [
'first_name',
'last_name',
'profile_pic',
#'date_birth',
'father_name',
'street_adr',
'city',
'zip_code',
]
def clean(self):
if self.is_valid():
first_name = self.cleaned_data['first_name']
last_name = self.cleaned_data['last_name']
father_name = self.cleaned_data['father_name']
street_adr = self.cleaned_data['street_adr']
city = self.cleaned_data['city']
zip_code = self.cleaned_data['zip_code']
And model does not need to be change, you have choice either to add and autofield(PrimaryKey) or use the default one
The problem was in view.py where i just removed instance attribute from the form object, then I called user_id from user model which is in this case #Applicant model, then assigned to the obj object and saved obj.
Thanks to all of you who has spent precious time in this problem.
Cheers!!!
I am new to django, I created a form to save Data into my database but it not working corectly, I got no error but data is not sent in database. Thanks for helping!
views.py
#login_required()
def data(request):
if request.POST == "POST":
form = CreatePost(request.POST)
if form.is_valid():
form.instance.author = request.user
form.save()
return redirect(data)
else:
form = CreatePost()
context = {
"form": form
}
return render(request, "sms/data.html", context)
forms.py
class CreatePost(forms.ModelForm):
class Meta:
model = Post
fields = ["title", "content"]
models.py
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
data.html
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
<pre></pre>
<button class="btn btn-outline-info" type="submit" value="Submit">Data</button>
</form>
try like this
#login_required()
def data(self, request):
if request.method == "POST": #this line
form = CreatePost(request.POST)
if form.is_valid():
post = form.save(commit=False) #new line
post.author = self.request.user #this line
post.save() #this line
return redirect(data)
else:
form = CreatePost()
context = {
"form": form
}
return render(request, "sms/data.html", context)
if request.POST == "POST":
Should instead be:
if request.method == 'POST':
My application has a form which requires me to pre-fill certain values in form fields using information extracted from a user's Twitter account after a successful login. Here's what my form looks like after the user has successfully logged in from his/her Twitter account (the 'Name' field is pre-filled with the full name associated with the user's twitter account):
models.py
from django.db import models
from django.core.validators import RegexValidator
from django.contrib.auth.models import User
class Evangelized(models.Model):
full_name = models.CharField(max_length=128)
email = models.EmailField()
mobile_no = models.CharField(unique=True, max_length = 10, validators=[RegexValidator(regex='^\w{10}$', message='Mobile number should be strictly of 10 digits.')])
twitter_url = models.CharField(unique=True, max_length=128)
GENDER_CHOICES = (('M', 'Male'), ('F', 'Female'), ('U', 'Unisex/Parody'))
gender = models.CharField(choices=GENDER_CHOICES, max_length = 128)
HTML
<form id="evangelized_form" method="post" action="/rango/fillform/">
NAME: <input type = "text" name = "name" value = "{{user.get_full_name}}"><br>
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
<b>{{ field.help_text }}</b><br>
{{ field }}<br><br>
{% endfor %}
<input type="submit" name="submit" value="Submit" />
</form>
forms.py
class EvangelizedForm(forms.ModelForm):
#full_name = forms.CharField(help_text="Full Name")
email = forms.CharField(help_text="Email ID")
mobile_no = forms.CharField(help_text="Mobile number")
twitter_url = forms.CharField(help_text="Twitter URL")
gender = forms.CharField(widget=forms.RadioSelect(
choices=Evangelized.GENDER_CHOICES), help_text="Gender", max_length = 128)
Note that I have included the full_name attribute in my models.py, but have excluded it from forms.py. I have included the Name field in my HTMl page instead as follows:
NAME: <input type = "text" name = "name" value = "{{user.get_full_name}}"><br>
Thus, value = "{{user.get_full_name}}" pre-fills the Name field in the form.
views.py
def fillform(request):
if request.method == 'POST':
form = EvangelizedForm(request.POST)
if form.is_valid():
form.full_name = request.POST['name']
form.save(commit=True)
return index(request)
else:
form.errors
else:
form = EvangelizedForm()
context = RequestContext(request,
{'request': request,
'user': request.user, 'form':form})
#return render(request, 'rango/fillform.html', {'form': form, 'context_instance':context})
return render_to_response('rango/fillform.html',
context_instance=context)
Now, I want the Name field value to be stored in the database just like all other form field values. However, except the full_name attribute, all other form attributes get stored in the database on submitting the form.
I think I'm not catching the Name form field value from my HTML page in my view properly. Any solutions?
EDIT 1:
Based on the suggestions of a commenter, I made the following changes in views.py:
def fillform(request):
if request.method == 'POST':
form = EvangelizedForm(request.POST)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
form.errors
else:
#form = EvangelizedForm()
form = EvangelizedForm(initial={'full_name': request.user.get_full_name()})
context = RequestContext(request,
{'request': request,
'user': request.user, 'form':form})
#return render(request, 'rango/fillform.html', {'form': form, 'context_instance':context})
return render_to_response('rango/fillform.html',
context_instance=context)
However, I'm now getting the following error:
'WSGIRequest' object has no attribute 'get_full_name'
What seems to be wrong here?