Django - Dealing With Integrity Error And Showing Error Pop up - python

I have my model.py file as below. I've created a conjugate primary key date & station.
Models.py
from django.db import models
from django import forms
# Create your models here.
from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
# Create your models here.
class ManHour(models.Model):
class Meta:
unique_together = (('date', 'station'),)
station_choices = (
('KHI','Station1'),
('ISB', 'Station2'),
('LHE','Station3'),
)
station = models.CharField(
max_length=3,
choices=station_choices,
)
date = models.DateField()
date_time = models.DateTimeField(auto_now=True)
imports_airside = models.DecimalField(max_digits= 5, decimal_places= 3, default = 0)
imports_landside = models.DecimalField(max_digits= 5, decimal_places= 3, default = 0)
exports = models.DecimalField(max_digits= 5, decimal_places= 3, default = 0)
Form.py
from django import forms
from manhourapp.models import ManHour
from datetime import date
class DateInput(forms.DateInput):
input_type = 'date'
class InputForm(forms.ModelForm):
class Meta:
model = ManHour
fields = ['date','station', 'imports_airside', 'imports_landside', 'exports']
widgets = {
'date':forms.widgets.DateInput(attrs={'type': 'date', 'max':str(date.today())})
}
Views.py
def form_page(request):
context = {}
try:
man_hour = ManHour.objects.get(pk=request.GET.get("pk"))
except ManHour.DoesNotExist:
man_hour = None
if man_hour:
context["Total_Imports"] = man_hour.imports_airside + man_hour.imports_landside
if man_hour:
context["Total_Hours"] = man_hour.imports_airside + man_hour.imports_landside + man_hour.exports
if request.method == 'POST':
properties_Form = InputForm(request.POST, instance=man_hour)
if properties_Form.is_valid():
obj = properties_Form.save()
return redirect("%s?pk=%s" % (reverse('form'), obj.pk))
else:
context['form']= InputForm(instance=man_hour)
return render(request, "form.html", context)
HTML
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" async></script>
</head>
<body>
<form target="upload_frame" action="." method="post" enctype="multipart/form-data" >
{% csrf_token %}
{{ form.as_p }}<br>
<input type="text" name="Total_Imports" value="{{ Total_Imports }}" class="form-control" disabled><br>
<input type="text" name="Total_Hours" value="{{ Total_Hours }}" class="form-control" disabled><br>
<input type="submit" name="submit" value="Upload" id="submit">
<div class="user_panel">
logout
</div>
</form>
</body>
</html>
I am new to Django and I want to understand how can I show a pop up that would tell user that record already exists on this date and station.
I need to understand how can I add an exception handling and show pop up to user?
I've tried to add exception handling using code below but it is not working.
try:
if request.method == 'POST':
properties_Form = InputForm(request.POST, instance=man_hour)
if properties_Form.is_valid():
obj = properties_Form.save()
return redirect("%s?pk=%s" % (reverse('form'), obj.pk))
except IntegrityError as e:
error_message = e.__cause__
print(error_message)

A Form class in Django will perform validation and cleaning for you. It will not raise errors but catch them itself so using a try-except does not make much sense as the form itself has caught the error.
Instead you just need to return a response in case .is_valid() returns False. Furthermore the form itself will render the errors to display it to the user when you render it so you should simply render the same page again:
if request.method == 'POST':
properties_Form = InputForm(request.POST, instance=man_hour)
if properties_Form.is_valid():
obj = properties_Form.save()
return redirect("%s?pk=%s" % (reverse('form'), obj.pk))
context['form'] = properties_Form
return render(request, "form.html", context) # form was not valid so returning a response here
If you want to customize the error message that is generated you can do it by setting the error_messages attribute on the Meta class of the form (See Considerations regarding model’s error_messages [Django docs]):
from django.core.exceptions import NON_FIELD_ERRORS
class InputForm(forms.ModelForm):
class Meta:
model = ManHour
fields = ['date','station', 'imports_airside', 'imports_landside', 'exports']
widgets = {
'date':forms.widgets.DateInput(attrs={'type': 'date', 'max':str(date.today())})
}
error_messages = {
NON_FIELD_ERRORS: {
'unique_together': "%(model_name)s's %(field_labels)s are not unique.",
}
}

Related

how I can insert and update (edit) latitude and long using (form.py) python Django

I want to insert latitude and long using python Django. I use code but does not work when click on the button it shows null in DB.
models.py
class UserLocation(models.Model):
map_id = models.AutoField(primary_key=True)
map_u_address = models.CharField(max_length=250, null=True)
latitude = models.DecimalField(max_digits=11, decimal_places=7, null=False, blank=True)
longitude = models.DecimalField(max_digits=11, decimal_places=7, null=False, blank=True)
view.py
def save_location(request):
if request.method == 'POST':
form = request.POST
latitude = form.get('latitude')
longitude = form.get('longitude')
user_id = request.session['user_id']
insert_data = UserLocation.objects.create( latitude=latitude,longitude=longitude,
)
if insert_data:
json_data = {'msg': "Insert data successfully", 'state_val': 1}
return JsonResponse(json_data)
else:
json_data = {'msg': "Data not saved", 'state_val': 2}
return JsonResponse(json_data)
else:
return render(request, 'map_1.html')
how I can do an update (edit) for latitude and long using (form.py) python Django?
In forms.py
from django.forms import ModelForm
# Import your UserLocation model
from .models import UserLocation
# Create your forms here
class UserLocationForm(ModelForm):
class Meta:
model = UserLocation
fields = ('latitude', 'longitude')
In views.py
from .forms import UserLocationForm
def save_location(request):
form = UserLocationForm()
context = {}
context['form'] = form
if request.method == 'POST':
form = UserLocationForm(request.POST)
user_id = request.session['user_id']
if form.is_valid():
insert_data = form.save()
if insert_data:
json_data = {'msg': "Insert data successfully", 'state_val': 1}
return JsonResponse(json_data)
else:
json_data = {'msg': "Data not saved", 'state_val': 2}
return JsonResponse(json_data)
else:
# Update form in context dictionary
context['form'] = form
# Re-render page with prefilled data
return render(request, 'map_1.html', context)
else:
return render(request, 'map_1.html', context)
In template
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit">
</form>
For Updating location
In views.py
def update_location(request, location_id):
try:
# Get location from db for location_id
location = UserLocation.objects.get(id=location_id)
except UserLocation.DoesNotExist:
return # redirect user back as the location id is invalid
# Populate the form with data of requested instance
form = UserLocationForm(instance=location)
context = {}
context['form'] = form
if request.method == 'POST':
form = UserLocationForm(request.POST)
user_id = request.session['user_id']
if form.is_valid():
form.save()
return # Redirect user to somewhere
# When the posted data is invalid
else:
# Update form in context dictionary
context['form'] = form
# Re-render page with prefilled data
return render(request, 'update_location.html', context)
else:
return render(request, 'update_location.html', context)
In update_location.html
{% block body %}
<div class="container-fluid">
<form method="POST" action="">
{% csrf_token %}
{{ form }}
<input type="submit" value="Upload" class="btn btn-primary">
</form>
</div>
{% endblock body %}
In urls.py
path('update_location/<int:location_id>/', views.update_location, name="update-location"),

How to Update ImageField in Django?

i am new in Django. i am having issue in updating ImageField.i have following code
in models.py
class ImageModel(models.Model):
image_name = models.CharField(max_length=50)
image_color = models.CharField(max_length=50)
image_document = models.ImageField(upload_to='product/')
-This is My forms.py
class ImageForm(forms.ModelForm):
class Meta:
model = ImageModel
fields = ['image_name', 'image_color' , 'image_document']
in Html file (editproduct.html)
<form method="POST" action="/myapp/updateimage/{{ singleimagedata.id }}">
{% csrf_token %}
<input class="form-control" type="text" name="image_name" value="{{ singleimagedata.image_name}}">
<input class="form-control" type="file" name="image_document">
<button type="submit" class="btn btn-primary">UPDATE PRODUCT</button>
</form>
-myapp is my application name. {{singleimagedata}} is a Variable Containing all fetched Data
-urls.py
urlpatterns = [
path('productlist', views.productlist, name='productlist'),
path('addproduct', views.addproduct, name='addproduct'),
path('editimage/<int:id>', views.editimage, name='editimage'),
path('updateimage/<int:id>', views.updateimage, name='updateimage'),
]
and Here is My views.py
def productlist(request):
if request.method == 'GET':
imagedata = ImageModel.objects.all()
return render(request,"product/productlist.html",{'imagedata':imagedata})
def addproduct(request):
if request.method == 'POST':
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.add_message(request, messages.SUCCESS, 'Image Uploaded')
return redirect('/myapp/productlist')
else:
imageform = ImageForm()
return render(request, "product/addproduct.html", {'imageform': imageform})
def editimage(request, id):
singleimagedata = ImageModel.objects.get(id=id)
return render(request, 'product/editproduct.html', {'singleimagedata': singleimagedata})
def updateimage(request, id): #this function is called when update data
data = ImageModel.objects.get(id=id)
form = ImageForm(request.POST,request.FILES,instance = data)
if form.is_valid():
form.save()
return redirect("/myapp/productlist")
else:
return render(request, 'demo/editproduct.html', {'singleimagedata': data})
My image Upload is working fine.i can not Update image while updating data.rest of the data are updated.i don't know how to update image and how to remove old image and put new image into directory.
I think you missed the enctype="multipart/form-data", try to change:
<form method="POST" action="/myapp/updateimage/{{ singleimagedata.id }}">
into;
<form method="POST" enctype="multipart/form-data" action="{% url 'updateimage' id=singleimagedata.id %}">
Don't miss also to add the image_color field to your html input.
Because, in your case the image_color field model is designed as required field.
To remove & update the old image file from directory;
import os
from django.conf import settings
# your imported module...
def updateimage(request, id): #this function is called when update data
old_image = ImageModel.objects.get(id=id)
form = ImageForm(request.POST, request.FILES, instance=old_image)
if form.is_valid():
# deleting old uploaded image.
image_path = old_image.image_document.path
if os.path.exists(image_path):
os.remove(image_path)
# the `form.save` will also update your newest image & path.
form.save()
return redirect("/myapp/productlist")
else:
context = {'singleimagedata': old_image, 'form': form}
return render(request, 'demo/editproduct.html', context)
I had a similar issue while updating the profile_pic of user. I solved this with the following code I think this might help:
Models.py
class Profile(models.Model):
# setting o2o field of user with User model
user_name = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True)
first_name = models.CharField(max_length=70, null=True, blank=True)
last_name = models.CharField(max_length=70, null=True, blank=True)
profile_pic = models.ImageField(upload_to="images", blank=True, null=True,)
def __str__(self):
return str(self.user_name)
forms.py
class ProfileEditForm(ModelForm):
class Meta:
model = Profile
fields = '__all__'
# excluding user_name as it is a one_to_one relationship with User model
exclude = ['user_name']
views.py
#login_required(login_url='login')
def edit_profile(request, id):
username = get_object_or_404(Profile, id=id)
extended_pro_edit_form = ProfileEditForm(instance=username)
if request.method == "POST":
extended_pro_edit_form = ProfileEditForm(request.POST, request.FILES, instance=username)
if extended_pro_edit_form.is_valid():
extended_pro_edit_form.save()
next_ = request.POST.get('next', '/')
return HttpResponseRedirect(next_)
context = {'extended_pro_edit_form': extended_pro_edit_form}
return render(request, 'edit_profile.html', context)
edit-profile.html
<form action="" method="post"
enctype="multipart/form-data">
{% csrf_token %}
{{ extended_pro_edit_form.as_p }}
{{ extended_pro_edit_form.errors }}
<!--To redirect user to prvious page after post req-->
<input type="hidden" name="next" value="{{ request.GET.next }}">
<button type="submit">UPDATE</button>
</form>
Answer from #binpy should solve your problem. In addition to your second answer, you could do:
def updateimage(request, id): #this function is called when update data
data = ImageModel.objects.get(id=id)
form = ImageForm(request.POST,request.FILES,instance = data)
if form.is_valid():
data.image_document.delete() # This will delete your old image
form.save()
return redirect("/myapp/productlist")
else:
return render(request, 'demo/editproduct.html', {'singleimagedata': data})
Check delete() method on django docs.
some times something like cached old image is not replaced in the front-end so you might just need to forces refresh by pressing CTRL + F5 or clear your browsing history.
the answer given by #binpy is a needed update so that the files are passed to the back-end.

Two forms in one view Django

I'm a beginner in django and I want to put two diferent registers in the same view. But also I want to make my own forms and put diferent url at the action tag. I did it in one form, but when I puy the second form, this doesn't work.
This is my models.py:
from django.db import models
class userProfile(models.Model):
usermail = models.CharField(max_length=264)
username = models.CharField(max_length=264)
userpass = models.CharField(max_length=264)
class companyProfile(models.Model):
companymail = models.CharField(max_length=264)
companyname = models.CharField(max_length=264)
companypass = models.CharField(max_length=264)
This is my forms.py:
from django import forms
from Pruebas_app.models import companyProfile, userProfile
class registerCompany(forms.Form):
companypassconf = forms.CharField()
class Meta():
model = companyProfile
fields = ['companymail','companyname', 'companypass']
labels = {'companymail': '', 'companyname': '', }
widgets = { 'companypass': forms.PasswordInput(),}
class registerUser(forms.Form):
userpassconf = forms.CharField()
class Meta():
model = companyProfile
fields = ['usermail','username', 'userpass']
labels = {'usermail': '', 'username': '', }
widgets = {'userpass': forms.PasswordInput(),}
And this is my template:
<form action="{ url 'user_register'}" method="post">
<input type="text" name="username">
<input type="email" name="usermail">
<input type="password" name="userpass">
<input type="password" name="userpassconf">
<input type="submit" value="Register">
</form>
<form action="{ url 'company_register'}" method="post">
<input type="text" name="companyname">
<input type="email" name="companymail">
<input type="password" name="companypass">
<input type="password" name="companypassconf">
<input type="submit" value="Register">
</form>
And this is my views.py:
from django.shortcuts import render
from Pruebas import forms
from Pruebas.forms import registerCompany, registerUser
from django.http import HttpResponse
def user_register(request):
form = forms.registerUser()
regd = False
passmatch = True
if request.method == "POST":
form = registerUser(request.POST)
if form.is_valid():
form_data = form.cleaned_data
print (form_data.get("userpass"))
if form_data.get("userpass") == form_data.get("userpassconf"):
passmatch = True
form.save()
regd = True
print("saved")
else:
passmatch = False
else:
print("error")
red = 'Pruebas/register.html'
regd = False
return render(request, 'Pruebas/register.html', {'registered': regd, "matchPass": passmatch})
I tried to send the data from my forms to one unique view, but I only can recive the data from the user register. I don't know what I was doing wrong or what I have to do to make this works, please help!
In your forms, don't define meta class and just display the fields like you're doing with the userpassconf. You can even combine the forms into a single form, and then just handle the data in your view like you're already doing, but create two instances. Something like:
if request.method == "POST":
form = registerUser(request.POST)
if form.is_valid():
form_data = form.cleaned_data
if form_data.get("userpass") == form_data.get("userpassconf"):
passmatch = True
new_user = userProfile()
new_user.usermail = form_data.get("usermail")
new_user.username = form_data.get("username")
new_user.save()
So basically you're just creating an instance of whatever model you want to save to, and assigning the form data to it, and then saving it. And don't forget to import your models into the views file.

Django/Python: form data doesn't get stored in database

Django 1.8 / Python 3.4
I wanna add data from an html-form via a Django view named "add" to my database. However, for some reason this just doesn't happen and I can't figure out what's wrong. Presumably the mistake is in the view's code, but what exactly do I need to change?
models.py
from django.db import models
from model_utils import Choices
class Entry(models.Model):
user = models.CharField(max_length=50)
title = models.CharField(max_length=200)
description = models.TextField()
due_date = models.DateField('Date')
due_time = models.TimeField('Time')
STATUS = Choices('Open', 'Done')
status = models.CharField(choices=STATUS, default=STATUS.Open, max_length=4)
def __unicode__(self):
return u"%s %s %s %s %s" % (self.user, self.title, self.description, self.expiry, self.status)
def expiry(self):
return u"%s %s" % (self.due_date, self.due_time)
The interesting part of my add.html
<td><input type="text" name="title"></td>
<td><input type="text" name="description"></td>
<td><input type="text" name="due_date"></td>
<td><input type="text" name="due_time"></td>
<td>
<select name="status" size="1" selected value="Open">
<option>Open</option>
<option>Done</option>
</select>
</td>
forms.py
from django import forms
from django.forms.widgets import TextInput
class EntryForm(forms.Form):
title = forms.CharField(max_length=200)
description = forms.widgets.TextInput()
due_date = forms.DateField()
due_time = forms.TimeField()
status = forms.ChoiceField(choices=[(x, x) for x in range(1, 2)])
And the relevant view in my views.py
from django import forms
from django.shortcuts import render
from django.shortcuts import redirect
from website.list.forms import EntryForm
def add(request):
if request.method == "POST":
form = EntryForm(request.POST)
if form.is_valid():
new_entry = form.save()
new_entry.save()
return redirect('website')
else:
form = EntryForm()
return render(request,'add.html', {'form': form})
Any help is appreciated!
[EDIT]
So, this is what my add.html looks like now:
<form action="." method="post">
{% csrf_token %}
{{ form }}
<br><input type="submit" value="Send"/>
<br><br>Cancel
</form>
And the slightly edited views.py again:
from django import forms
from django.shortcuts import render
from django.shortcuts import redirect
from www.todolist.forms import EntryForm
from django.contrib.auth.models import User
def add(request):
if request.method == "POST":
form = EntryForm(request.POST)
if form.is_valid())
form.save()
return redirect('website')
else:
form = EntryForm()
return render(request,'add.html', {'form': form})
Figured it out ...
This is what forms.py has to look like in order for the save() function to work in the view:
class EntryForm(forms.ModelForm):
CHOICES = (
('1', 'Open'),
('2', 'Done'),
)
title = forms.CharField(max_length=200)
description = forms.CharField(widget=forms.Textarea)
due_date = forms.DateField()
due_time = forms.TimeField()
status = forms.ChoiceField(choices=CHOICES)
class Meta:
model = Entry
fields = '__all__'
The important things to notice are "ModelForm" instead of just "Form" and the class Meta information.
I am guessing you are getting an error here; form = EntryForm(request.POST) but because you are manually writing out the form html instead of using the Django form to do it, you aren't seeing the error.
https://docs.djangoproject.com/en/1.8/topics/forms/#the-template is how you should use Django to render your html for your Django form; and this by default will display any errors the happened when trying to validate your data.

Django convert current model/raw HTML input to Form to save input data

I have a simple form where there is a username and a message. Upon clicking the submit button, I want the data for user and message to be stored separately into the database. I am currently receiving an IntegrityError on m.save()
"Exception Value: SimpleMessage_message.content may not be NULL"
and was told to instead use forms to accomplish this. However, I am confused as to how to use a form to pass in form data to the individual User and Message Models so that the input data is saved in the database.
Models
class User (models.Model):
name = models.CharField(max_length=20)
def __unicode__(self):
return self.name
class Message (models.Model):
content = models.TextField(max_length=140, null=True, blank=True)
user = models.ForeignKey(User)
time = models.DateTimeField()
def __unicode__(self):
return self.content
views.py
def index (request):
if request.method == 'POST':
u = User(name=request.POST.get('user'))
u.save()
m = Message(content=request.POST.get('text'), user = u)
m.save()
return render_to_response('index.html', {
'user': u,
'message': m,
}, RequestContext(request))
else:
u = User()
m = Message()
return render_to_response('index.html', {
'user': u,
'message': m,
}, RequestContext(request)
)
index.html
<form action="{% url 'index' %}" method = "post">
{% csrf_token %}
<input type="text" name="user" id="user" maxlength="20" placeholder = "Username">
<br>
<br>
<textarea rows="4" cols="35" id="text" name="text" maxlength="140" placeholder = "Message goes here"></textarea><br>
<input type="submit" value="Submit">
</form>
Try changing your model so that content can be null:
class Message (models.Model):
content = models.TextField(max_length=140, null=True, blank=True)
Or give a default value in the form:
m = Message(content=request.POST.get('text', ' '), user = u)

Categories