So I have a model called Organization inside core/models.py. I am trying to implement CRUD Ajax on a single page. Inspired by this post . Every time I save an object of this model I get this error as shown below. I want to have multiple organizations that are unique.
core/models.py
class Organization(models.Model):
name = models.CharField(max_length=255, unique=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
gstin = models.CharField(max_length=15)
address = models.CharField(max_length=500)
city = models.CharField(max_length=50)
state = models.CharField(max_length=50)
zipcode = models.CharField(max_length=6)
country = models.CharField(max_length=50)
is_billed = models.BooleanField(default=False)
def __str__(self):
return f'{self.name} Organization'
core/forms.py
class OrganizationForm(forms.ModelForm):
class Meta:
model = models.Organization
fields = ('name', 'address', 'state', 'city', 'zipcode', 'country', 'gstin')
core/views.py
def save_organization_form(request, form, template_name):
data = dict()
if request.method == 'POST':
if form.is_valid():
stock = form.save(commit=False)
stock.user = request.user
stock.save()
data['form_is_valid'] = True
organizations = Organization.objects.all()
data['html_book_list'] = render_to_string('core/includes/partial_organization_list.html', {
'organizations': organizations
})
else:
data['form_is_valid'] = False
context = {'form': form}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
@login_required(login_url="/accounts/login/")
def organization_create(request):
if request.method == 'POST':
form = OrganizationForm(request.POST)
else:
form = OrganizationForm()
return save_organization_form(request, form, 'core/includes/partial_organization_create.html')
templates/base.html
{% load static %}
<!DOCTYPE html>
<html>
<head>
<title>{% block head_title %}{% endblock %}</title>
{% block extra_head %}
{% endblock %}
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href='https://fonts.googleapis.com/css?family=Russo One' rel='stylesheet'>
<link rel="stylesheet" type="text/css" href="{% static 'font/flaticon.css' %}">
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
{% block body %}
{% if messages %}
<div class="text-center">
<strong>Messages:</strong>
<ul>
{% for message in messages %}
<li>{{message}}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% block content %}
{% endblock %}
{% endblock %}
{% block extra_body %}
{% endblock %}
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"
integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"
integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
{% block javascript %}
{% endblock %}
</body>
</html>
templates/core/organization_list.html
{% extends 'base.html' %}
{% load static %}
{% block javascript %}
<script src="{% static 'organizations/js/organizations.js' %}"></script>
{% endblock %}
{% block content %}
<h1 class="page-header">Organizations</h1>
<!-- BUTTON TO TRIGGER THE ACTION -->
<p>
<button type="button"
class="btn btn-primary js-create-book"
data-url="{% url 'organization_create' %}">
<span class="glyphicon glyphicon-plus"></span>
New Organization
</button>
</p>
<table class="table" id="book-table">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Address</th>
<th>State</th>
<th>City</th>
<th>Zipcode</th>
<th>Country</th>
<th>Billing Active</th>
</tr>
</thead>
<tbody>
{% include 'core/includes/partial_organization_list.html' %}
</tbody>
</table>
<!-- THE MODAL WE WILL BE USING -->
<div class="modal fade" id="modal-book">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
</div>
{% endblock %}
templates/core/partial_organization_list.html
{% for organization in organizations %}
<tr>
<td>{{ organization.id }}</td>
<td>{{ organization.name }}</td>
<td>{{ organization.address }}</td>
<td>{{ organization.state }}</td>
<td>{{ organization.city }}</td>
<td>{{ organization.zipcode }}</td>
<td>{{ organization.country }}</td>
<td>{{ organization.is_billed }}</td>
<td>
<button type="button"
class="btn btn-warning btn-sm js-update-book"
data-url="{% url 'organization_update' organization.id %}">
<span class="glyphicon glyphicon-pencil"></span> Edit
</button>
<button type="button"
class="btn btn-danger btn-sm js-delete-book"
data-url="{% url 'organization_delete' organization.id %}">
<span class="glyphicon glyphicon-trash"></span> Delete
</button>
</td>
</tr>
{% empty %}
<tr>
<td colspan="8" class="text-center bg-warning">No Organization</td>
</tr>
{% endfor %}
static/organizations/js/organizations.js
$(function () {
$(".js-create-book").click(function () {
$.ajax({
url: '/profile/organization/create/',
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal-book").modal("show");
},
success: function (data) {
$("#modal-book .modal-content").html(data.html_form);
}
});
});
});
$("#modal-book").on("submit", ".js-book-create-form", function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#book-table tbody").html(data.html_book_list); // <-- Replace the table body
$("#modal-book").modal("hide"); // <-- Close the modal
}
else {
$("#modal-book .modal-content").html(data.html_form);
}
}
});
return false;
});
$(".js-create-book").click(function () {
var btn = $(this); // <-- HERE
$.ajax({
url: btn.attr("data-url"), // <-- AND HERE
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal-book").modal("show");
},
success: function (data) {
$("#modal-book .modal-content").html(data.html_form);
}
});
});
$(function () {
/* Functions */
var loadForm = function () {
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal-book").modal("show");
},
success: function (data) {
$("#modal-book .modal-content").html(data.html_form);
}
});
};
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#book-table tbody").html(data.html_book_list);
$("#modal-book").modal("hide");
}
else {
$("#modal-book .modal-content").html(data.html_form);
}
}
});
return false;
};
/* Binding */
// Create book
$(".js-create-book").click(loadForm);
$("#modal-book").on("submit", ".js-book-create-form", saveForm);
// Update book
$("#book-table").on("click", ".js-update-book", loadForm);
$("#modal-book").on("submit", ".js-book-update-form", saveForm);
// Delete book
$("#book-table").on("click", ".js-delete-book", loadForm);
$("#modal-book").on("submit", ".js-book-delete-form", saveForm);
});
And when I add a new organization I get the following error:
django.db.utils.IntegrityError: UNIQUE constraint failed: core_organization.name
How do I fix this?
I believe your javascript file contains duplicate ajax calls.
There are 3 calls to create your modal:
$(function () {
$(".js-create-book").click(function () {
at the top of your js file. Then the same function in the middle of your js file. And
var loadForm = function ()
which your binding to the click event at the bottom of your script.
In addition there are two functions handling the submission of the form data:
$("#modal-book").on("submit", ".js-book-create-form", function ()
in the top part and
var saveForm = function ()
in the bottom part.
The duplicate regarding the submission of the form can cause the unique constraint error because you are submitting the same data twice. The duplication of the loading of the modal probably does not cause any noticable errors, but is unnecessary load.
The bottom part of your javascript file, ie the part beginning with
$(function () {
/* Functions */
should be sufficient.
I think you are having this issue, because of the unique=True
constraint on your name
field
name = models.CharField(max_length=255, unique=True)
This means that the name is going to be unique for all users, and you will keep getting UNIQUE constraint failed
error everytime you add the same name for different users.
To solve this, I suggest using unique_together
meta option. All you have to do, is removing the unique
constraint from name field, and adding Meta
class with the unique_toghether
option to include both the user_id
and name
fields.
class Organization(models.Model):
name = models.CharField(max_length=255)
user = models.ForeignKey(User, on_delete=models.CASCADE)
address = models.CharField(max_length=1000, default=None)
is_billed = models.BooleanField(default=False)
def __str__(self):
return f'{self.name} Organization'
class Meta:
unique_together = ['name', 'user_id']
Then, python manage.py makemigrations
, python manage.py migrate
.
The UNIQUE
constraint going to remain, but it is going to be for all Organization
names related for one user.
If USER1 have organization ORG1 , and tried to add another ORG1 , it is going to fail, but if USER2 added ORG1 it is going to work successfully.
Try updating the instance rather than form object, Create separate endpoint/logic for updating instance and an separate endpoint/logic to create objects using form
views.py
def save_organization_form(request, form, template_name):
data = dict()
if request.method == 'POST':
if form.is_valid():
stock = form.instance
stock.user = request.user
stock.something = request.something
stock.save()
data['form_is_valid'] = True
organizations = Organization.objects.all()
data['html_book_list'] = render_to_string('core/includes/partial_organization_list.html', {
'organizations': organizations
})
else:
data['form_is_valid'] = False
context = {'form': form}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
@login_required(login_url="/accounts/login/")
def organization_create(request):
if request.method == 'POST':
form = OrganizationForm(request.POST)
else:
form = OrganizationForm()
return save_organization_form(request, form, 'core/includes/partial_organization_create.html')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.