Django update view only seems to work with regex urls - django

I am getting my hands dirty with Django and have a simple use case in which i have to create a function based view for updating a Model. Below is my function based view function:
def update_post(request, id=None):
obj = get_object_or_404(PostModel, id=id)
form = PostModelForm(request.POST or None, instance=obj)
if form.is_valid():
obj = form.save(commit=False)
print(f"The object that i am going to save is {form.cleaned_data}")
obj.save()
messages.success(request, f"Updated object with id {id}")
return HttpResponseRedirect(f"/blog/read/{id}")
context = {
"form": form
}
return render(request, "blog/update-post.html", context)
Below is my update-post.html:
<html>
<form method="POST" action="."> {% csrf_token %}
{{form.as_p}}
<input type="submit" value="Change">
</form>
</html>
And this is my urls.py file :
from django.urls import path, include
from django.conf.urls import url
from .views import list_posts, read_post, create_post, update_post
app_name = "blog"
urlpatterns = [
path('posts/', list_posts, name="list"),
path('read/<int:id>', read_post, name="read"),
path("create/", create_post, name="create"),
#url(r'^(?P<id>\d+)/edit/$', update_post, name="update")
path("update/<int:id>", update_post, name="update"),
]
The update view only seems to work when i use the above regex url pattern for editing the post .
Otherwise i get the below error message:
Can someone please tell me where i am going wrong with this.

Related

Reverse for 'entrypage' with no arguments not found. 1 pattern(s) tried: ['wiki/(?P<title>[^/]+)$']

VIEWS.PY
from django.shortcuts import render
from django.shortcuts import redirect
from django.urls import reverse
from django.http import HttpResponseRedirect
from django import forms
import markdown2
from . import util
class AddPageForm(forms.Form):
title = forms.CharField(max_length=20)
content = forms.CharField(widget=forms.Textarea(
attrs={
"class": "form-control",
"placeholder": "Tell us more!"
})
)
def add_page(request):
if request.method == "POST":
form = AddPageForm(request.POST)
entries = util.list_entries()
if form.is_valid():
title = form.cleaned_data['title']
content = form.cleaned_data['content']
util.save_entry(title, content)
for entry in entries:
if title.upper() == entry.upper():
return render(request, "encyclopedia/errorpage.html")
else:
return HttpResponseRedirect(reverse('encyclopedia:entrypage'))
else:
return render(request, "encyclopedia/addpage.html", {
"form": AddPageForm()
})
URLS.PY
app_name = "encyclopedia"
urlpatterns = [
path("", views.index, name="index"),
path("wiki/<str:title>", views.entry_page, name="entrypage"),
path("search", views.search, name="search"),
path("add_page", views.add_page, name="addpage"),
]
ADDPAGE.HTML
<form action="{% url 'encyclopedia:addpage' %}" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" class="btn btn-secondary">
</form>
LAYOUT.HTML
<div>
Create New Page
</div>
<div>
I have tried updating the urls and the views to this but i keep getting error responses
path("add_page/<str:title>", views.add_page, name="addpage"),
def add_page(request, title):
Please advise where this error response could be coming from as the above edits is what i saw in some other stackoverflow responses to clear the error but this didn't work for me.
Thank you
When you make a redirect to entrypage, you need to specify the title, so:
from django.shortcuts import redirect
def add_page(request):
if request.method == "POST":
form = AddPageForm(request.POST)
entries = util.list_entries()
if form.is_valid():
title = form.cleaned_data['title']
content = form.cleaned_data['content']
util.save_entry(title, content)
for entry in entries:
if title.upper() == entry.upper():
return render(request, "encyclopedia/errorpage.html")
# specify title &downarrow;
return redirect('encyclopedia:entrypage', title=title)
# …
I would also strongly advise to make use of a database, and not fetch all entries from the utility: a database is optimized to search effective, whereas accessing the list of files takes linear time to search. If you define a database model, you can add db_index=True [Django-doc] to build an index which can boost searching enormously.

how do i get the specific profile of user that created a post in django

i ve been stuck for days now trying to find a way to solve this, i am trying to return the specific profile of user that created a post in django but when i try it i get a VectorDetails() missing 1 required positional argument: 'pk'. Let me show my views.py and urls.py
Views.py (views for showing the posts and returning specific users )
def VectorDetails(request, pk, vectors_slug):
vector = get_object_or_404(Vectors, slug=vectors_slug)
vectors = Vectors.objects.filter(status='published').order_by('?')[:6]
creators = Profile.objects.filter(creator=True)
creator = Profile.get_object_or_404(pk=pk)
context = {
'vector': vector,
'vectors': vectors,
'creators':creators
}
return render(request, 'vector-details.html', context)
views.py (view for returning the specific user)
from django.shortcuts import render, get_object_or_404
from userauths.models import Profile
def creator_profile_detail(request, pk):
creators = get_object_or_404(Profile, pk=pk)
context = {
'creators': creators
}
return render(request, 'creator_profile_detail.html', context)
urls.py
from django.urls import path
from . import views
app_name = 'creators'
urlpatterns = [
path('<int:pk>', views.creator_profile_detail, name="creator_profile_detail"),
]
template.html
<div class="premium_uyhau mt-4">
<div class="urip_widget_avater">
<img src="{{vector.creator.profile.image.url}}" class="img-fluid circle" alt="">
<div class="veryfied_author"><img src="assets/img/verified.svg" class="img-fluid" width="15" alt=""></div>
</div>
<div class="widget_avater_124">
<h4 class="avater_name_214">{{vector.creator|title}}</h4>
<span>{{vector.creator.profile.bio|title}}</span>
</div>
</div>
This was how i fixed the bug
def profile(request, username):
if request.user.is_authenticated:
user = get_object_or_404(User, username=username)
profile = Profile.objects.get(user=user)
...
Then in main project urls.py add
path('u/<username>/', profile, name="profile"),

Django: form works in index but not in a particular page

I'm having multiple forms around my website.
However, a have a particular form that is working in the home page (index.html), but when coping this particular form in a section of my site it doesn't work anymore (on this section, if I return to home everything works as expected).
What am I missing?
Views.py:
from django.shortcuts import render, HttpResponse, HttpResponseRedirect
from .models import Treasure, TamaniosCantidades
from .forms import TreasureForm, TamaniosCantidadesForm, LoginForm
from django.contrib.auth import authenticate, login, logout
# Create your views here.
def index(request):
treasures = Treasure.objects.all()
form = TreasureForm()
tamanioscantidades_form = TamaniosCantidadesForm()
return render(request, 'main_app/index.html', {'treasures': treasures,
'form': form,
'tamanioscantidades_form': tamanioscantidades_form})
def productos(request):
treasures = Treasure.objects.all()
form = TreasureForm()
return render(request, 'main_app/productos.html', {'treasures': treasures,
'form': form})
def die_cut(request):
tamanioscantidades_form = TamaniosCantidadesForm()
return render(request, 'main_app/die-cut-stickers.html', {'tamanioscantidades_form': tamanioscantidades_form})
def post_tamanioscantidades(request):
form = TamaniosCantidadesForm(request.POST)
if form.is_valid():
tamanioscantidades = TamaniosCantidades(tamanios=form.cleaned_data['tamanios'],
cantidades=form.cleaned_data['cantidades'])
# tamanioscantidades = tamanioscantidades_form.save(commit = False)
# tamanioscantidades.usuario = request.user
tamanioscantidades.save()
return HttpResponseRedirect('/')
def post_treasure(request):
form = TreasureForm(request.POST)
if form.is_valid():
treasure = Treasure(name=form.cleaned_data['name'],
value=form.cleaned_data['value'])
treasure.save()
return HttpResponseRedirect('/')
urls.py:
app_name = 'main_app'
urlpatterns = [
path('', views.index),
path('productos/', views.productos),
path('productos/die-cut-stickers', views.die_cut, name='die-cut-stickers'),
path('post_url/', views.post_treasure, name='post_treasure'),
path('post_url_tamanioscantidades/', views.post_tamanioscantidades, name='post_tamanioscantidades'),
]
*html**:
<div class="col-md-6 border border-primary rounded border-3">
<div class="m-5">
<div class="row">
<form action="post_url_tamanioscantidades/" method="post">
{% csrf_token %}
{{ tamanioscantidades_form.as_p }}
<input type="submit" value="Submit"/>
</form>
</div>
</div>
As I said, this form works in home, but when coping the same code in a section of my site the submit button does not save the form in database.
It returns:
Page not found (404)
Request Method: POST
Request URL: http://127.0.0.1:8000/productos/post_url_tamanioscantidades/
Using the URLconf defined in gallito.urls, Django tried these URL patterns, in this order:
admin/
productos/
productos/die-cut-stickers [name='die-cut-stickers']
post_url/ [name='post_treasure']
post_url_tamanioscantidades/ [name='post_tamanioscantidades']
accounts/
The current path, productos/post_url_tamanioscantidades/, didn't match any of these.
The problem is the form is being submitted to http://127.0.0.1:8000/productos/post_url_tamanioscantidades/ which does not exist instead you want it to submit at http://127.0.0.1:8000/post_url_tamanioscantidades/
So in your form html start the form action with /
<form action="/post_url_tamanioscantidades/" method="post">

How to make form in _base.html

I need to make form in header section of site. This form will be available for all pages in my site. For example, i have in my app "accounts":
forms.py
class SignupForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ('phone',)
views.py
def signup(request):
form = SignupForm(request.POST or None)
# CODE #
ctx = {
'form': form,
}
return render(request, 'accounts/signup.html', ctx)
urls.py
from django.urls import path
from . import views
app_name = 'accounts'
urlpatterns = [
path('signup/', views.signup, name='signup'),
]
accounts/signup.html
{% block signup %}
{{ form }}
{% endblock %}
If I add{% include 'accounts/signup.html' %} to my _base.html, I don't, get form - {{ form }} but all other content will be included.
And can you tell me how exactly get form for all pages in site? Is it the correct approach?
Use a custom templatetag to initialize an empty form and display it from wherever you want - just make sure the action attribute of the HTML <form> tag points to your signup view.

Form Field not displaying in Template

I'm new to Django and am having a bit of trouble with forms. I'm trying to display a single text input so that users can enter their phone number and it will be sent to my email. I'm actually going to have it stored in a postgre database but want to get the basics down first. The submit button is being displayed but the text input field isn't. I tried putting the forms.py inside of the views.py to see if the PhoneForm() function and file wasn't importing but that didn't do anything.
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect
from django.core.mail import send_mail
from .forms import PhoneForm
# Create your views here.
def index(request):
# Render the index.html template with a context dictionary
return render(request, "index.html")
def get_number(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
#create a form instance
form = PhoneForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(
cd['phone_form'],
['siteadmin#example.com'],
)
return HttpResponseRedirect('/thanks/')
else:
form = PhoneForm()
return render(request, 'index.html', {'form': form})
index.html
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
forms.py
from django import forms
class PhoneForm(forms.Form):
phone_form = forms.CharField(widget=forms.TextInput())
EDIT: Adding urls.py (the one in the app)
from django.conf.urls import include, url
from django.contrib import admin
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^$', views.get_number, name='get_number'),
]
Both urls in urls.py have the same expression r'^$' and django looks for them in order, therefore the first one (index) will always be selected. This links to the index view not the get_number view. This means the form is not passed to the template and the form does not show up.
To solve this move url(r'^$', get_number), to the top of 'urlpatterns'.
Change from {{form}} to {{form.phone_form}} in index.html