Reputation: 185
I am trying to create an update view that allows users to update their data. I am trying to access the data by using primary keys. My problem is that I do not know the syntax to implement it.
models.py
class Detail(models.Model):
"""
This is the one for model.py
"""
username = models.ForeignKey(User, on_delete=models.CASCADE, null=True, default="")
matricno = models.CharField(max_length=9, default="")
email = models.EmailField(default="")
first_name = models.CharField(max_length=200, default="")
last_name = models.CharField(max_length=255, default="")
class Meta:
verbose_name_plural = "Detail"
def __str__(self):
return self.first_name+ " "+self.last_name
views.py
def success(request):
return render(request, "success.html", {})
@login_required(login_url="signin")
def details(request):
form = Details()
if request.method == "POST":
form = Details(request.POST)
if form.is_valid():
detail = form.save(commit=False)
detail.username = request.user
detail.save()
return redirect(success)
else:
form = Details(initial={"matricno":request.user.username})
return render(request, "details.html", {"form":form})
def updatedetails(request, pk):
detail = Detail.objects.get(id=pk)
form = Details(instance=detail)
if request.method == "POST":
form = Details(request.POST, instance=detail)
if form.is_valid():
form.save()
return redirect(success)
return render(request, "details.html", {"form":form})
urls.py
from django.urls import path
from . import views
urlpatterns = [
path("details/", views.details, name="details"),
path("success/", views.success, name="success"),
path("edit/<str:pk>/", views.updatedetails, name="updatedetails"),
]
my html template
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Success</title>
</head>
<body>
<h1>Thank You for Filling Out the Form</h1>
<p><a href="/edit/{{request.detail.id}}/">Click Here To Edit</a></p>
</body>
</html>
So what I am trying to figure out is how to call the primary key in my template.
Upvotes: 0
Views: 429
Reputation: 8837
At first, I'd recommend you to change <str:pk>
to <int:pk>
in updatedetails
path so urls.py should be:
from django.urls import path
from . import views
urlpatterns = [
path("details/", views.details, name="details"),
path("success/<int:pk>/", views.success, name="success"),
path("edit/<int:pk>/", views.updatedetails, name="updatedetails"),
]
Secondly, I'd recommend you to use get_object_or_404()
instead of get()
and also if you see it correctly you are also missing ""
in redirect(success)
that should be redirect("success")
so views.py should be:
from django.shortcuts import get_object_or_404
def updatedetails(request, pk):
detail = get_object_or_404(Detail,id=pk)
form = Details(instance=detail)
if request.method == "POST":
form = Details(request.POST, instance=detail)
if form.is_valid():
form.save()
return redirect("success", args=(pk))
return render(request, "details.html", {"form":form})
@login_required(login_url="signin")
def details(request):
form = Details()
if request.method == "POST":
form = Details(request.POST)
if form.is_valid():
detail = form.save(commit=False)
detail.username = request.user
detail.save()
return redirect(success,args=(detail.id))
else:
form = Details(initial={"matricno":request.user.username})
return render(request, "details.html", {"form":form})
def success(request,pk):
return render(request, "success.html", {"id":pk})
Then, in the template you can use url tags
and pass id
to updatedetails
view as:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Success</title>
</head>
<body>
<h1>Thank You for Filling Out the Form</h1>
<p><a href="{% url 'updatedetails' id %}">Click Here To Edit</a></p>
</body>
</html>
Upvotes: 1
Reputation: 2880
Answer to the original question
How can I access primary key in template tag?
Well, you have to pass it to the view that renders the template, either through the context, or in this case, since you need it in the success page, which you are getting to via a redirect, send it as a parameter in your redirect.
Second, if you are trying to create a form from a model, then use a ModelForm. This you do not do just by setting a form variable equal to a model instance. You do this by creating a file called forms.py:
# forms.py
from django.forms import ModelForm
from .models import Detail
class DetailForm(ModelForm):
class Meta:
model = Detail
# Include below the fields from the Detail model you
# would like to include in your form
fields = ['username', 'matricno', 'email', 'first_name', 'last_name', ]
Then in your views you can access this form:
#views.py
from .models import Detail
from .forms import DetailForm
def success(request, pk):
# NOTE that here you must receive the pk
return render(request, "success.html", {'pk': pk})
@login_required(login_url="signin")
def details(request):
form = DetailForm()
if request.method == "POST":
form = DetailForm(request.POST)
if form.is_valid():
detail = form.save(commit=False)
detail.username = request.user
detail.save()
# NOTE: here you can send the detail primary key, pk, or id
# to the success view where you are trying to use it
return redirect('success', pk=detail.pk)
else:
form = Details(initial={"matricno": request.user.username})
return render(request, "details.html", {"form": form})
def updatedetails(request, pk):
detail = Detail.objects.get(id=pk)
form = DetailForm(instance=detail)
if request.method == "POST":
form = Details(request.POST, instance=detail)
if form.is_valid():
form.save()
return redirect('success', pk=detail.pk)
return render(request, "details.html", {"form":form})
Note how you can send the primary key to the success template in the redirect. That is the answer to the original question.
Now you can access the primary in your template simply:
<!--html template -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Success</title>
</head>
<body>
<h1>Thank You for Filling Out the Form</h1>
<p><a href="{% url 'updatedetails' pk %}">Click Here To Edit</a></p>
</body>
</html>
Since the success view needed to be changed to get the primary key, we have to modify the urls.py so that it can receive it:
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path("details/", views.details, name="details"),
path("success/<int:pk>/", views.success, name="success"),
path("edit/<int:pk>/", views.updatedetails, name="updatedetails"),
]
Upvotes: 1
Reputation: 11
Try using
href="{% url 'updatedetails' pk=request.detail.id %}"
Let me know if that works. This will look for the path name updatedetails located in your urlpatterns and provide the id as the key. I'm somewhat new at this also, so i'm hoping this helps and is correct.
Upvotes: 0