I have 2 models Project and Fundamentals the fundamentals is linked via FK to Project I have a view that allows me to add data to the fundamentals table and also a view to update the fundamentals when data already exists.
But when I try to retrieve the data i pass is the project_id in the request. But what seems to be happening is that if i have 5 projects and from project 5 i add fundamentals data the data in the table has an ID of 1 being that this is the first entry in the fundamentals table. but my project id is 5 being the 5th project
If i then go to project 1 and add fundamentals it will return data from project 5.
should i be sending in a different param in the request. (request, project_name) ??
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 = FundamentalsForm(request.POST)
if form.is_valid():
fundamental = form.save(commit=False)
fundamental.project_name = project
fundamental.save()
return redirect('dashboard.html')
else:
form = FundamentalsForm()
return render(request, 'pages/add_fundamentals.html', {'project': project, "form": form})
def update_fundamentals_view(request, project_id):
project = get_object_or_404(Fundamentals, pk=project_id)
form = FundamentalsForm(request.POST or None, instance=project)
if form.is_valid():
form.save()
return redirect('/')
return render(request, 'pages/update_fundamentals.html', {'project': project, "form": form})
From a general approach, I would recommend removing the function fundamentals_view as a proxy of calling add or update. When rendering the template, the app should know if the action should be an add or an update. In the add view, you can verify that one indeed doesn’t exist before creating it for a project and redirect them to the update page. However, you don’t have to do this.
I suspect something is wrong here. The get_object_or_404 is operating on the Fundamentals model, but the variable is named project. Additionally, the project_id being passed in was used to fetch the Project instance in fundamentals_view. I would assume you want this to be:
However, if that’s a foreign key from Fundamental to Project, then that will error when there is more than one Fundamental for a Project. If there should only ever be one, you should consider using a OneToOneField for the relationship. If there should be more than one, you’ll need to change your approach to specify an unique identifier for the Fundamental that should be updated or otherwise determine which Fundamental instance to update (such as most recently created).
There should only ever be 1 entry in fundamentals for a project.
I have a FK from fundamental to project project_name = models.ForeignKey(Project, on_delete=models.CASCADE)
What i dont understand is if i am querying project_id , is that the ID of the entry in the Project model which would be created based on a first come first serve. So how will the Project.ID ever relate to the Fundamental.ID unless both entries are created at the same time?
Or is there something happening in the background that knows what project.id relates to which fundamental.id?
You are creating a ForeignKey relationship, not a One-to-One relationship. The ID fields of those two tables have no relationship to each other.
Your link between the two is the ForeignKey field of the Fundamentals table.
This means that, given a Fundamentals object named fundamental, your access to the Project object is fundamental.project.
Again, since this is an FK relationship, your access to all the related Fundamentals object from a Project object is project.fundamentals_set.all(). If you just want one object (since there should only be one even thought the database structure allows otherwise), then you could use project.fundamentals_set.all().first() Or, if you have the Project’s id value as id_value, you could query it as Fundamentals.objects.filter(project_name_id=id_value)
Im sure this is really simple stuff. but jeez i am confused.
This line: check_exist = Fundamentals.objects.filter(project_name_id=project_id)
Is that checking that the project_name_id in the fundamentals model (which is the ID of the entry in fundamentals ??) equals the project_id past in the request exists?
But it can’t be, because it works, but the project_id being past in via the request is 1 and the entry in fundamentals is 7.
So i think i am misunderstanding this project_name_id
You have a field in Fundamentals called project_name. It is the FK to Project. In reality, the database column name (visible to Django) is project_name_id.
So, assuming that the project_id being supplied is 1, this query is answering the question:
What are all the Fundamental objects that exist, that are referring to the Project object with an id of 1?
It has absolutely nothing to do with the ID field of the Fundamental object itself.
You’re on the right track - but follow this line of thinking a little bit further.
Why do you think a get_object_or_404 is the right call here? What are you trying to protect against? And is it necessary to do that if you’ve gotten to this point?
Also, I strongly suggest you change your variable names to properly represent the type of object being processed.
I don’t think I’d say it’s wrong as much as I would describe it as potentially-confusing. It may lead someone looking at this code to drawing an incorrect conclusion about this function. (Then again, it may not.)
Nope, that’s exactly what it’s doing.
That is an opinion I have, yes. (That’s all it is, just an opinion.) It’s not a question of correctness. It’s an issue of code-clarity and obviousness.