FOREIGN KEY constraint failed in Django TabularInline - django

I have 2 models: Responsavel and Filho. Responsavel can have a lot of Filhos, so in my admin.py file i have the following:
class FilhoInline(admin.TabularInline):
model = Filho
#admin.register(Responsavel)
class ResponsavelAdmin(admin.ModelAdmin):
inlines = [
FilhoInline
]
def save_model(self, request, obj, form, change):
obj.user.is_pai = True
obj.user.save()
super().save_model(request, obj, form, change)
With this i can insert Responsavel and Filho in same screen, much more usable. So, in my models.py i have:
class Responsavel(models.Model):
user = models.OneToOneField(TogetherUser, verbose_name="Usuário", primary_key=True, on_delete=models.CASCADE)
cpf = models.CharField(max_length=11, unique=True)
telefone1 = models.CharField(max_length=50, blank=True, null=True)
telefone2 = models.CharField(max_length=50, blank=True, null=True)
telefone3 = models.CharField(max_length=50, blank=True, null=True)
def __str__(self):
return self.user.username
class Meta:
verbose_name_plural = "Responsáveis"
verbose_name = "Responsável"
class Filho(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
nome = models.CharField(max_length=100)
data_nascimento = models.DateField(verbose_name="Data de Nascimento")
genero = models.CharField(max_length=1, choices=Genero.choices(), verbose_name="Gênero")
responsavel = models.ForeignKey(Responsavel, on_delete=models.PROTECT, verbose_name="Responsável")
def __str__(self):
return self.nome
class Meta:
verbose_name_plural = "Filhos"
When i try to save the Responsavel and your "Filhos" inside Admin Django i got the following error:
IntegrityError at /admin/core/responsavel/add/
FOREIGN KEY constraint failed
But if i add Responsavel without any "Filhos" everything works.
Edit 1:
I changed the models.PROTECT to models.CASCADE and it works, in this point:
responsavel = models.ForeignKey(Responsavel, on_delete=models.PROTECT, verbose_name="Responsável")
to
responsavel = models.ForeignKey(Responsavel, on_delete=models.CASCADE, verbose_name="Responsável")
I have no ideia why this can impact in my save method if this is a "on_delete" and not "on_update" or something else.

Related

how to use django Serializer or signal to add object in database?

I create ticket , ticketflow , ticketstate , tickettype models
i need a serializer or signal that when user create ticket programmatically add ticketflow object and set state of ticket to submited or something else
Here is my models
class TicketType(models.Model):
title = models.CharField(max_length=255, blank=False, unique=True, null=False)
def __str__(self):
return self.title
class TicketState(models.Model):
title = models.CharField(max_length=255, blank=False, unique=True, null=False)
def __str__(self):
return self.title
class Ticket(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4 , editable=False)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
ticket_type = models.ForeignKey(TicketType,on_delete=models.CASCADE , default=1)
title = models.CharField(max_length=255, blank=False, null=False)
message = models.TextField()
attachment = models.FileField(upload_to='uploads/tickets/', validators=[FileExtensionValidator(allowed_extensions=['pdf','docx','zip','jpg','png'])], blank=True)
created_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
class TicketFlow(models.Model):
uuid = models.UUIDField(default=uuid4, editable=False)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
ticket = models.ForeignKey(Ticket,on_delete=models.CASCADE , related_name='ticketflow')
ticket_state = models.ForeignKey(TicketState,on_delete=models.CASCADE , default=1 , related_name='ticketstate')
message = models.TextField()
attachment = models.FileField(upload_to='uploads/tickets/', validators=[FileExtensionValidator(allowed_extensions=['pdf','docx','zip','jpg','png'])], blank=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now= True)
class Meta:
ordering = ['-created_on']
here is my serializers
class TicketTypeSerializer(serializers.ModelSerializer):
class Meta:
model = TicketType
fields = ('id','title',)
class TicketStateSerializer(serializers.ModelSerializer):
class Meta:
model = TicketState
fields = ('id','title',)
class TicketSerializer(serializers.ModelSerializer):
class Meta:
model = Ticket
fields = ['id' , 'author', 'ticket_type','title' ,'message' , 'attachment' , 'created_on']
class TicketFlowSerializer(serializers.ModelSerializer):
class Meta:
model = TicketFlow
fields = ['author', 'ticket_state', 'message', 'attachment', 'created_on', 'updated_on']
It'll be great if someone can help me out in this. how can i create signal or override create method in serializers
You probably want your "state" field to be read-only in the serializer, this way it can only be changed programmatically, and in the model set a default value with default='pending'.
Then you can override the update method in a Serializer (see the doc here):
def update(self, instance, validated_data):
validated_data['state'] = 'edited'
return super(MySerializer, self).update(instance, validated_data)

User foreign key in same model getting updated together in sql database

models.py
class test(models.Model):
data = models.CharField(max_length=25, null=True)
recordname = models.CharField(max_length=25, null=True)
recordname2 = models.CharField(max_length=25, null=True)
a_names = models.ForeignKey(User, related_name='a_names', on_delete=models.DO_NOTHING, blank=True, null=True)
b_names = models.ForeignKey(User, related_name='b_names', on_delete=models.DO_NOTHING, blank=True, null=True)
forms.py
class Test1ModelForm(forms.ModelForm):
class Meta:
model = Test1
fields = ('id', 'a_names','data', 'recordname')
class Test2ModelForm(forms.ModelForm):
class Meta:
model = Test1
fields = ('id', 'b_names','data', 'recordname2')
views.py
def Testing(request, pk):
form = Test1ModelForm(instance=pk)
if form.is_valid():
form.save()
def Testing1(request, pk):
form = Test2ModelForm(instance=pk)
if form.is_valid():
form.save()
the problem is, when the data is getting updated in the database, both a_names and b_names are getting updated.
Step 1: User "a_names" is updating "recordname"
Step 2: User "b_names" is updating "recordname1"
Since there is no difference between the two line - except the field name - those two fields always be the same.
models.py
class test(models.Model):
a_names = models.ForeignKey(User, related_name='a_names', on_delete=models.DO_NOTHING, blank=True, null=True)
b_names = models.ForeignKey(User, related_name='b_names', on_delete=models.DO_NOTHING, blank=True, null=True)
what do you want to achieve?

How to update a User and its Profile in nested serializer using generic ListCreateAPIView?

I am working on genericAPIViews in DRF. I am using a built in user model with UserProfile model having one to one relation with it. But I am unable to update user due to nested serializer. My question is that how I can update my built in User model and Profile User model at the same time as UserProfile model is nested in User model.Here is my code:
Models.py
USER_CHOICE = (
('SS', 'SS'),
('SP', 'SP')
)
LOGIN_TYPE = (
('Local', 'Local'),
('Facebook', 'Facebook'),
('Google', 'Google')
)
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
cell_phone = models.CharField(max_length=15, blank=True, default="", null=True)
country = models.CharField(max_length=50, blank=True, default="", null=True)
state = models.CharField(max_length=50, blank=True, default="", null=True)
profile_image = models.FileField(upload_to='user_images/', default='', blank=True)
postal_code = models.CharField(max_length=50, blank=True, default="", null=True)
registration_id = models.CharField(max_length=200, null=True, blank=True, default=None)
active = models.BooleanField(default=True)
# roles = models.ForeignKey(Role, null=True, on_delete=models.CASCADE, related_name='role', blank=True)
user_type = models.CharField(max_length=50, choices=USER_CHOICE, null=True, blank=True)
login_type = models.CharField(max_length=40, choices=LOGIN_TYPE, default='local')
reset_pass = models.BooleanField(default=False)
confirmed_email = models.BooleanField(default=False)
remember_me = models.BooleanField(default=False)
reset_code = models.CharField(max_length=200, null=True, blank=True, default="")
reset_code_time = models.DateTimeField(auto_now_add=True, blank=True)
longitude = models.DecimalField(max_digits=80, decimal_places=10, default=0.00)
latitude = models.DecimalField(max_digits=80, decimal_places=10, default=0.00)
r_code = models.CharField(max_length=15, null=True, blank=True)
refer_user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name="user_refer")
referred = models.ManyToManyField(User, related_name="user_referred", null=True, blank=True)
otp = models.CharField(max_length=6, blank=True, default="", null=True)
def __str__(self):
return self.user.username
Seralizer.py
from rest_framework import serializers
from django.contrib.auth.models import User
from .models import UserProfile
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = '__all__'
class UserSerializer(serializers.ModelSerializer):
profile = UserProfileSerializer()
class Meta:
model = User
fields = ['id', 'username', 'email', 'first_name', 'last_name', 'profile']
def create(self, validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create(**validated_data)
Profile.objects.create(user=user, **profile_data)
return user
Views.py
class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
class UserDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [IsAdminUser]
How can write my .update() methods which can be override according to DRF documentation.Thanks in advance for your addition to my knowledge.
There is update method in ModelSerializer which can be overriden the same way as you did with create.
def update(self, instance, validated_data):
profile_data = validated_data.pop('profile', {})
profile = instance.profile
for attr, value in profile_data.items():
setattr(profile, attr, value)
profile.save()
return super(UserSerializer, self).update(instance, validated_data)
You can also write nested serializer.

Django Rest Framework- foreign key throwing error

I am using django rest framework wherein the model has composite primary key, one of the them being a foreign key.
models/TestSuite.py
class TestSuite(models.Model):
team_name = models.ForeignKey('Team', on_delete=models.DO_NOTHING, db_column='team_name')
suite_name = models.CharField(max_length=100)
description = models.CharField(max_length=200, blank=True, null=True)
schedule = models.CharField(max_length=100, blank=True, null=True)
email_list_ok = models.CharField(max_length=200, blank=True, null=True)
email_list_fail = models.CharField(max_length=200, blank=True, null=True)
template_name = models.ForeignKey('EmailTemplates', on_delete=models.DO_NOTHING, db_column='template_name')
class Meta:
managed = False
db_table = 'test_suite'
unique_together = (('team_name', 'suite_name'),)
models/Team.py
class Team(models.Model):
team_name = models.CharField(primary_key=True, max_length=30)
description = models.CharField(max_length=100, blank=True, null=True)
class Meta:
managed = False
db_table = 'team'
TestSuiteSerializer.py
class Meta:
model = models.TestSuite
fields = '__all__'
TestSuiteViewSet.py
class TestSuiteViewSet(viewsets.ModelViewSet):
queryset = models.TestSuite.objects.all()
serializer_class = serializers.TestSuiteSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data,
many=isinstance(request.data, list))
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data,
status=status.HTTP_201_CREATED, headers=headers)
Now when I do a post request, it throws below errors
When the post() has team_name already existing in team table
{
"team_name": [
"test suite with this team name already exists."
]
}
When the post() has team_name not existing in team table
Exception Type: ValueError
Exception Value:
Cannot assign "'dummy'": "TestSuite.team_name" must be a "Team" instance.
Can someone please help me here. I am assuming I am missing something.
The first argument to your foreign key fields should be the model itself, not a string of the model (eg. not 'Team', but Team - likewise for EmailTemplate)
class TestSuite(models.Model):
# Change this field's first argument from a string to the Team class
team_name = models.ForeignKey(Team, on_delete=models.DO_NOTHING, db_column='team_name')
suite_name = models.CharField(max_length=100)
description = models.CharField(max_length=200, blank=True, null=True)
schedule = models.CharField(max_length=100, blank=True, null=True)
email_list_ok = models.CharField(max_length=200, blank=True, null=True)
email_list_fail = models.CharField(max_length=200, blank=True, null=True)
# Change this field's first argument from a string to the EmailTemplates class
template_name = models.ForeignKey(EmailTemplates, on_delete=models.DO_NOTHING, db_column='template_name')
class Meta:
managed = False
db_table = 'test_suite'
unique_together = (('team_name', 'suite_name'),)

Django design model - when a data of status field changes, remaining models status change with it

Its my first time trying django as my first programming project.
I have a hierarchy structure of Company -> Business -> Outlets using foreign key.
I would like to know is there anyway to structured it in a way where the Company status is saved as inactive status, the remaining business, outlets models that will be triggered as inactive status.
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Common_Info(models.Model):
"""(Common description)"""
name = models.CharField(blank=True, max_length=100)
slug = models.SlugField(unique=True, max_length=120)
address_1 = models.CharField(max_length=50, null=True)
address_2 = models.CharField(max_length=50, null=True)
address_3 = models.CharField(max_length=50, null=True)
post_code = models.CharField(max_length=6, null=False)
registration_no. = models.CharField(max_length=15,null=False)
gst_no. = models.CharField(max_length=15,null=True)
telphone_no. = models.CharField(max_legth=15, null=False)
fax_no. = models.CharField(max_legth=15, null=True)
email_address = models.EmailField(max_length=254,null=False)
"""(Status choice)"""
Active_Status = 1
Inactive_Status = 0
STATUS_CHOICES = (
(Active_Status, 'Active'),
(Inactive_Status, 'Inactive'),
)
status = models.IntegerField(choices=STATUS_CHOICES, default=Active_Status)
create_date = models.DateTimeField(auto_now_add=True)
create_user = models.ForeignKey(settings.AUTH_USER_MODEL)
modified_date = models.DateTimeField(auto_now_add=True)
modified_user = models.ForeignKey(settings.AUTH_USER_MODEL)
class Meta:
abstract = True
class Company(Common_Info):
"""(Company additional description)"""
gst_no. = models.CharField(max_length=15,null=True)
class Meta:
verbose_name ='Company'
verbose_name_plural = "Companies"
def __unicode__(self):
return u"Company"
class Business(Common_Info):
"""(Business description)"""
parent=models.ForeignKey(Company, on_delete=models.CASCADE)
gst_no. = models.CharField(max_length=15,null=True)
class Meta:
verbose_name ='Business'
verbose_name_plural = "Businesses"
def __unicode__(self):
return u"Business"
class Outlet(Common_Info):
outlet_code = models.CharField(max_length=3, unique=True)
business_name = models.ForeignKey(Business, on_delete=models.CASCADE)
def __unicode__(self):
return u"Outlet"
Is there something similar to cascade on delete or other more elegant way of extending such a function across other apps in the project.
I don't think there is any direct support in ORM. But you can override the save() method to update the related the outlets and business. You can use related objects to fetch business and outlets. Here is an example:
class Company(Common_Info):
"""(Company additional description)"""
gst_no. = models.CharField(max_length=15,null=True)
class Meta:
verbose_name ='Company'
verbose_name_plural = "Companies"
def __unicode__(self):
return u"Company"
def save(self, *args, **kwargs):
super(Company, self).save(*args, **kwargs)
if self.status == 0:
self.business_set.update(status=self.status)
self.outlet_set.update(status=self.status)