Check if record exists in model

If you’re reporting everything accurately, something, somewhere, is trying to send you to “/show_project_details/…”.

I don’t know where that is - I don’t have nearly enough information about your complete project. It’s going to be up to you to find out at exactly what location that URL gets into your page - or as an internal reference.

You’re going to need to examine the rendered HTML in the browser to verify URLs being generated and requested.

Found this error:

[29/Nov/2021 20:46:51] "GET / HTTP/1.1" 200 60298
[29/Nov/2021 20:46:57] "GET /show_project_details/1 HTTP/1.1" 200 55819
Internal Server Error: /show_project_details/...
Traceback (most recent call last):
  File "d:\AzDoProjects\webApp\venv\lib\site-packages\django\db\models\fields\__init__.py", line 1823, in get_prep_value
    return int(value)
ValueError: invalid literal for int() with base 10: '...'

It was this line that was throwing the 404 :frowning:
<img src="..." class="img-fluid rounded-start" alt="...">

So i’ve got rid of the error, but the view isn’t redirecting to the update_fundamentals_view
It always goes to the add_fundamentals_view even if the check_exists is True

Please post the current view.

def Fundamentals_view(request, project_id):
    check_exist = Fundamentals.objects.filter(project_name_id=project_id)
    if check_exist:
        return update_fundamentals_view(request, project_id)
    else:
        return add_fundamentals_view(request, project_id)


@login_required
def add_fundamentals_view(request, project_id):
    project = get_object_or_404(Project, pk=project_id)
    if request.method == 'POST':
        form = AddFundamentalsForm(request.POST)
        if form.is_valid():
            form.instance.project = project
            form.save()
            return redirect('http://127.0.0.1:8000/')
    else:
        form = AddFundamentalsForm()
    return render(request, 'pages/add_fundamentals.html', {'project': project, "form": form})

def update_fundamentals_view(request, project_id):
    project= Project.objects.get(pk=project_id)
    form = AddFundamentalsForm(request.POST or None, instance=project)
    if form.is_valid():
        form.save()
        return redirect('dashboard.html')
    return render(request, 'pages/update_fundamentals.html', {'project': project, "form": form})

I dont think its the `Fundamentals_view, cause thats pretty simple.

Ok, either I missed this earlier or this was an edit:

project_name = models.ForeignKey(Project, to_field='project_name', on_delete=models.CASCADE)

You’ve got the “to_field” defined in your foreign key definition, but you’re passing the integer value in as the parameter.

You need to do one of the following:

  • Pass in the project name as the url parameter

  • Rewrite your query to work with the non FK id

  • (Recommended) Eliminate the “to_field” attribute of your ForeignKey specification. Yes, that attribute has some value - but this really isn’t one of those cases. You’re only going to make things more difficult for yourself by doing it the way you have it now.

That has always been there, but is that not right then? should i not be defining the field?

Sorry, mis-hit save too soon. Answer has been edited to hopefully address your question here.

Thanks Ken. this is working now except i cant post back to the database. And this is because of the way i have setup JavaScript to post back to the current URL . I feel that i have done this all wrong now and making this alot harder than it needs to be.

The POST from the JavaScript is xhr.open("POST", window.location.href); but becuase i am handing the different views from within the single view i assume that this has broken this part of the add or update view

if request.method == 'POST':
        form = AddFundamentalsForm(request.POST)
        if form.is_valid():
            form.instance.project = project
            form.save()

i think when you use crispy forms the forms takes care of the submit whereas in my case i have to tell JS where to post.

Do you think its better if i re-create the forms using cripsty and use {% forms %} to render my form?

No, not an accurate statement.

No, that is not the correct conclusion.

This is not correct - if you’re using AJAX, you always need to specify the target url.

The two items are completely unrelated. Don’t think of those sub-functions as views - think of them as utility functions within your code. Dividing the code like this is the right approach. The issues you’re currently encountering have nothing to do with that.

To fully diagnose this, we may need to see the complete subfunction, not just the snippet you provided. You also didn’t post whether there was an error message received as part of this.

Also, see the section of the docs when you need to modify an object with data not provided by the form. Pay particular attention to the text after the first example and the second example in that section, ignoring all specific references to ManyToMany relationships. (They don’t apply in this case.)

In particular, pay attention to the usage of the commit parameter in the save call, and what the objects are that are being worked with at each step of that second example.

Ill take a look at the link.

These are my two views

@login_required
def add_fundamentals_view(request, project_id):
    project = get_object_or_404(Project, pk=project_id)
    if request.method == 'POST':
        form = AddFundamentalsForm(request.POST)
        if form.is_valid():
            form.instance.project = project
            form.save()
            return redirect('http://127.0.0.1:8000/')
    else:
        form = AddFundamentalsForm()
    return render(request, 'pages/add_fundamentals.html', {'project': project, "form": form})

def update_fundamentals_view(request, project_id):
    project= Project.objects.get(pk=project_id)
    form = AddFundamentalsForm(request.POST or None, instance=project)
    if form.is_valid():
        form.save()
        return redirect('dahsboard.html')
    return render(request, 'pages/update_fundamentals.html', {'project': project, "form": form})

Hi Ken,

I can’t get this to work still. It seems to only work when i add back the models.ForeignKey(Project, to_field='project_name' Then i can post to the database, but this breaks the check_exists function.

When i remove this models.ForeignKey(Project, to_field='project_name' and attempt to post i get a 200 and the body of the POST contains the form content but it doesn’t appear in the database.

I’m stuggling to debug it. I also change back the view to the single add_fundamentals view to see if that helped. but i still couldn’t get data added to database.

So for some reason models.ForeignKey(Project, to_field='project_name' is needed

I really dont know why.

Ok, taking a step back for a moment.

What is the difference between these two lines?

project_name = models.ForeignKey(Project, to_field='project_name', on_delete=models.CASCADE)

and

project_name = models.ForeignKey(Project, on_delete=models.CASCADE)

(Other than the obvious textual difference. I’m really asking what the significance is of the difference between these two.)

Mapping the ForeignKey to the field project_name in Projects?

Ok, so from a table level in the database, what would be the difference in the columns being generated?
(You could investigate this by creating a second field with a different name and without the to_name clause, makemigrations and migrate, and then examine the underlying table in the database.)

Its a int? and automatically generated?

Correct, the second field is an int.
What is the first field? (The original FK with the to_name clause.)

And what do you mean by “automatically generated”?

I mean its incremented automatically.
first field is a string?

The ForeignKey field? No.

What is your understanding of what a ForeignKey is?

Im not really sure, other than a way to link two tables together. Ill read up