Foreign Key Constraint Failed Django with UUID - django

Trying to save to a table with a foreign key but come up with a IntegrityError: Foreign Key Constraint failed. I have checked to make sure I am getting the correct data for my foreign key and it seems to be there. I am not sure why I am getting this error.
Models.py
class IPHold(models.Model):
uuid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
CHOICES = [
('1', 'Book'),
('2', 'Documentary'),
('3', 'Graphic Novel/Comic'),
('4', 'Journalism'),
('5', 'Merchandise'),
('6', 'Podcast'),
('7', 'Stage Play/Musical'),
('8', 'Video Game'),
]
media_type = models.CharField(max_length=1, choices=CHOICES, blank=False)
title = models.CharField(max_length=255, blank=False)
author_creator = models.CharField(max_length=255, blank=True)
production_company = models.CharField(max_length=255, blank=True)
class RoleHold(models.Model):
ip = models.ForeignKey(IPHold, on_delete=models.CASCADE, related_name='ip_role')
name = models.CharField(max_length=128, blank=False)
TYPE = [
('1', 'Lead'),
('2', 'Supporting'),
]
role_type = models.CharField(max_length=1, choices=TYPE, blank=True)
age_min = models.PositiveSmallIntegerField(blank=True)
age_max = models.PositiveSmallIntegerField(blank=True)
ETHNICITY = [
('1', 'American Indian or Alaska Native'),
('2', 'Asian'),
('3', 'Black or African American'),
('4', 'Hispanic or Latino'),
('5', 'Native Hawaiian or Other Pacific Islander'),
('6', 'White'),
('7', 'Unknown/Irrelevant'),
]
race = models.CharField(max_length=1, choices=ETHNICITY, blank=True)
GENDEROPTIONS = [
('1', 'Male'),
('2', 'Female'),
('3', 'N/A'),
('4', 'Unknown/Irrelevant'),
]
gender = models.CharField(max_length=1, choices=GENDEROPTIONS, blank=True)
description = models.TextField(blank=True)
Views.py
def add_characters(request):
id = request.GET.get('id')
ips = IPHold.objects.get(uuid=id)
form = forms.AddCharacter
context = {
'form':form,
}
if request.method == 'POST':
ip = ips
name = request.POST.get('name')
role_type = request.POST.get('role_type')
age_min = request.POST.get('age_min')
age_max = request.POST.get('age_max')
race = request.POST.get('race')
gender = request.POST.get('gender')
description = request.POST.get('description')
role_save = RoleHold(ip=ip, name=name, role_type=role_type, age_min=age_min,
age_max=age_max, race=race, gender=gender, description=description)
role_save.save()
if request.POST.get('add') == 'Add Another Role':
return redirect('/iphold/add_characters/?id=' + str(ips.uuid))
else:
return(render, 'iphold/pay.html')
return render(request, 'iphold/add_characters.html', context)
The error I am getting is IntegrityError at /iphold/add_characters/
FOREIGN KEY constraint failed. When I print(ip) it shows the object is there.

I assume that in your id it is id (integer number), and not uuid. Try to print the id, what it will show. You want to select by id, so you need to specify the id field and select uuid in the resulting object. Try doing the following:
id = request.GET.get('id')
ips = IPHold.objects.get(id=id)

Related

Get value list from ManytoMany Queryset

I have two models Bookings and Presenter, which are setup as a Many to Many Field.
I then have a function called 'export excel' (found on online tutorial) , which exports all of the data from the Booking model to an Excel spreadsheet. Each booking may contain more than one presenter.
Currently the export works but displays a new record for bookings that have more than one presenter assigned. Is it possible to get the presenter name be displayed as a list? rather than duplicating the booking on a new row.
So for example if booking 1 contains two presenters the names will display as ['mark', 'jake']
Queryset used in export excel function
rows= Bookings.objects.all().exclude(status='Cancelled').values_list(
'id', 'program_type', 'delivery_method', 'booking_date', 'booking_time', 'duration', 'school_name', 'year_level', 'street', 'suburb', 'post_code',
'contact_name', 'email', 'phone_number', 'comments', 'students_attending', 'status', 'presenter__name')
Models
class Presenter(models.Model):
id = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=80)
email = models.EmailField()
phone_number = models.CharField(max_length=10)
role = models.CharField(max_length=50)
def __str__(self):
return self.name
class Bookings(models.Model):
statuses = [
('TBC', 'TBC'),
('Confirmed', 'Confirmed'),
('Completed', 'Completed'),
('Cancelled', 'Cancelled'),
]
id = models.BigAutoField(primary_key=True)
program_type = models.CharField(max_length=40)
delivery_method = models.CharField(max_length=40)
booking_date = models.DateField()
booking_time = models.CharField(max_length=10)
duration = models.CharField(max_length=10)
school_name = models.CharField(max_length=120)
year_level = models.CharField(max_length=10)
street = models.CharField(max_length=120)
suburb = models.CharField(max_length=120)
post_code = models.CharField(max_length=10)
contact_name = models.CharField(max_length=80)
email = models.EmailField()
phone_number = models.CharField(max_length=10)
comments = models.TextField(blank=True, null=True)
students_attending = models.CharField(max_length=5)
status = models.CharField(max_length=80, choices=statuses, default='TBC')
presenter = models.ManyToManyField(Presenter)
def __str__(self):
return self.contact_name
Function
def export_excel(request):
# Set the application type
response = HttpResponse(content_type='application/ms-excel')
# Set the file name and extenstion
response['Content-Disposition'] = 'attachment; filename=Advancement Series' +'.xls'
# Create the workbook
wb = xlwt.Workbook(encoding='utf=8')
# Add the worksheets
advancement = wb.add_sheet('Advancement')
# Set the starting row number
advancement_row_num = 0
# Set the font style
font_style = xlwt.XFStyle()
font_style.font.bold = True
font_style.font.name = 'calibri'
# Set the worksheet columns
advancement_columns = ['Booking ID', 'Program Type', 'Delivery Method', 'Booking Date', 'Booking Time', 'Duration', 'School Name', 'Year Level', 'Street', 'Suburb','Post Code', 'Contact Name', 'Email', 'Phone Number', 'Comments', ' Students Attending', 'Status', 'Presenter']
for col_num in range(len(advancement_columns)):
advancement.write(advancement_row_num, col_num, advancement_columns[col_num], font_style)
# Set the font style for non headings
font_style = xlwt.XFStyle()
font_style.font.name = 'calibri'
# Adds the values from the Bookings table
rows= Bookings.objects.all().exclude(status='Cancelled').values_list(
'id', 'program_type', 'delivery_method', 'booking_date', 'booking_time', 'duration', 'school_name', 'year_level', 'street', 'suburb', 'post_code',
'contact_name', 'email', 'phone_number', 'comments', 'students_attending', 'status', 'presenter__name')
for row in rows:
advancement_row_num+=1
for col_num in range(len(row)):
advancement.write(advancement_row_num, col_num, str(row[col_num]), font_style)
wb.save(response)
return response
Managed to resolve this using the Django import-export.
https://django-import-export.readthedocs.io/en/latest/getting_started.html

Django admin form raises IntegrityError for model with conditional UniqueConstraint

I was asked to add some logic to model uniqueness.
Each Payment must have either transaction_id or payment_id filled.
Each Payment is identificated by (transaction_id, operation, payment_created_date) or (payment_id, operation, payment_created_date).
On database level this works fine.
Inserting Payment with same transaction_id, operation, payment_created_date twice causes unique constraint violation.
For this model i created admin page. But inserting same row with admin page causes IntegrityError at /admin/finance/payment/add/ duplicate key value violates unique constraint "unique_finance_payment_without_payment_id" DETAIL: Key (transaction_id, operation, payment_created_date)=(dasdasd, Refund, 2021-10-04) already exists. instead of simple user-friendly admin error Please correct the error below. Payment with this Transaction id, Operation and Payment created date already exists. How to make Django admin catch this IntegrityError and show it in admin form?
here is my models.py
class ReportName(DiModel):
name = CharField(
max_length=50,
blank=False,
null=False)
def __str__(self):
return self.name
class Payment(DiModel):
class Meta:
unique_together = ('transaction_id', 'payment_id', 'operation', 'payment_created_date')
constraints=[UniqueConstraint(fields=['transaction_id', 'operation', 'payment_created_date'],
condition=Q(payment_id=None),
name='unique_finance_payment_without_payment_id'),
UniqueConstraint(fields=['payment_id', 'operation', 'payment_created_date'],
condition=Q(transaction_id=None),
name='unique_finance_payment_without_transaction_id'),]
OPERATION_TYPE = [
('Refund', 'Refund'),
('Charge', 'Charge'),
]
CURRENCY_CODE = [
('EUR', 'EUR'),
('RUB', 'RUB'),
('USD', 'USD'),
('GBP', 'GBP'),
('AUD', 'AUD'),
('PLN', 'PLN'),
('SGD', 'SGD'),
('MYR', 'MYR'),
('RON', 'RON'),
('ZAR', 'ZAR'),
]
report_name = ForeignKey(ReportName,
on_delete=models.PROTECT,
blank=False,
null=False,
help_text="Processor and report type")
operation = CharField(max_length=6,
choices=OPERATION_TYPE,
blank=False,
null=False,
default=OPERATION_TYPE[0][0],
help_text='Payment operation type')
payment_created_date = DateField(blank=False,
null=False,
default=timezone.now)
amount = DecimalField(blank=True,
null=True,
max_digits=10,
decimal_places=2,
help_text='Payment amount')
commission = DecimalField(blank=False,
null=False,
max_digits=10,
decimal_places=2,
help_text='Transaction fee')
currency = CharField(max_length=3,
choices=CURRENCY_CODE,
blank=False,
null=False,
default=CURRENCY_CODE[0][0],
help_text='Amount and commission currency code')
transaction_id = CharField(max_length=32,
blank=True,
null=True,
help_text='Payota transaction id')
payment_id = IntegerField(blank=True,
null=True,
help_text='Payota payment id')
author_user = models.ForeignKey(User,
on_delete=models.PROTECT,
null=True,
related_name='finance_author_user')
def __str__(self):
return f"{self.report_name} {self.operation} {self.created_at}"
and this is my admin.py
class PaymentForm(forms.ModelForm):
class Meta:
fields = (
'report_name',
'operation',
'payment_created_date',
'amount',
'commission',
'currency',
'transaction_id',
'payment_id',
)
#admin.register(Payment)
class PaymentAdmin(ImportExportMixin, admin.ModelAdmin):
form = PaymentForm
list_display = [
'report_name',
'operation',
'payment_created_date',
'amount',
'commission',
'currency',
'transaction_id',
'payment_id',
]
list_filter = (
'report_name',
'operation',
('payment_created_date', DateRangeFilter),
)
search_fields = ['report_name__name', 'operation']
resource_class = PaymentResource
class Meta:
model = Payment

How to programatically create a database view in Django?

I have following query that I ran to create a database view inside my SQLite database:
CREATE VIEW customerview AS
SELECT
a.id
, name
, email
, vat
, street
, number
, postal
, city
, country
, geo_lat
, geo_lon
, customer_id
, is_primary
FROM customerbin_address a
, customerbin_customer b
WHERE b.id = a.customer_id
AND a.is_primary = 1
In models.py I added the model:
class Customerview(models.Model):
name = models.CharField(max_length=100, db_column='name')
email = models.EmailField(unique=True, db_column='email')
vat = VATNumberField(countries=['NL', 'BE', 'FR', 'DE', 'UK'], blank=True, null=True, db_column='vat')
street = models.CharField(max_length=100, db_column='street')
number = models.IntegerField(null=True, db_column='number')
postal = models.IntegerField(null=True, db_column='postal')
city = models.CharField(max_length=100, db_column='city')
country = CountryField(db_column='country')
is_primary = models.BooleanField(null=False, db_column='is_primary')
geo_lat = models.DecimalField(max_digits=9, decimal_places=6, blank=True, null=True, db_column='geo_lat')
geo_lon = models.DecimalField(max_digits=9, decimal_places=6, blank=True, null=True, db_column='geo_lon')
class Meta:
managed = False
db_table = 'customerview'
and in admin.py I altered the list:
#admin.register(models.Customerview)
class CustomerviewAdmin(admin.ModelAdmin):
list_display = ('name', 'email', 'vat', 'street', 'number', 'postal', 'city', 'country', 'is_primary', 'geo_lat', 'geo_lon')
readonly_fields = ('name', 'email', 'vat', 'street', 'number', 'postal', 'city', 'country', 'is_primary', 'geo_lat', 'geo_lon',)
How do I programatically add the database view with the query above in my application?
Django's migrations framework lets you execute raw SQL - https://docs.djangoproject.com/en/3.1/ref/migration-operations/#runsql
So, you could create an empty migration (manage.py makemigrations <appname> --empty) and then edit it to execute your view-creating SQL via a migrations.RunSQL() call.
Maybe you should try this with the get_view_str method https://pypi.org/project/django-database-view/#description

When I open the model, one field value is replaced automatically

Have a stupid issue: When I open the employee model (in django admin), one field (employee_type) value is replaced automatically, idk why...
Example: I create employee, define employee type as manager, save. In DB value is manager. After that, I open employee and see employee type as sewer and if I save, that value will saved in DB.
I created text choices for this field, and In DB field is defined as enum.
I tried to research the issue, value isn't used from DB, always first value from text choices is used.
By the way, I created same fields (enum in DB and text choices in the model) in other model. And all works properly.
How can I fix it???
Models.py with the issue:
class Employee(models.Model):
class EmployeeType(models.TextChoices):
SEWER = 'SEWER', _('Sewer')
MANAGER = 'MANAGER', _('Manager')
UNDEFINED = 'UNDEFINED', _('Undefined')
user = models.OneToOneField(User,
models.CASCADE,
db_column='user',
verbose_name=_('User'),
primary_key=True)
employee_type = models.CharField(db_column='Employee type',
verbose_name=_('Employee type'),
max_length=9,
choices=EmployeeType.choices,
default=EmployeeType.UNDEFINED)
phone = models.CharField(db_column='Phone',
verbose_name=_('Phone'),
max_length=255)
work_xp = models.IntegerField(db_column='Work XP',
verbose_name=_('Work XP'),
blank=True,
null=True)
Another one models.py. With same fields but without issues:
class Order(models.Model):
class OrderStatus(models.TextChoices):
CREATED = 'Created', _('Created')
CANCELLED = 'Cancelled', _('Cancelled')
IN_PROGRESS = 'In progress', _('In progress')
COMPLETED = 'Completed', _('Completed')
PASSED_TO_CLIENT = 'Passed to the client', _('Passed to the client')
RETURNED_FOR_REWORK = 'Returned for rework', _('Returned for rework')
class Urgency(models.TextChoices):
LOW = 'Low', _('Low urgency')
MEDIUM = 'Medium', _('Medium urgency')
HIGH = 'High', _('High urgency')
VERY_HIGH = 'Very high', _('Very high urgency')
class LabourIntensity(models.TextChoices):
LOW = 'Low', _('1-3 days')
MEDIUM = 'Medium', _('4-6 days')
HIGH = 'High', _('7-9 days')
VERY_HIGH = 'Very high', _('10+ days')
class PaymentStatus(models.TextChoices):
PENDING = 'Pending payment', _('Pending payment')
PREPAYMENT_MADE = 'Prepayment made', _('Prepayment made')
PAID = 'Paid', _('Paid')
id_service = models.ForeignKey(Service,
models.SET_NULL,
db_column='id_Service',
verbose_name=_('Service'),
blank=True,
null=True)
status = models.CharField(db_column='Status',
verbose_name=_('Status'),
max_length=20,
choices=OrderStatus.choices,
default=OrderStatus.CREATED)
payment_status = models.CharField(db_column='Payment status',
verbose_name=_('Payment status'),
max_length=15,
choices=PaymentStatus.choices,
blank=True,
null=True)
prepayment = models.DecimalField(db_column='Prepayment',
verbose_name=_('Prepayment'),
max_digits=19,
decimal_places=2,
blank=True,
null=True)
cost = models.DecimalField(db_column='Cost',
verbose_name=_('Cost'),
max_digits=19,
decimal_places=2,
blank=True,
null=True)
start_date = models.DateTimeField(db_column='Start date',
verbose_name=_('Start date'),
blank=True,
null=True)
end_date = models.DateTimeField(db_column='End date',
verbose_name=_('End date'),
blank=True,
null=True)
id_client = models.ForeignKey(Client,
models.SET_NULL,
db_column='id_Client',
verbose_name=_('Client'),
blank=True,
null=True)
id_employee = models.ForeignKey(Employee,
models.SET_NULL,
db_column='id_Employee',
verbose_name=_('Employee'),
blank=True,
null=True)
labour_intensity = models.CharField(db_column='Labour intensity',
verbose_name=_('Labour intensity'),
max_length=9,
choices=LabourIntensity.choices,
default=LabourIntensity.LOW)
urgency = models.CharField(db_column='Urgency',
verbose_name=_('Urgency'),
max_length=9,
choices=Urgency.choices,
default=Urgency.LOW)
materials = models.ManyToManyField(Material, through='OrderMaterials')
comment = models.TextField(db_column='Comment',
verbose_name=_('Comment'),
blank=True,
null=True)
I solved this issue.
In DB a type of field "employee_type" was defined as:
ENUM('Undefined','Sewer','Manager')
But the model has EmployeeType choices with uppercase.
Solution: I changed lowercase to uppercase of the values in the field type in DB:
ENUM('UNDEFINED','SEWER','MANAGER')
Now everything works fine.

django.db.utils.ProgrammingError: relation "postgres_po_db_view" already exists

am developing an api based on database view and am trying to a create a model for the same postgres database view with managed=False option in class meta of model, and am connecting my model via db_table parameter in the same class meta, here my database view name is "postgres_po_db_view" and am getting an error when ever am trying to run migrations for the corresponding model, please don't bother about the view or the model code, everything is good and working but my concern is when ever am trying to connect my model with my database view through class meta configuration inside the model class,when i migrated the very first time it is running smooth, and then after trying to run one more migration for another model or again trying to run the same command migrate am getting relation postgres_po_db_view already exists error...any useful lead is much appreciable..am unable to apply further migrations due to this error...
here is my model:
class ProductionOrderView(models.Model):
class Meta:
managed = False,
ordering = '-creation_time',
db_table = 'postgres_po_db_view'
DRAFT = 'draft'
PLANNING = 'planning'
NOT_STARTED = 'not_started'
IN_PROGRESS = 'in_progress'
CANCELLED = 'cancelled'
DONE = 'done'
FAILED = 'failed'
STATUS_CHOICES = (
(DRAFT, 'Draft'),
(PLANNING, 'Planning'),
(NOT_STARTED, 'Not Started'),
(IN_PROGRESS, 'In Progress'),
(CANCELLED, 'Cancelled'),
(DONE, 'Done'),
(FAILED, 'Failed'),
)
ACTIVE_STATUS_LIST = [DRAFT, IN_PROGRESS, PLANNING]
id = models.UUIDField(
default=uuid.uuid4,
primary_key=True,
editable=False,
unique=True,
)
name = models.CharField(
max_length=64,
default = '',
blank = True,
)
deadline = models.DateTimeField(**NB)
planned_date = models.DateTimeField(**NB)
print_date = models.DateTimeField(**NB)
build = models.CharField(
max_length=256,
default='',
blank=True,
)
sop = models.CharField(
max_length=128,
default='',
blank=True,
)
notes = models.CharField(
max_length=256,
default='',
blank=True,
)
build_qty = models.IntegerField(default=0)
status = models.CharField(
max_length=64,
default='',
)
last_updated_by =models.CharField(
max_length=64,
default='',
)
site = JSONField(
default=dict
)
site_id = models.CharField(
max_length=64,
default='',
)
production_type = models.CharField(
max_length=64,
default='',
blank=True,
)
operation_failures = JSONField(
default=dict
)
operation_status = JSONField(
default=dict
)
files = JSONField(
default=dict
)
sap_backflush_submission_status = models.BooleanField(default=False)
creation_time = models.DateTimeField(**NB)
update_time = models.DateTimeField(**NB)
here is my postgres data base view:
create or replace view postgres_po_db_view as
(select po.id,po.name as name),
(po.institution_id as institution),
(po.deadline),
(po.planned_date),
(po.print_date),
(po.status),
(po.production_type),
(po.notes),
(po.creation_time),
(po.update_time),
(Select bu.name from skyforge_build as bu where bu.id = po.build_id) as build,
(Select so.name from skyforge_sop as so where so.id = po.sop_id) as sop,
(select json_agg(site) from (Select si.name,si.id from skyforge_site as si where si.id=po.site_id) as site) as site,
(Select us.first_name from auth_user as us where us.id=po.last_updated_by_id) as last_updated_by,
(Select sum(quantity) from skyforge_buildpart as bup where bup.build_id=po.build_id) as build_qty,
(select json_agg(totrecs) as operation_fail_list from (select operation_id,array_agg(id) as operation_failures from skyforge_failure as fail where ROW(operation_id) in (select id from skyforge_operation as op where op.production_order_id = po.id) group by fail.operation_id) as totrecs) as operation_failures,
(select json_agg(json_build_object(op.id,op.status)) from skyforge_operation as op where op.production_order_id = po.id) as operation_status,
(select json_agg(vtorecs) from (select id,name,content from skyforge_file group by id having parent_id=po.id union select id,name,content from (select fi.id,fi.name,fi.content,po.id as poid from skyforge_file as fi,skyforge_productionorder as po where fi.id in (po.backflush_id,po.pdf_id,po.inspection_template_full_id,po.inspection_template_sampling_id,po.production_slips_id,po.serialized_part_tags_id,po.batches_qr_labels_id)) as recs where recs.poid=po.id) as vtorecs) as files,
(po.sap_backflush_submission_status)
From skyforge_productionorder as po;