I am trying to override the default django-allauth templates and use django-crispy-forms from improved rendering but having no luck getting the forms to actually submit, meaning I press submit and nothing happens.
Here is my settings.py:
INSTALLED_APPS = [
'about.apps.AboutConfig',
'content.apps.ContentConfig',
'users.apps.UsersConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
]
...
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# All Auth settings
AUTHENTICATION_BACKENDS = (
# Needed to login by username in Django admin, regardless of `allauth`
'django.contrib.auth.backends.ModelBackend',
# `allauth` specific authentication methods, such as login by e-mail
'allauth.account.auth_backends.AuthenticationBackend',
)
SITE_ID = 1
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
Here is my custom template:
{% extends "about/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% block navbar %}{% endblock %}
<div class="site-section mb-5">
<div class="container">
<div class="form-register">
<form method="POST" class="signup" id="signup_form" action="{% url 'account_signup' %}">
{% csrf_token %}
<legend>Signup</legend>
<div class="form-group">
{{ form | crispy }}
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Sign Up">
</div>
</form>
</div>
</div>
</div>
{% endblock %}
I know the template is in the correct location and correctly overriding the django-allauth default templates because it renders, but why won't the submit button submit the form? I also know everything with django-allauth is working, because if I remove the custom template and use the django-allauth template, it will submit the form and redirect properly.
I'm doing this myself now. Really, I'd need to see the data for the {{ form|crispy }} to know exactly what is going on.
However, it isn't enough to simply render a similar form and submit. allauth has stuff running in the background (some of which is not entirely known to me).
I would recommend pulling the templates from the allauth github and editing them directly, removing tags you know are sure you don't need, like "extends 'allauth/base.html', headings, etc.. They're found Here.
Then, I followed the details of the second method from this answer to add the forms as context processors (most useful for my case use):
2. Contex processor
a) Make folder your_project/your_app/context_processor. Put there 2 files - __init__.py and login_ctx.py
b) In login_ctx.py add:
from allauth.account.forms import LoginForm
def login_ctx_tag(request):
return {'loginctx': LoginForm()}
c) In project's SETTINGS add your_app.context_processors.login_ctx.login_form_ctx' inTEMPLATES`
section. Something like:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'templates', 'allauth')],
'APP_DIRS': True,
'OPTIONS': {
'debug': DEBUG,
'context_processors': [
'your_app.context_processors.login_ctx.login_form_ctx', # <- put your
processor here
'django.template.context_processors.debug',
# [...other processors...]
],
},
},
]
d) In your *.html where you need add the next:
{% if not user.is_authenticated %}
<form action="{% url 'account_login' %}" method="post">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.get_full_path }}" />
{{ loginctx }}
<button type="submit">Login</button>
</form>
{% else %}
{# display something else here... (username?) #}
{% endif %}
So if you are rendering your own forms, I would recommend rendering the very same allauth forms instead in the custom template.
Add the crispy tag and all is good.
Related
I am working on the login/logout functionality of a basic Django website. (CS50's Pinocchio's Pizza). The logout path is being injected into the URL & I am unsure as to why. My navbar links to the home page, yet when I click on it it redirects me to the logout page. Any other link I click, that link's path is added to the URL but attached to the logout path.
For example, clicking on the login button of my site, whose path is login_default, the url becomes:
http://127.0.0.1:8000/logoutlogin_default
Trying to click the link in the navbar that should link to the index page gets me:
http://127.0.0.1:8000/logout
The folder "orders" is an app which "pizza" is made aware of. All html pages are inside orders/templates/orders.
This is orders/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name = "index"),
path("register_default", views.register_default, name = "register_default"),
path("register_setup", views.register_setup, name = "register"),
path("login_default", views.login_default, name = "login_default"),
path("login_setup", views.login_setup, name = "login"),
path("logout", views.logout_view, name="logout"),
]
In pizza/urls.py, the Orders app's URLs have been made known:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("", include("orders.urls")),
path("register_default", include("orders.urls")),
path("register_setup", include("orders.urls")),
path("login_default", include("orders.urls")),
path("login_setup", include("orders.urls")),
path("logout", include("orders.urls")),
path("admin/", admin.site.urls),
]
This is orders/views.py
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
# Create your views here.
def index(request):
# If user is not logged in
if not request.user.is_authenticated:
return render(request, "orders/index.html", {"message": None})
context = {
"user": request.user
}
return render(request, "orders/index.html", context)
def register_default(request):
return render(request, "orders/register.html")
def register_setup(request):
firstName = request.POST["userFirstName"]
lastName = request.POST["userLastName"]
email = request.POST["userEmail"]
pw = request.POST["userPW"]
user = User.objects.create_user(firstName, email, pw)
user.save()
return HttpResponseRedirect(reverse("index"))
def login_default(request):
return render(request, "orders/login.html")
def login_setup(request):
username = request.POST["loginName"]
password = request.POST["loginPW"]
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return HttpResponseRedirect(reverse("index"))
else:
return render(request, "orders/login.html", {"message": "Invalid Credentials"})
def logout_view(request):
logout(request)
return render(request, "orders/login.html", {"message": "Logged Out"})
This is base.html, which all other templates are based off of.
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}{% endblock %}
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<nav class="navbar navbar-expand-md bg-light">
Pinocchio's Pizza
<ul class="navbar-nav">
{% if message %}
<li class="nav-item">
Log Out
</li>
{% else %}
<li class="nav-item">
Log In
</li>
<li class="nav-item">
Sign Up
</li>
{% endif %}
</ul>
</nav>
{% block body %}{% endblock %}
</body>
</html>
This is login.html
{% extends "orders/base.html" %}
{% block title %}Log In{% endblock %}
{% block body %}
{% if message %}
<h1 class="text-danger">{{ message }}</h1>
{% endif %}
<div class="container-fluid">
<div class="row">
<div class="col-md-6 mx-auto mt-4">
<form action="{% url 'login' %}" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="loginName">First Name</label>
<input type="text" name="loginName" id="loginName" class="form-control">
</div>
<div class="form-group">
<label for="loginPW">Password</label>
<input type="password" class="form-control" name="loginPW" id="loginPW">
</div>
<button class="btn btn-success" type="submit">Log In</button>
</form>
</div>
</div>
</div>
{% endblock %}
This is pizza/settings.py
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'i0&iq&e9u9h6(4_7%pt2s9)f=c$kso=k$c$w#fi9215s=1q0^d'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'orders.apps.OrdersConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'pizza.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'pizza.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = '/static/'
Try changing pizza/urls.pyto the following:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("", include("orders.urls")),
path("admin/", admin.site.urls),
]
the reason is the "" path should automatically include all the urls in orders.urls. Here is a link to the documentation: https://docs.djangoproject.com/en/2.2/topics/http/urls/#including-other-urlconfs
Another thing that I noticed that helps catch bugs is to include a / at the end of urls so in your orders/urls.py you can change it to the following.
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name = "index"),
path("register_default/", views.register_default, name = "register_default"),
path("register_setup/", views.register_setup, name = "register"),
path("login_default/", views.login_default, name = "login_default"),
path("login_setup/", views.login_setup, name = "login"),
path("logout/", views.logout_view, name="logout"),
]
Could anyone of you please help me to implement LDAP authentication using Django. I want to develop a web application which should allow users to access the application post LDAP authentication. I have coded the basic things but I get some failures.
Settings.py
"""
Django settings for HandBook project.
Generated by 'django-admin startproject' using Django 2.1.7.
For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""
import os
import ldap
from django_auth_ldap.config import LDAPSearch
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
AUTH_LDAP_SERVER_URI = "serverIp"
AUTHENTICATION_BACKENDS = ('django_auth_ldap.backend.LDAPBackend')
AUTH_LDAP_CONNECTION_OPTIONS = {
ldap.OPT_REFERRALS: 0
}
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '4xkkb*m!&#^xzhkpe6#gxe#xeee0ug3q0h$#-)#lv8+0dqpid*'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ["192.168.113.75"]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'NewHandBook.apps.NewhandbookConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
]
ROOT_URLCONF = 'HandBook.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'HandBook.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = '/static/'
Views.py
from django.shortcuts import render
from django.contrib.auth import authenticate, login
from django.template import RequestContext
from django.shortcuts import render_to_response
def login(request):
return render(request, 'login/login.html')
def login_user(request):
username = password = ""
state = ""
if request.POST:
username = request.POST.get('username')
password = request.POST.get('password')
print(username, password)
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return render(request, 'login/base.html', {'state': state, 'username': username})
else:
return render(request, 'login/login.html', {'state': state, 'username': username})
)
login.html
{% extends 'login/base.html' %}
{% load static %}
<html>
<head>
<title>Login</title>
</head>
<body>
{% block body %}
<form method="post" action="/NewHandBook/validate/">{% csrf_token %}
<div class="container">
<div class="row">
<div class="col-md-10 offset=md-1">
<div class="row">
<div class="col-md-5 register-left "><br><br>
<img style="width: 350px;position: absolute;margin-left: -350px;margin-top: -80px"
src="{% static 'images/gar.png' %}">
<h1 style="font-family: Brush Script MT;font-size: 70px;margin-top: 45px;margin-left: -342px">
HandBook.</h1>
<p style="font-family: Courier New;margin-top: -20px;margin-left: -359px "><i
class="fas fa-shield-alt"></i> Secure <i
class="far fa-share-square"></i> Share <i class="far fa-smile-beam"></i> Smile
</p>
</div>
<div class="col-md-7 register-right">
<h2 style="font-family: Courier;color: azure">Login Here</h2>
<h7 style="font-family: Courier;font-size: 13px;color: aliceblue">
<h7 style="color: red">*</h7>
Please use your system credentials
</h7>
<div class="register-form">
<div class="form-group">
<input type="text" name="username" class="form-control" placeholder="User name"
style="font-family: Courier">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" placeholder="Password"
style="font-family: Courier">
</div>
<input type="reset" class="btn btn-primary" value="Reset">
<button type="submit" class="btn btn-primary"> Login Now</button>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
{% endblock %}
</body>enter code here
</html>## Heading ##
I get below error when i run my project
exception
Could anyone of you please help me here.
My use case:
user should be able to land on some home page after a successful login or should land back on same login page if provided credentials are invalid.
The error indicates that you are passing a single Python path where you should actually pass a list of Python paths, i.e. django.some.module.path instead of ['django.some.module.path']
Django then iterates over the string, and tries to import each character. In case of django.some.module.path, Django tries to import d, which gives you the error you are seeing.
To pinpoint the exact source of the error, you have to provide the complete traceback. You can click on 'Switch to copy-and-paste view' on the Debug Error page.
Update:
Here is your error:
AUTHENTICATION_BACKENDS = ('django_auth_ldap.backend.LDAPBackend')
Single entry tuples need a comma, like this:
AUTHENTICATION_BACKENDS = ('django_auth_ldap.backend.LDAPBackend',)
Start using the default LoginView
def login(request):
return LoginView.as_view(template_name='login.html')(request)
This shall work. If it does now implement your customized login method in a LoginView class...
I wrote a django web application and now I need to translate it to english. I followed the documentation but I keep getting this strange error:
ImproperlyConfigured at /i18n/setlang/ settings.DATABASES is
improperly configured. Please supply the ENGINE value. Check settings
documentation for more details. Request Method: POST Request
URL: http://192.92.149.139:8000/i18n/setlang/ Django Version: 2.0.3
Exception Type: ImproperlyConfigured Exception Value:
settings.DATABASES is improperly configured. Please supply the ENGINE
value. Check settings documentation for more details. Exception
Location: /home/mwon/venvs/arquivo/lib/python3.6/site-packages/django/db/backends/dummy/base.py
in complain, line 20 Python
Executable: /home/mwon/venvs/arquivo/bin/python3.6 Python
Version: 3.6.4 Python Path: ['/home/mwon/digitalocean/website_dev',
'/home/mwon/venvs/arquivo/lib/python36.zip',
'/home/mwon/venvs/arquivo/lib/python3.6',
'/home/mwon/venvs/arquivo/lib/python3.6/lib-dynload',
'/usr/lib/python3.6',
'/home/mwon/venvs/arquivo/lib/python3.6/site-packages',
'/home/mwon/venvs/arquivo/lib/python3.6/site-packages/django_styleguide-1.2.5-py3.6.egg',
'/home/mwon/venvs/arquivo/lib/python3.6/site-packages/Markdown-2.6.11-py3.6.egg',
'/home/mwon/venvs/arquivo/lib/python3.6/site-packages/bs4-0.0.1-py3.6.egg',
'/home/mwon/venvs/arquivo/lib/python3.6/site-packages/beautifulsoup4-4.6.0-py3.6.egg',
'/home/mwon/venvs/arquivo/lib/python3.6/site-packages/duc_preprocess-1.0-py3.6.egg',
'/home/mwon/venvs/arquivo/lib/python3.6/site-packages/simple_cnlp-1.0-py3.6.egg',
'/home/mwon/venvs/arquivo/lib/python3.6/site-packages/django_mongoengine-0.3-py3.6.egg']
Server time: Qua, 5 Set 2018 11:21:17 +0000
EDIT: and the settings.DATABASES:
{
'default': {
'ENGINE': 'django.db.backends.dummy',
'ATOMIC_REQUESTS': False,
'AUTOCOMMIT': True,
'CONN_MAX_AGE': 0,
'OPTIONS': {},
'TIME_ZONE': None,
'NAME': '',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
'TEST': {
'CHARSET': None, 'COLLATION': None, 'NAME': None, 'MIRROR': None
}
}
}
This is my urls.py:
urlpatterns = [
path('i18n/',include('django.conf.urls.i18n')),
]
urlpatterns += i18n_patterns(
path('admin/',admin.site.urls),
path('',include('arquivo.urls')),
prefix_default_language = True
)
and settings.py:
LANGUAGE_CODE = 'pt'
LANGUAGES = (
('en', 'English'),
('pt', 'Portuguese'),
)
USE_I18N = True
LOCALE_PATHS = [
os.path.join(BASE_DIR,'locale')
]
The translation seems to be working fine. The problem was when I included a form to select the language. I used the example code from documentation:
{% load i18n %}
<form action="{% url 'set_language' %}" method="post">{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}">
<select name="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<input type="submit" value="Go">
</form>
Ok, so the problem was related with sessions. I'm using a MongoDB database with Django-MongoEngine and didn't turn on sessions support. So just added these two lines of code
SESSION_ENGINE = 'django_mongoengine.sessions'
SESSION_SERIALIZER = 'django_mongoengine.sessions.BSONSerializer'
to settings.py and everything started to work fine.
Created a set of forms for a simple model. When I am try to change the model object data in the form and save these changes in the database, the new data is not saved as a result, and a redirect to the form page with the same data occurs, although at least messages about the success or failure of the operation should be output. The terminal does not return any errors, it is written in the logs that the correct request was sent, the test server works without drops in normal mode. There is an opinion that the reason for this is a refusal to validate, but for what reason this happens and where exactly the error is hidden, it is not yet possible to understand.
And
When I clicked a "save" button, see this message in terminal (see below):
[25/Aug/2017 18:03:06] "GET
/categories/?csrfmiddlewaretoken=igSZl3z8pcF9qRGaMts9hG3T9dyaIpVvAxB672R34bmKvGYd6pymjmtwyEgDHGg2&form-TOTAL_FORMS=6&form-INITIAL_FORMS=5&form-MIN_NUM_FORMS=0&form-MAX_NUM_FORMS=1000&form-0-id=1&form-0-name=fhdrhddh&form-0-order=0&form-1-id=2&form-1-name=gdegasf&form-1-order=6&form-2-id=3&form-2-name=dfdgbsbgsdgs&form-2-order=2&form-3-id=4&form-3-name=dbgsgbasedgbaedvg&form-3-order=3&form-4-id=5&form-4-name=dgfsdg3waesdvz&form-4-order=4&form-5-id=&form-5-name=&form-5-order=0
HTTP/1.1" 200 7502
models.py (categories app)
from django.db import models
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length = 30, db_index = True, unique = True, verbose_name = "Title")
order = models.PositiveSmallIntegerField(default = 0, db_index = True, verbose_name = "Serial number")
def __str__(self):
return self.name
class Meta:
ordering = ["order", "name"]
verbose_name = "category"
verbose_name_plural = "categories"
views.py (categories app)
from django.views.generic.base import TemplateView
from django.forms.models import modelformset_factory
from django.shortcuts import redirect
from django.contrib import messages
from categories.models import Category
from generic.mixins import CategoryListMixin
CategoriesFormset = modelformset_factory(Category, can_delete=True, fields = '__all__', extra=1, max_num=None)
class CategoriesEdit(TemplateView, CategoryListMixin):
template_name = "categories_edit.html"
formset = None
def get(self, request, *args, **kwargs):
self.formset = CategoriesFormset()
return super(CategoriesEdit, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(CategoriesEdit, self).get_context_data(**kwargs)
context["formset"] = self.formset
return context
def post(self, request, *args, **kwargs):
self.formset = CategoriesFormset(request.POST)
if self.formset.is_valid():
self.formset.save()
messages.api.add_message(request, messages.SUCCESS, "List of categories successfully changed")
return redirect("categories_edit")
else:
messages.api.add_message(request, messages.SUCCESS, "Something is wrong!!!")
return super(CategoriesEdit, self).get(request, *args, **kwargs)
mixins.py
from django.views.generic.base import ContextMixin
class CategoryListMixin(ContextMixin):
def get_context_data(self, **kwargs):
context = super(CategoryListMixin, self).get_context_data(**kwargs)
context["current_url"] = self.request.path
return context
categories_edit.html (categories app)
{% extends "categories_base.html" %}
{% block title %} Categories {% endblock %}
{% block main %}
{% include "generic/messages.html" %}
{{ formset.errors }}
<h2>Categories</h2>
<form action="" method="post">
{% include "generic/formset.html" %}
<div class="submit-button"><input type="submit" value="Save"></div>
</form>
{% endblock %}
formset.html (categories app)
{% csrf_token %}
{{ formset.management_form }}
<table class="form">
<tr>
<th></th>
{% with form=formset|first %}
{% for field in form.visible_fields %}
<th>
{{ field.label }}
{% if field.help_text %}
<br>{{ field.help_text }}
{% endif %}
</th>
{% endfor %}
{% endwith %}
</tr>
{% for form in formset %}
<tr>
<td>
{% for field in form.hidden_fields %}
{{ field }}
{% endfor %}
</td>
{% for field in form.visible_fields %}
<td>
{% if field.errors.count > 0 %}
<div class="error-list">
{{ field.errors }}
</div>
{% endif %}
<div class="control">{{ field }}</div>
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
messages.html (categories app)
{% if messages %}
<div id="messages-list">
{% for message in messages %}
<p class="{{ message.tags }}">{{ message }}</p>
{% endfor %}
</div>
{% endif %}
urls.py (categories app)
from django.conf.urls import url
from django.contrib.auth.decorators import login_required
from categories.views import CategoriesEdit
urlpatterns = [
url(r'^$', login_required(CategoriesEdit.as_view()), name = "categories_edit"),
]
settings.py (project)
"""
Django settings for t****** project.
Generated by 'django-admin startproject' using Django 1.10.6.
For more information on this file, see
https://docs.djangoproject.com/en/1.10/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.10/ref/settings/
"""
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '***************************************************'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'guestbook',
'categories',
'imagepool',
'page',
'main',
'news',
'shop',
'django.contrib.sites',
'django_comments',
'easy_thumbnails',
'taggit',
'precise_bbcode',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 't******.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'tdkennel.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 't******l',
'USER': 'p*******',
'PASSWORD': '********',
'HOST': '',
'PORT': '5432',
}
}
# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
MEDIA_ROOT = os.path.join(BASE_DIR, 'upload')
MEDIA_URL = '/media/'
LOGIN_URL = "login"
LOGOUT_URL = "logout"
SITE_ID = 1
THUMBNAIL_BASEDIR = "thumbnails"
THUMBNAIL_BASEDIR = {"goods.Good.image": {"base": {"size": (200, 100)},},}
LOGIN_REDIRECT_URL = "main"
I recall that something similar happened to me. I ended up using a Form to create the Formset:
try:
from django.forms import ModelForm
from categories.models import Category
from django.forms.models import modelformset_factory
class CategoryForm(ModelForm):
class Meta:
model = Category
fields = '__all__'
CategoryFormSet = modelformset_factory(Category, form=CategoryForm)
and use CategoryFormSet in CategoriesEdit
It's just a workaround, but hope this helps!
My inattention was my mistake. I wrote method="post" in the commented and concatenated part of the code of categories_edit.html (in my project) and forgot to write it in uncommented piece of code:
{# <form method="post" action=""> #}
<form method="" action="">
{% include "generic/formset.html" %}
{# {% csrf_token %} #}
{# {{ formset.as_p }} #}
<div class="submit-button"><input type="submit" value="Save"></div>
</form>
But I confused the users, because wrote everything is correct in my Question, than delete concatenated part of the code and entered the correct piece of code:
<form method="post" action="">
{% include "generic/formset.html" %}
{# {% csrf_token %} #}
{# {{ formset.as_p }} #}
<div class="submit-button"><input type="submit" value="Save"></div>
</form>
I apologize to the users who responded to my question! Code working.
I have attempted all the solutions listed in In Django admin, how can I hide Save and Continue and Save and Add Another buttons on a model admin? and that post was from a few years ago, and I can't find anything about how to disable those buttons. Due to custom saving, the Save And Continue Editing button causes an error. Is there any way to disable it in the current version of django?
Constraints:
- Cannot put app before django.contrib.admin
- I need to only disable it for one form.
- I have a custom form for creation, and it has a custom save method (it's an account creation)
You can just hide the button (the underlying functionality will still be there, but the button will not be visible).
This should work
from django.contrib import admin
class MyModelAdmin(admin.ModelAdmin):
...
class Media:
css = {
'all': ('some/path/to/css/disable_save_and_continue_editing_button.css')
}
disable_save_and_continue_editing_button.css
input[name="_continue"] {
display: none;
}
SO I have figured it out. If you need to play with these buttons then copy the code of submit_line.html and then override it to your templates/admin/submit_line.html and go to your setting.py and then go to
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))),"Project name or app name depends where you put your templates folder","templates")],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
And in yours submit_line.html code
{% load i18n admin_urls %}
<div class="submit-row">
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save">{% endif %}
{% if show_delete_link %}<p class="deletelink-box">{% trans "Delete" %}</p>{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" {{ onclick_attrib }}/>{%endif%}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" {{ onclick_attrib }}/>{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue" {{ onclick_attrib }}/>{% endif %}
</div>
Just remove that save and continue buttons or you can simply comment it.
Hope this will help.
Mark it correct if it helps.
To remove "Save and continue editing" button, set "False" to "extra_context['show_save_and_continue']" in "changeform_view()" as shown below:
# "admin.py"
from django.contrib import admin
from .models import MyModel
#admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
extra_context = extra_context or {}
extra_context['show_save_and_continue'] = False # Here
# extra_context['show_save'] = False
# extra_context['show_delete'] = False
return super().changeform_view(request, object_id, form_url, extra_context)
You can also remove "Save and continue editing" button by setting "False" to "show_save_and_continue" in "context.update()" in "render_change_form()" as shown below:
# "admin.py"
from django.contrib import admin
from .models import MyModel
#admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
context.update({
'show_save_and_continue': False, # Here
# 'show_save': False,
# 'show_delete': False,
})
return super().render_change_form(request, context, add, change, form_url, obj)