Oleg Radchenko
Oleg Radchenko

Reputation: 79

Django: OneToOne self-referencing field form validation error (Model with this field already exists)

Guys, could you please give a hint..

I just made a onetoone field in model that refers to itself. I have a collision problem in form validation when Im trying to edit already created model with already filled onetoone field with the SAME instance as it was assigned from scratch. In case I remain same relation (instance that was assigned before) in field it will return error: "Model (name of my model) with this field (name of my field) already exists" but If I change field value in form to another instance it will eventually validate this form without any problems. So, my solution that came to my mind is to override validate/clean methods in form. Is it a proper way to manage this problem? And if it's true so how to write a proper code to handle this case?

For clarity I attach my code below:

Models.py

db_dr = models.OneToOneField('self', on_delete=models.CASCADE, blank=True, null=True)

Part of code in views.py

form = DatabaseInfoForm(initial=data)
if request.method == 'POST':
   form = DatabaseInfoForm(request.POST)
   if form.is_valid():

Upvotes: 0

Views: 578

Answers (1)

cosmos multi
cosmos multi

Reputation: 565

you are not putting in your full code for help, so here is an example, if let's say you have two models employee and company:

class Employee(models.Model):
    name = models.CharField(max_length=25)
    created_name = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name


class Company(models.Model):
    employee = models.OneToOneField(Employee, on_delete=models.CASCADE)
    name = models.CharField(max_length=50)
    direction = models.CharField(max_length=80)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

Assuming you already have the employee form created, we'll just create the company form:

class CompanyForm(ModelForm):
    class Meta:
        model = Company
        fields = (
            'employee', 'name', 'direction',
        )

already having the company models and forms, it is only a matter of creating the views, first we start with the creation one:

def company_creation(request):
    template_name = 'your template'
    form = CompanyForm(request.POST)

    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect('your url')

    return render(request, template_name, {
        'form': form,
    })

then we create the modification view:

def company_edit(request, pk):
    template_name = 'your template'

    # here we get the data we want to modify
    company = Company.objects.get(pk=pk)
    form = CompanyForm(request.POST, instance=company)

    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect('your url')

    return render(request, template_name, {
        'form': form,
    })

finally we just create the url:

app_name = 'company'
urlpatterns = [
    path('create/', views.company_creation, name='create'),
    path('edit/<pk>/', views.company_edit, name='edit'),
]

and that way create and edit, without any problem

Upvotes: 1

Related Questions