I am in a process to learn Django Framework and I want to understand how can I provide user with a pop up when data integrity is breached due to entry being placed for similar primary key. Since Django does not allows conjugate primary key I've used the unique_together functionality to perform a validity check on form. I've created the model as follows
Model.py
from django.db import models
from django import forms
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','Karachi'),
('ISB', 'Islamabad'),
('LHE','Lahore'),
)
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)
As per the model above user can input 3 entries on same date i.e. one for each station.
Following block contains forms.py
Forms.py
from django import forms
from manhour.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())})
}
Following block shows views.py
Views.py
from django.shortcuts import render, redirect
from django.template.context_processors import csrf
from django.http import HttpResponse
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth import login, logout, authenticate
from django.contrib import messages
from .form import InputForm
from django.urls import reverse
from django.contrib.auth.decorators import login_required
from manhourapp.models import ManHour
from django.utils.decorators import method_decorator
from django.contrib.auth.models import User
from django.db import IntegrityError
from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponse
# Create your views here.
def home_view(request):
context = {
'total_ops': request.GET.get("total_ops", 0)
}
return render(request, 'home.html', context)
def login_request(request):
if request.method == 'POST':
form = AuthenticationForm(request=request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
messages.info(request, f"You are now logged in as {username}")
return redirect('form')
else:
messages.error(request, "Invalid username or password.")
else:
messages.error(request, "Invalid username or password.")
else:
form = AuthenticationForm()
return render(request = request,
template_name = "login.html",
context={"form":form})
@login_required(login_url='login')
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()
print(obj.pk)
return redirect("%s?pk=%s" % (reverse('form'), obj.pk))
else:
context['form'] = properties_Form
return render(request, "form.html", context)
else:
context['form']= InputForm(instance=man_hour)
return render(request, "form.html", context)
@login_required
def update_form(request, id):
obj= get_object_or_404(manhourapp_dev, id=id)
form = InputForm(request.POST or None, instance= obj)
context= {'form': form}
if form.is_valid():
obj= form.save(commit= False)
obj.save()
messages.success(request, "You successfully updated the post")
context= {'form': form}
return render(request, 'update_form.html', context)
else:
context= {'form': form,
'error': 'The form was not updated successfully. Please enter in a correct values'}
return render(request,'update_form.html.html' , context)
urls.py
from django.contrib import admin
from django.contrib.auth import views as auth_views
from django.urls import path
from pages import views
from django.contrib.auth.views import LogoutView
from django.conf.urls import url
from django.conf import settings
urlpatterns = [
path('home/', views.home_view, name='home'),
path('admin/', admin.site.urls),
path('login/', views.login_request, name='login'),
path('form/', views.form_page, name='form'),
path('update_form/<int:pk_>/', views.update_form, name='update_form'),
path("logout/", LogoutView.as_view(), name="logout"),
]
form.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">
<a class="btn btn-sm btn-info" href="update_form/<int:pk_>">Update</a>
<div class="user_panel">
<a href="/logout">logout</a>
</div>
</form>
</body>
</html>
update_form.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 %}
{{ update_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">
<a href="/logout">logout</a>
</div>
</form>
</body>
</html>
I've following questions:
How can I only enable update button when user inputs data for same date/station?
Since Djnago doesn't allows conjugate primary key I want to access the incremental id (primary key) to be returned and passed to
update_formforstationandDatefor which user is passing another entry. How can I achieve that?Currently I am unable to redirect to
update_formview using update button inform.html. I've got the following error.django.urls.exceptions.NoReverseMatch: Reverse for 'update_form' with arguments '('',)' not found. 1 pattern(s) tried: ['\\^\\(\\?P(?P<pk>[^/]+)\\[0\\-9\\]\\+\\)/update_form/\\$$']
I need an answer that can do following things:
- Enable update button when data is being passed for already existing
stationanddate - When user is redirected to update form show the already existing values at that
stationanddateand enable user to update it.