django ModelForm extra field - python

i will like to have extra field in modelForm. From this extra field i will like to pass the value to field in model when save. this is example what i want to get
will like to generate name in random name field, and save to database as name
models.py
from django.db import models
class Test2App(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
forms.py
from django import forms
from .models import test2App
class TestForm(forms.ModelForm):
class Meta:
model = Test2App
fields = ['name']
Views.py
def add_name(request):
if request.method == 'POST':
form = TestForm(request.POST)
if form.is_valid():
form.save()
return redirect('test_name')
else:
form = TestForm()
return render(request, 'test/add.html', {'form': form})
html
<form method="post">
{% csrf_token %}
<label for="name">Random Name</label>
<button>Generate</button>
<input id="name" name="name_test">
{{ form}}
<input type="submit" value="Submit">
</form>

def add_name(request):
if request.method == 'POST':
form = TestForm(request.POST)
name1 = request.POST.get('name_test')
print(name1)
if form.is_valid():
form.instance.name = name1
form.save()
return redirect('test_name')
else:
form = TestForm()
return render(request, 'test/add.html', {'form': form})

Related

Django dose not validate form

I have form with the name of CommentForm when the form is validated it has to return HttpResponse which is saying that the form is valid if does nothing
views.py
def comment(request,pk):
blog = BlogPost.objects.get(pk=pk)
comment = CommentForm()
if request.method == "POST":
comment = CommentForm(request.POST or None)
if comment.is_valid():
return HttpResponse('this is request method')
context = {
'blog':blog,
'comment':comment,
}
return render(request, 'blog/comment.html', context)
froms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = '__all__'
models.py
class Comment(models.Model):
blog = models.ForeignKey('BlogPost', on_delete = models.CASCADE)
text = models.TextField()
template
{% extends 'base.html' %}
{% block content %}
{{blog.title}}
<form method="POST" action="">
{% csrf_token %}
{{comment.text}}
<input type="submit">
<form>
{% endblock %}
I used class meta in my forms.py I removed class meta and I save comments to model while instantiating it in view.py.
form.py
class CommentForm(forms.Form):
text = forms.CharField(widget=forms.Textarea())
view.py
def comment(request,pk):
blog = BlogPost.objects.get(id=pk)
form = CommentForm()
if request.method=='POST':
form = CommentForm(request.POST)
if form.is_valid():
comments = Comment(
text = form.cleaned_data['text'],
blog =blog
)
comments.save()
return redirect('/blog')
else:
context = {'blog':blog,
'form':form}
return render(request, 'blog/comment.html', context)

Django form does not save new post using based view function

I have a model as follow:
class Post(models.Model):
title = models.CharField(max_length=150)
author = models.ForeignKey(User, on_delete=models.CASCADE)
date_posted = models.DateTimeField(default=timezone.now)
imagefile = models.FileField(null=True, blank=True, upload_to='images', default='default.jpg')
There is a bug in the view file that, when I use class base view I can post the new post but whenever I use it as a function it does not save the form.
This one works(saves post in database):
class PostCreateView(LoginRequiredMixin, AjaxFormMixin, CreateView):
model = Post
template_name = "app/postform.html"
success_url = '/posts'
form_class = postform
But this one does not(does not save post in database):
#login_required
def PostCreateView(request):
if request.method == 'POST':
mform = postform(request.POST or None, request.FILES or None, instance=request.user)
if mform.is_valid():
mform.save() # when I print something here, Ill see something
messages.success(request, f'Yes!')
return redirect('posts')
else:
mform = postform()
return render(request, 'myapplication/postform.html', {'form': mform})
and in postform.html:
<form method="POST" action="" enctype="multipart/form-data">
<fieldset class="form-group">
{% csrf_token %}
<div class="content-section">
<!-- {{ form|crispy }} -->
</div>
</fieldset>
</form>
and form.py:
class postform(forms.ModelForm):
class Meta:
model = Post
fields = ("__all__")
exclude = ['date_posted']
I think the problem is that you form's model is post and you're assigning object of user as instance.
So try this way:
#login_required
def PostCreateView(request):
if request.method == 'POST':
mform = postform(request.POST or None, request.FILES or None)
if mform.is_valid():
post = mform.save(commit=False)
post.author = request.user
post.save()
messages.success(request, f'Yes!')
return redirect('posts')
else:
mform = postform()
return render(request, 'myapplication/postform.html', {'form': mform})

Unique=True in Django model gives IntergretyError instead of ValidationError

I want to show a validation message like "This email is already in use" inside my html form.
But I think i'm missing something. I keep getting an IntegrityError at my email field. Isn't Django supposed to validate this and give an ValidationError if I use unique=True in my model? Or do I have to Try and Catch the IntegrityError myself?
Or maybe show me a best practice for validating unique users inside a form/model.
models.py
class Customer(models.Model):
FirstName = models.CharField(max_length=50)
LastName = models.CharField(max_length=50)
Email = models.CharField(max_length=50, unique=True, error_messages={'unique':"This email is already in use"})
views.py
def customerform(request):
if request.method == 'POST':
form = CustomerForm(request.POST)
if form.is_valid():
post = Customer()
post.FirstName = form.cleaned_data['FirstName']
post.LastName = form.cleaned_data['LastName']
post.Email = form.cleaned_data['Email']
post.save()
return render(request, 'results.html', {
'FirstName': form.cleaned_data['FirstName'],
'Email': form.cleaned_data['Email'],})
else:
form = CustomerForm()
return render(request, 'form.html', {'form':form})
forms.py
class CustomerForm(forms.Form):
FirstName = forms.CharField (label='First name:', max_length=50)
LastName = forms.CharField (label='Last name:', max_length=50)
Email = forms.EmailField(label='Email:', max_length=50)
form.html
<form action="/customer/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
If you want form validation to automatically use the model attributes, you have to use a ModelForm:
class CustomerForm(forms.ModelForm):
class Meta:
model = Customer
fields = ["FirstName", "LastName", "Email"]
If you want to use a regular Form, you need to do the validation manually.
def customerform(request):
if request.method == 'POST':
form = CustomerForm(request.POST)
if form.is_valid():
# first we check if email is valid
customer = Customer.objects.filter(Email = form.cleaned_data['Email'])
if customer.count() == 0: # email not in use
post = Customer()
post.FirstName = form.cleaned_data['FirstName']
post.LastName = form.cleaned_data['LastName']
post.Email = form.cleaned_data['Email']
post.save()
return render(request, 'results.html', {
'FirstName': form.cleaned_data['FirstName'],
'Email': form.cleaned_data['Email'],})
else: # email in use so we redirect to html and we add an error message
render(request, 'form.html', {'form':form,'error','This email is already in use'})
else:
form = CustomerForm()
return render(request, 'form.html', {'form':form})
<form action="/customer/" method="post">
{% if error %}
<b> {{ error }} </b> <br>
{% endif %}
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>

How to populate(get the data filled) the modelform with the user data?

This is my models.py.
from django.db import models
from django.contrib.auth.models import User
class User_data(models.Model):
user_ID = models.CharField(max_length = 20)
name = models.CharField(max_length = 50)
user = models.ForeignKey(User, on_delete = models.CASCADE, null =True)
def __str__(self):
return self.name
This is my forms.py
from django import forms
from lrequests.models import User_data
class UserForm(forms.ModelForm):
class Meta:
fields = ("name", "user_ID")
model = User_data
This is my views.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import UserForm
from django.shortcuts import render_to_response
from .models import User_data
def get(request):
form_class = UserForm
if request.method == "POST":
form = UserForm(request.POST)
if form.is_valid():
data = form.save(commit = False)
data.user = request.user
form.save()
return HttpResponse("Sucessfully submitted")
else:
form = UserForm()
return render(request, "request_form.html", {'form' : form_class})
#update
def auto_fill_form(request):
form = UserForm(initial = dict(name = request.user.first_name))
context = dict(form=form)
return render(request, "request_form.html", context)
Now, I've tried populating the user data, which was specified whilst creating account. So, that he(user) doesn't tamper the data (as it need to read-only) and it is automatically filled without the user giving the input. I've read django documentation but it specifies only dynamically initialising data
see here. I've tried putting that code in the forms.py, but it didn't work.
I've even tried in the HTML template, that didn't work too.
{% csrf_token %}
<div class="form-row">
{{ form.name.errors }}
{{ form.name.label_tag }} {{ form.name = user.first_name }}
</div>
{% comment %} {{ form.as_p }} {% endcomment %}
How do I get data by default into the form?
Can someone help me on this?
Just replace
else:
form = UserForm()
return render(request, "request_form.html", {'form' : form_class})
by:
else:
return auto_fill_form(request)

Django: ModelForms: ImageField is always empty and rejected by ModelForm

I created a form based on several ModelForm elements. All fields work fine excluding the
ImageField. Due to the missing ImageField form.is_valid() always returns False - even though I pass request.FILES to form.
Why the form with the ImageField is always invalid / empty?
Forms
class UserProfileForm2(forms.ModelForm):
class Meta:
model = models.UserProfile
fields = ['description', 'picture']
class LocationForm(forms.ModelForm):
class Meta:
model = models.Location
fields = ['city', 'state', 'country']
class UserForm(forms.ModelForm):
class Meta:
model = registration_models.User
fields = ['first_name', 'last_name']
Models
class Location(models.Model):
city = models.CharField(max_length=100)
state = models.CharField(max_length=100)
country = models.CharField(max_length=100)
def __unicode__(self):
return ' - '.join([self.city, self.state, self.country])
class UserProfile(models.Model):
authenticationuser = fields.AutoOneToOneField(AuthUser)
description = models.TextField()
picture = models.ImageField(upload_to='uploaded_files/', null=True)
location = models.ForeignKey(Location, null=True)
appear_in_public_ranking = models.BooleanField(default=True)
def __unicode__(self):
return self.authenticationuser.username
View
#login_required
def changeprofile(request):
form = None
# user posted his new profile settings
if request.method == 'POST':
user_form = myforms.UserForm(request.POST)
user_profile_form = myforms.UserProfileForm2(request.POST, request.FILES)
location_form = myforms.LocationForm(request.POST)
forms_are_invalid = not (user_form.is_valid() and user_profile_form.is_valid() and not location_form.is_valid())
if forms_are_invalid:
forms = {'user_form':user_form,
'user_profile_form':user_profile_form,
'location_form':location_form}
return shortcuts.render(request, 'changeprofile.html', forms)
location_form.save()
user_form.save()
user_profile_form.save()
return HttpResponseRedirect('/profile')
else:
forms = {'user_form':user_form,
'user_profile_form':user_profile_form,
'location_form':location_form}
return shortcuts.render(request, 'changeprofile.html', forms)
Template
<form action="{% url 'changeprofile' %}" method="post">
{% csrf_token %}
{{ user_form }}
{{ location_form }}
{{ user_profile_form }}
<input type="submit" value="Submit" />
</form>
If your form contains file input then you must set enctype in your form as:
<form action="{% url 'changeprofile' %}" method="post" enctype="multipart/form-data">
Otherwise request.FILES will always be empty.

Categories