Django model form ImproperlyConfigured error - python

ImproperlyConfigured: Creating a ModelForm without either the 'fields'
attribute or the 'exclude' attribute is prohibited; form
CustomUserChangeForm needs updating.
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from login1.models import CustomUser
class CustomUserCreationForm(UserCreationForm):
def __init__(self, *args, **kargs):
super(CustomUserCreationForm, self).__init__(*args, **kargs)
del self.fields['username']
class Meta:
model = CustomUser
fields = ("email",)
class CustomUserChangeForm(UserChangeForm):
def __init__(self, *args, **kargs):
super(CustomUserChangeForm, self).__init__(*args, **kargs)
del self.fields['username']
class Meta:
model = CustomUser

When you create a ModelForm it expecting you to specify what fields to show in template i.e) when you do {{ form }} in html you would expect some fields to render right? So in this case you have specify the fields attribute.
class CustomUserChangeForm(UserChangeForm):
def __init__(self, *args, **kargs):
super(CustomUserChangeForm, self).__init__(*args, **kargs)
del self.fields['username']
class Meta:
model = CustomUser
fields = '__all__' or ['your_field']

You need to define within CustomUserChangeForm.Meta class that what model fields should be included in form:
class CustomUserChangeForm(UserChangeForm):
def __init__(self, *args, **kargs):
super(CustomUserChangeForm, self).__init__(*args, **kargs)
del self.fields['username']
class Meta:
model = CustomUser
fields = '__all__' #<-- add this or name fields you want to include as sequence

Related

django form filter field queryset

How do I filter form's field queryset? After a little search I found that this way it's done. But I am getting an error here.
class TbPeopleEntranceRightForm(forms.ModelForm):
def __init__(self, user=None, *args, **kwargs):
self.user = user
super().__init__(*args, **kwargs)
print(self.user)
self.fields['user'].queryset = self.user
class Meta:
model = TbPeopleEntranceRight
fields = ['user', 'area', 'room']
'TbUser' object has no attribute 'all'
self.fields['user'].queryset = self.user
here self.fields["user"].queryset expects a queryset where you are providing a user instance.
You might want to do something like this.
class TbPeopleEntranceRightForm(forms.ModelForm):
def __init__(self, user=None, *args, **kwargs):
self.user = user
super().__init__(*args, **kwargs)
print(self.user)
self.fields['user'].queryset = YourUserModel.objects.filter(id=self.user.id)
class Meta:
model = TbPeopleEntranceRight
fields = ['user', 'area', 'room']

Get current user info inside model form in django admin

I have the below code structure. I want to get the request.user information inside StaffForm.
How do I pass the user info to that class
class UserProfileAdmin(admin.ModelAdmin):
class UserProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
pass
class StaffForm(UserProfileForm):
def __init__(self, *args, **kwargs):
pass
class Meta:
model = models.UserProfile
fields = ()
class SuperUserForm(UserProfileForm):
def __init__(self, *args, **kwargs):
pass
class Meta:
model = models.UserProfile
fields = ()
search_fields = [
'email',
'name'
]
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
return self.SuperUserForm
else request.user.is_staff:
return self.StaffForm

Django model field validators doesn't work at all

I can't figure out why my validators doesn't work at all.
Form is not invalid
Model doesn't raise ValidationError when being saved
For input: "123456sdad"
I have a model which has broker_ico field:
REGEX_ICO = r"\d{6,8}"
broker_ico = models.CharField(max_length=100, verbose_name='IČO',
validators=[RegexValidator(REGEX_ICO)])
I've overwritten save method:
def save(self, **kwargs):
print('full clean')
self.full_clean()
super().save(**kwargs)
Moreover the form is a ModelForm:
class BusinessCaseDocumentForm(ModelForm):
class Meta:
model = BusinessCaseDocument
exclude = ['id','business_case']
def __init__(self, *args, **kwargs):
super(BusinessCaseDocumentForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
fs_helpers.add_widget_attribute('class', 'form-control', field)
UpdateView:
class BusinessCaseDocumentUpdateView(SuccessMessageMixin, UpdateView):
model = BusinessCaseDocument
form_class = BusinessCaseDocumentForm
template_name = "business_cases/businesscase_documents/create.html"
success_message = "Podklad k obchodnému prípadu bol upravený"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['businesscase'] = self.object.business_case # TODO self.businesscase set
return context
def get_success_url(self):
return reverse("business_cases:list")
Can you see where is the problem?

Django formset - how to give a different queryset for each form within the modelformset

I have a form for a Model - ClinicallyReportedSample, which links to a Sample model.
I am trying to create a formset for ClinicallyReportedSample where, based on a queryset of Sample, a specific amount of forms are displayed so that the user can add data.
Currently, the Sample model has entries, but the ClinicallyReportedSample model is completely empty:
models:
class Sample(models.Model):
request_number = models.PositiveIntegerField()
year = models.PositiveIntegerField()
class Meta:
db_table = "sample"
unique_together = (('request_number', 'year'),)
def __str__(self):
return("%s/%s" %(self.request_number, self.year))
class ClinicallyReportedSample(models.Model):
sample_id = models.ForeignKey(Sample,
on_delete=models.CASCADE,
db_column='sample_id')
reported = models.BooleanField(default=False)
evidence = models.TextField(null=True, blank=True)
... other fields ...
class Meta:
db_table = "clinically_reported_sample"
unique_together = (('sample_id'),)
def __str__(self):
clinically_reported_sample = str(self.sample_id)
return(clinically_reported_sample)
I want ClinicallyReportedSample model forms, within a formset, that relate to a queryset of Sample model.
For example, Sample objects with pk 1, 2 and 3:
forms.py:
class BaseCRSFormSet(BaseModelFormSet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# self.queryset = ClinicallyReportedVariant.objects.none()
class CRSForm(forms.ModelForm):
class Meta:
model = ClinicallyReportedSample
fields = ('sample_id', 'evidence',)
def __init__(self, *args, **kwargs):
super(CRSForm, self).__init__(*args, **kwargs)
So I try to do this using queryset in my formset
views.py:
def get(self, request, *args, **kwargs):
sample_obj = Sample.objects.filter(id__in=[1, 2, 3])
formset = modelformset_factory(
ClinicallyReportedSample,
form=self.crsform,
formset=BaseCRSFormSet,
extra=3,
)
formset = formset(queryset=sample_obj)
but this displays as three forms, with ALL Sample objects, the queryset does not work. Is this the correct way to go about this?
You'll need to set the default Sample queryset to none:
class CRSForm(forms.ModelForm):
class Meta:
model = ClinicallyReportedSample
fields = ('sample_id', 'evidence',)
sample_id = forms.ModelChoiceField(queryset=Sample.objects.none())
def __init__(self, *args, **kwargs):
super(CRSForm, self).__init__(*args, **kwargs)
And then when you make a formset instance manually assign the queryset like so:
def get(self, request, *args, **kwargs):
sample_obj = Sample.objects.filter(id__in=[1, 2, 3])
formset = modelformset_factory(
ClinicallyReportedSample,
form=self.crsform,
formset=BaseCRSFormSet,
extra=3,
)
formset = formset(queryset=sample_obj)
for form in formset:
form.fields['sample_id'].queryset = sample_obj
Note that you'll also have to manually set the queryset in your POST function too otherwise it won't validate.

Overriding django form in Forms.modelAdmin

I have a problem when I want to override a field in my form
The class looks like below
class UserCreationForm(forms.ModelForm):
class Meta:
model = User
fields = ['password', 'services', 'project', 'email', 'name', 'first_name', 'role']
I want to modify the field 'Services' with another value.
For this I used the get_form function like this :
class UserAdmin(admin.ModelAdmin):
exclude = ('uuid',)
search_fields = ('email', "project")
list_display = ("email", "project", "nb_connexion")
form = UserCreationForm
def get_form(self, request, obj=None, **kwargs):
if obj != None:
print(obj.name)
print(request)
form = super(UserAdmin, self).get_form(request, obj=obj, **kwargs)
form.base_fields['services'].initial = Service.objects.filter(projects=obj.project)
return form
But I still get the same results for all the services while I am only interested in getting the services of one project.Any help would be appreciated.
Thanks
You are currently trying to set initial, which is the initial value selected. If you want to limit the choices, you want to override the queryset instead.
You can alter the form's fields in the __init__ method:
class UserCreationForm(forms.ModelForm):
class Meta:
model = User
fields = ['password', 'services', 'project', 'email', 'name', 'first_name', 'role']
def __init__(self, *args, **kwargs):
super(UserCreationForm, self).__init__(*args, **kwargs)
if self.instance.pk:
self.fields['services'].queryset = Service.objects.filter(projects=self.instance.project)
Your UserAdmin class already uses form = UserCreationForm, so all you have to do is remove the get_form method.
class UserAdmin(admin.ModelAdmin):
...
form = UserCreationForm
...

Categories