How do I implement action={% url '......' %} in django-form - django

I want to know the equivalent using <form action={% url '......' %}> in django-form(i.e. using forms.ModelForm class).
How do I define the action url of my form in djano-form? it can be easily done in HTML using action attribute of form as action={% url....

The form action in views.py will run when you click <button type='submit'> Submit </button> in your <form>. If it's not what you want:
That is how you can trigger a view function from html :
views.py
def YourAction(request, arg):
# do something
return redirect('/anywhere') # you need to return something
urls.py
from .views import YourAction
urlpatterns = [
path('dosomething/<arg>', YourAction, name='action_name'),
]
your html
<form action='{% url 'action_name' arg %}'>
<button type='submit'> Submit! </button>
</form>
You don't have to use form. You can just use <a href='{% url 'action_name' arg %}'> Do Something! </a>

You can change it, also, in View (views.py):
from django.urls import reverse
from .models import YOUR_FORM_MODEL
def myView(request):
if request. Method == 'GET':
form = YOUR_FORM_MODEL()
form.helper.form_action = reverse('appname:testme')
mydata = {'form': form}
return HttpResponse(render(request, 'appname/custom_page.html', context=mydata))
and add in Your urls.py:
from django.urls import path
from . import views
app_name = 'appname'
urlpatterns = [
path('test-my-custom-form-send-path', views.myView, name='testme'),
]
in your template (custom_page.html):
{% extends 'appname/base_html_file.html' %}{% load crispy_forms_tags %}{% load static %}
{% crispy form %}

Related

Creating a login page with user Authentication & this happened : raise TemplateDoesNotExist(', '.join(template_name_list), chain=chain)

New in django. Learning how to create a login page with user Authentication. All is working, but when I put wrong password for checking that the loop is working properly or not. Know that the error is due to wrong assignment of url, but can't understand how to solve it.
I am using two apps one for login(name=trevalo_app) and another for all (name=MYapp)
trevalo_app/views.py
from django.shortcuts import render,redirect
from django.http import *
from django.contrib.auth import authenticate,login,logout
from django.contrib import messages
from .models import *
def login_user(request):
if request.method=='POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('index')
else:
messages.success(request,('There was an error in logining. Please Try again...'))
return redirect('login')
else:
return render(request,'login_user.html',{})
MYapp/index.html
<body>
{% include 'MYapp/navebar.html' %}
<center>
<h1>{{name}}</h1>
</center>
<div class="cotainer">
{% if messages %}
{% for message in messages %}
{{message}}
{% endfor %}
{% endif %}
</div>
{% block content %}{% endblock content %}
{% include 'MYapp/footer.html' %}
</body>
trevalo_app/urls.py
from django.urls import path,include
from . import views
urlpatterns = [
path('login_user', views.login_user,name='login_user'),
]
MYapp/urls.py
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('footer', views.footer, name='footer'),
path('navebar', views.navebar, name='navebar'),
]
trevalo_app/login_user.html
{% extends 'MYapp/index.html' %}
{% block content %}
<center>
<h3>login...</h3>
<hr>
</center>
<div class="container container-fluid ">
<form method=POST action="">
{% csrf_token %}
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label"> username</label>
<input type="text" name='username' class="form-control"
placeholder="username" aria-describedby="emailHelp">
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Password</label>
<input type="password" name='password' class="form-control" placeholder="password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
{% endblock %}
There are a few issues with your templates:
Use the correct directory structure for templates in your apps so that Django knows where to find them:
/ MYapp
- urls.py
- views.py
- ...
/ templates
/ MYapp
- index.html
/ trevalo_app
- urls.py
- views.py
- ...
/ templates
/ trevalo_app
- login_user.html
In your views pass the correct template path to the render:
def login_user(request):
if request.method=='POST':
...
else:
return render(request,'trevalo_app/login_user.html', {}) # The correct template path
Note that your code fails because in your trevalo_app/login_user.html template you are extending 'MYapp/index.html'. For this to work you must follow the directory structure Django is recommending so that it can find the correct template.
{% extends 'MYapp/index.html' %}

Django: custom button in admin change form return bad url for custom view function

I have problems to link my custom button from change_form.html to my view function.
pic : admin change form custom button
change_form.html
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block title %} Send Email {% endblock %}
{% block content %}
{% if request.resolver_match.url_name == 'requests_requests_change' %}
<div class="submit-row">
{% csrf_token %}
<a href="{% url 'requests:send-email' original.pk %}"
class="button" style="background-color: #F08000;float: left">Request Subscription
</a>
</div>
{% endif %}
{{ block.super }}
{% endblock %}
views.py
from django.shortcuts import render, redirect
def send_email(request, requests_id):
return redirect('') # or whatever to test the url
urls.py
from django.urls import path
from . import views
app_name = 'requests'
urlpatterns = [
path('<int:pk>/send-email/', views.send_email, name='send-email'),
]
main project urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', admin.site.urls), # admin site administration
path('requests/', include('requests.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
pic: error message
Any help would be great! Thanks!
I have found the solution on my own.
The issue was the url inside the template.
Worked with this one:
Template :
<a href="{% url 'admin:requests_requests_change' original.pk %}send-email/"
And the URL path:
path('<int:pk>/change/send-email/', views.send_email, name='send-email')

How do I trigger a Celery task from Django admin?

I have a model called Publication and I'd like to add a button to the list view in Django Admin which would allow triggering a Celery task.
admin.py:
from django.contrib import admin
from .models import Publication
class PublicationAdmin(admin.ModelAdmin):
change_list_template = "variants/admin_publication_list.html"
def update(self, request):
# trigger task
# redirect to admin list
admin.site.register(Publication, PublicationAdmin)
variants/admin_publication_list.html:
{% extends 'admin/change_list.html' %}
{% block object-tools %}
<li>
<a href="/admin/variants/publication/update/">
Update
</a>
</li>
{{ block.super }}
{% endblock %}
However when I press a button I only get a notice:
Publication with ID “update” doesn’t exist. Perhaps it was deleted?
Method name update or route name update is too generic and sometimes used by frameworks automatically, try naming it to match your functionality. revoke-publications or sync-publications.
admin.py:
from django.contrib import admin
from django.urls import path
from django.http import HttpResponseRedirect
from .models import Publication
from .tasks import your_celery_task
#admin.register(Publication)
class PublicationAdmin(admin.ModelAdmin):
change_list_template = "variants/admin_publication_list.html"
def get_urls(self):
urls = super().get_urls()
my_urls = [
path('update-publications/', self.publication_update),
]
return my_urls + urls
def publication_update(self, request):
result = your_celery_task.delay("some_arg")
self.message_user(
request,
f"Task with the ID: {result.task_id} was added to queue. Last known status: {result.status}"
)
return HttpResponseRedirect("../")
variants/admin_publication_list.html:
{% extends 'admin/change_list.html' %}
{% block object-tools %}
<div>
<form action="update-publications/" method="POST">
{% csrf_token %}
<button type="submit">Run Celery Task</button>
</form>
</div>
<br />
{{ block.super }}
{% endblock %}

Reverse for 'register' not found. 'register' is not a valid view function or pattern name

I'm trying to make a simple app that uses the django built-in User model. I have created a registration page, but when I run the server, I get this error at the index page. Here's the code I'm using:
Registration.html
<!DOCTYPE html>
{% extends "basic/base.html" %}
{% block title_block %}
<title>Registration</title>
{% endblock title_block %}
{% block body_block %}
<div class="jumbotron">
{% if registered %}
<h1>Thank you for registering</h1>
{% else %}
<h1>Register here!</h1>
<h3>Fill out the form: </h3>
<form enctype="multipart/form-data" method="post">
{% csrf_token %}
{{userForm.as_p}}
{{profileForm.as_p}}
<input type="submit" value="Register" name="">
</form>
{% endif %}
</div>
{% endblock body_block %}
Views.py for the 'register' method
def register(request):
registered = False
if(request.method == 'POST'):
userForm = forms.UserForm(data=request.POST)
profileForm = forms.UserProfileInfoForm(data=request.POST)
if((userForm.is_valid()) and (profileForm.id_valid())):
user = userForm.save()
user.set_password(user.password)
user.save()
profile = profileForm.save(commit=False)
profile.user = user
if('profileImage' in request.FILES):
profile.profileImage = request.FILES['profileImage']
profile.save()
registered = True
else:
print(userForm.errors, profileForm.errors)
else:
userForm = forms.UserForm()
profileForm = forms.UserProfileInfoForm()
return render(request, 'basic/registration.html', {'userForm':userForm, 'profileForm':profileForm, 'registered':registered})
This is the urls.py for the project
from django.contrib import admin
from django.urls import path, include
from basic import views
urlpatterns = [
path('', views.index, name='index'),
path('admin/', admin.site.urls),
path('basic/', include('basic.urls', namespace='basic'))
]
This is the urls.py for the basic app
from django.urls import path
from . import views
app_name = 'basic'
urlpatterns = [
path('register/', views.register)
]
And the link to the page in base.html
<a class="nav-link" href="{% url 'basic:register' %}">Register</a>
What can cause the error here?
You must include a name argument to the register route.
path('register/', views.register, name='register')
https://docs.djangoproject.com/en/2.1/topics/http/urls/#reverse-resolution-of-urls
try this (inside your html file)
<a class="nav-link" href={% url 'basic:register' %}>Register</a>
and your urls.py (inside your app) as this:
urlpatterns = [
path('register/', views.register,name='register'),
]
this method worked for me I was fasing the same issue.

Uploading and displaying an image in Django

I am currently learning Django. I am building a system that gets input from the user as image and throws back the damage level. I have the python files all caught up. But I am having difficulty doing the Django part.
How do I get an image as input from the user ?
And how will I throw back the result of the code that does the damage level prediction to the front end ?
Thanks in advance
To get images from user you can do as following. However getting data from request is not recommended way.
Views.py
from django.shortcuts import render, render_to_response
from django.core.files.storage import FileSystemStorage
def index(request):
if request.POST:
if request.method == 'POST' and request.FILES['image']:
uploaded_image = request.FILES['image']
fs = FileSystemStorage()
filename = fs.save(uploaded_image.name, uploaded_image)
uploaded_file_url = fs.url(filename)
code = get_code(uploaded_file_url)
return render_to_response("homepage.html", {"code": code})
else:
return render(request, "homepage.html")
Using this request.FILES['image'] we are getting a image from our form passed on post event.
In your template homepage.html
<form method="post" action="{% url 'code' %}" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="image" id="file-input" accept="image/x-png,image/jpeg,image/jpg"/>
<input type="submit" style="background: #0b0b0b" class="btn btn-secondary" value="Generate Caption"/>
<br><br>
<div style="background: #0b0b0b">
<a>Code for image is : {{ code }}</a>
</div>
</form>
{% url 'code' %} this will reverse the url by name as defined in urls.py. {% csrf_token %} is required for security reasons. enctype="multipart/form-data" is required to pass data like images, files etc. Input with name name="image" is what we are looking in request.FILES['image']. If you want change the name make your to change it everywhere.
And in your urls.py
from django.conf.urls import url
urlpatterns = [
url(r'^$', views.homepage, name='code'),
]
Also you can have look at Django forms for a better way.