Autocomplete-light registry issues - django

I am trying to install autocomplete-light into one of my forms. I keep getting this error:
Institution not registered, you have registered: ['InstitutionAutocomplete']
I have not declare or registered InstitutionAutocopmlete anywhere in my code so I don't know how I could have triggered this error.
I have the following form:
class AddUserAccountsForm(forms.ModelForm):
"""
Form for adding new user financial accounts.
"""
required_css_class = 'required'
name = forms.ModelChoiceField(required=True, queryset=Institution.objects.all(), widget=autocomplete_light.ChoiceWidget('Institution'))
user_accounts_name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'User Name'}), label="")
user_accounts_password = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Password'}), label="")
class Meta:
model = Institution
fields = ('name','user_accounts_name', 'user_accounts_password',)
This is in my autocomplete_light_registry.py:
import autocomplete_light
from models import Institution
autocomplete_light.register(Institution,
search_fields = ['name'],
attrs={
'placeholder':'Find your institution',
'data-autocomplete-minimum-characters':1,
},
widget_attrs={
'data-widget-maximum-values':4,
'class':'modern-style',
},
)
Here is my html. The error is triggered when the code runs {{ form.as_p}}.
{% load staticfiles %}
<script type="text/javascript" src="{% static 'jquery.js' %}">
</script>
{% include 'autocomplete_light/static.html' %}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
urls.py is:
url(r'^profile/add_user_accounts/', UserAccountsUpdate.as_view(), name='add_user_accounts'),

In your form you have to use 'InstitutionAutocomplete' instead of 'Institution'
name = forms.ModelChoiceField(required=True,
queryset=Institution.objects.all(),
widget=autocomplete_light.ChoiceWidget('InstitutionAutocomplete'))

Related

Form validation in Django 2.2! Can't display any validation errors

I am working with this simple form and can't able to display inline validation in each line. I want validation as it worked in the Django admin site, with particular fields. How could it be done! It only shows the HTML validation like "Please fill out the field"
models.py
class MemberRegistration(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(max_length=100)
phone = models.CharField(max_length=50)
def __str__(self):
return self.name
forms.py
from django import forms
from . models import MemberRegistration
from django.core import validators
class MemberForm(forms.ModelForm):
name = forms.CharField(widget=forms.TextInput(
attrs={'class': 'form-control', 'placeholder':'Name'}),
max_length=100, error_messages = {
'required':"Please Enter your Name"})
email = forms.EmailField(widget=forms.EmailInput(
attrs={'class': 'form-control', 'placeholder':'E-mail'}),
required=True, max_length=100)
phone = forms.CharField(widget=forms.TextInput(
attrs={'class': 'form-control', 'placeholder':'Phone'}),
required=True, max_length=100)
class Meta:
model = MemberRegistration
fields = "__all__"
def clean_name(self):
all_clean_data = super().clean()
name = all_clean_data['name']
if name == "":
raise forms.ValidationError("Name field is required")
member_form.html:
{% block body_block %}
<div class="container">
<h1>This is member reg form</h1>
<form method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label for="">Name</label>
{{ form.name.errors }}
{{form.name}}
</div>
<div class="form-group">
<label for="">Email</label>
{{ form.email.errors }}
{{form.email}}
</div>
<div class="form-group">
<label for="">Phone</label>
{{form.phone}}
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
{% endblock %}
How I can do this with Django's built-in validation?

Why the attribute of an instance model does not change

I create a financial manager and I need the user to change the account activity (indicate an active account or not), but when I send the form for change, then the model attribute does not change and always remains TRUE
I also tried to do this through a copy of the Account, but it was also not a result of the outcome
Account.objects.get(user=self.request.user, id=id).is_active = False
models.py
class Account(models.Model):
type_of_currency = models.CharField(max_length=20)
user = models.ForeignKey(get_user_model(), blank=True,
related_name='user_account',
on_delete=models.CASCADE)
count = models.DecimalField(max_digits=12, decimal_places=2, blank=True)
created = models.DateTimeField(default=datetime.datetime.now)
is_active = models.BooleanField()
def __str__(self):
return f'{self.type_of_currency} - {self.count}'
views.py
class AccountDetailView(DetailView, UpdateView):
model = Account
form_class = AccountCreateForm
template_name = 'account_detail.html'
def post(self, request, *args, **kwargs):
id = self.request.POST['accountid']
self.request.user.user_account.get(id=6).is_active = False
print(self.request.user.user_account.get(
id=id).is_active) # always True why?
return redirect('/counts/' + id)
template
{% extends 'base.html' %}
{% block content %}
<div class="col-sm-5">
<h1>account: {{ account.id }}</h1>
<p><strong>Author:</strong> {{ account.user }}</p> <!-- author detail link not yet defined -->
<p><strong>Type:</strong> {{ account.type_of_currency }}</p>
<p><strong>count:</strong> {{ account.count }}</p>
<p><strong>IsCreated:</strong> {{ account.created }}</p>
<p><strong>IsActive:</strong>{{ account.is_active }}</p>
<a class="btn btn-outline-primary"
href="{% url 'account-list' %}">Back</a>
{% if account.is_active %}
<form method="post">
{% csrf_token %}
<input type="hidden" value="{{ account.id }}" name="accountid">
<button type="submit" class="btn btn-outline-danger">Deactivate</button>
</form>
{% else %}
<form method="post">
{% csrf_token %}
<button type="submit" class="btn btn-outline-success">Activate</button>
</form>
{% endif %}
</div>
{% endblock %}
In the post method DetailViews, I expect that after the button is pressed, user activity will change, but the result is always True
You're never commiting change to DB.
Also, I wouldn't use the following syntax: self.request.user.user_account.get(id=6).is_active = False
You can try: self.request.user.user_acocount.filter(id=6).update(is_active=False)
But, if you're dead set on using .get():
user_acc = self.request.user.user_account.get(id=6)
user_acc.is_active = False
user_acc.save()

Showing custom error messages in django model form with bootstrap

I want to show custom error messages, if some field is not valid. I have following model:
class Test(models.Model):
name = models.IntegerField(max_length=10)
class TestForm(forms.ModelForm):
class Meta:
model = Test
fields = '__all__'
error_messages = {
'name': {
'max_length': ("This user's name is too long."),
},
}
The view is:
def test(request):
if request.method == 'POST':
print "The form is submitted successfully."
form = TestForm(request.POST)
if form.is_valid():
print request.POST.get("name")
return render(request, 'test.html',{'form' : TestForm()})
else:
print "Something wrong with inputs."
return render(request, 'test.html',{'form' : form})
else:
return render(request,'test.html',{'form' : TestForm()})
and template is:
{% extends "base.html" %}
{% block title %}
Test Form
{% endblock title %}
{% load widget_tweaks %}
{% block body_block %}
<h1>hello from test</h1>
<form class='form-horizontal' role='form' action="." method="POST">
<div class='form-group'>
<label class='control-label col-md-2 col-md-offset-2' for='id_name'>Name</label>
<div class='col-md-6'>
{% render_field form.name class="form-control" placeholder="Full Name" type="text" %}
{{ form.name.error_messages }}
{# I want to add here classes for alert-error etc #}
</div>
</div>
{% csrf_token %}
<div class='form-group'>
<div class='col-md-offset-4 col-md-6'>
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
{% endblock body_block %}
But, I am not getting any messages in the template. Please help me to solve this.
Change form.name.error_messages to form.name.errors in your template.
It seems you render fields/errors one by one manually, explained here:
You may want to consider a more automatic approach using a {% for %} template tag.
EDIT: To change the default error message, you need to update your error_messages in the form Meta and overwrite the key used by django, in this case it is key invalid, based on IntegerField source:
class Meta:
model = Test
fields = '__all__'
error_messages = {
'some_integer_field': {
'invalid': 'some custom invalid message',
},
}

setting initial values for more then one form

I have looked at some examples but none of them have worked for me.
What i have is List of Locations and the user has the choice to add them to a group. First step is he gives the group a name. And then he can choose from the locations which are already in the database, to add them to the group name.
To put it simple i want to loop 3 form elements for each location, and attach initial values for each location, so it can be stored inside a group.
This is what i want to see:
<form>
<input type="text" label="group_name">
First Location
<input type="hidden" value="street_name">
<input type="hidden" value="location_name">
<input type="checkbutton">
Second location
<input type="hidden" value="street_name2">
<input type="hidden" value="location_name2">
<input type="checkbutton">
and so on
<input type="submit" value="Create this Group">
</form>
I have tried it like this:
Froms.py is currently missing the check input for True and False.
FORMS.py:
class GroupAddForm(forms.ModelForm):
groupname = forms.CharField(label='',widget=forms.HiddenInput(attrs={'rows': '4', 'class': 'form-control'}))
page_name = forms.CharField(label='' ,widget=forms.HiddenInput(attrs={'rows': '4', 'class': 'form-control'}))
page_street = forms.CharField(label='' ,widget=forms.HiddenInput(attrs={'rows': '4', 'class': 'form-control'}))
class Meta:
model = GroupManagement
fields = ['groupname', 'page_name', 'page_street']
VIEW:
def page_groups(request):
email =request.user.email
locationdata = LocationData.objects.filter(email=email).values_list(
'id',
'name',
'street',
'postal_code',
'tel',
'website',
'description',
'fb_page_id'
)
form = []
for items in locationdata:
name = items[1]
form = GroupAddForm(request.POST or None, initial={"page_name": name})
print(form)
context = {
'locationdata': locationdata,
'form': form,
}
return render(request, 'page_groups.html', context)
OR in the Template:
<form method="POST" action=""> {% csrf_token %}
{% for items in locationdata %}
{{items.1}}
{{form.fields.page_name.value|default:items.1}}
{{form}}
{% endfor %}
</form>
Inside the View only the last element is attached to the form.
The initial Value inside the Template doesn't work at all.
Fixed it myself.
for items in locationdata:
name = items[1]
form = GroupAddForm(request.POST or None, initial={"page_name": name})
forms.append(form)
<form method="POST" action=""> {% csrf_token %}
{% for items in forms %}
{{items}}
{% endfor %}
</form>

Why is Django widgets for TimeInput not showing

I'm trying to create a TimeInput field in a form and noticed that the widget isn't showing correctly. But when I check the localhost:8000/admin, I see the widget showing up correctly.
My code is as follows. For models.py,
class TimeLimit(models.Model):
before = models.TimeField(blank=True, default=time(7, 0)) # 7AM
after = models.TimeField(blank=True, default=time(23, 0)) # 11PM
For views.py,
class UpdateTimeLimitView(LoginRequiredMixin, FormView):
model = TimeLimit
template_name = 'accounts/update_time_limit.html'
form_class = UpdateTimeLimitForm
def get_success_url(self):
return reverse_lazy('accounts:user_profile') + '?username=' + self.request.GET['username']
def get_context_data(self, **kwargs):
data = super(UpdateTimeLimitView, self).get_context_data(**kwargs)
data['username'] = self.request.GET['username']
return data
For forms.py,
class UpdateTimeLimitForm(forms.Form):
time_error = {'required': 'This field is required.',
'invalid': 'Please enter valid Hour:Minute values.'}
before = forms.TimeField(widget=forms.TimeInput(format='%H:%M'))
after = forms.TimeField(widget=TimeInput(format='%H:%M'))
class Meta:
model = TimeLimit
Finally, the relevant part for fields in update_time_limit.html,
<div class="container">
<form method="post">
{% csrf_token %}
<p>
{% for field in form %}
{{ field.errors }}
<label for="{{ field.id_for_label }}">{{ field.label }}({{ field.help_text }}):</label>
<br />
{{ field }}<br /><br /> and
{% endfor %}
</p>
<input class="btn btn-primary done-btn" type="submit" value="Update Time Limit">
</form>
</div>
Is there anything that I'm missing or doing wrong? Thank you.
The Django admin uses AdminTimeWidget to display time fields, not the TimeInput widget that you are using in your code.
There isn't a documented way to reuse the AdminTimeWidget outside of the Django admin. Getting it to work is very hacky (see the answer on this question, which is probably out of date), so it's probably better to use a different widget.
convert datetime.time(7, 0) to string work for me.
data['before'] = data['before'].strftime('%H:%M:%S')