ModelForm in Django - python

ModelForm:
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(ChapterCreateForm, self).__init__(*args, **kwargs)
Not working
I wanna add self.field other. But it not working.
This is my code:
class ChapterCreateForm(ModelForm):
class Meta:
model = Chapter
exclude = ('user', 'book',)
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(ChapterCreateForm, self).__init__(*args, **kwargs)
def clean_title(self):
title = self.cleaned_data['title']
if Chapter.objects.filter(user=self.user, title=title).exists():
raise forms.ValidationError('THIS CHAPTER ALREADY WRITTEN')
return title
But this form it's working:
class BookCreateForm(ModelForm):
class Meta:
model = Book
exclude = ('user',)
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(BookCreateForm, self).__init__(*args, **kwargs)
def clean_title(self):
title = self.cleaned_data['title']
if Book.objects.filter(title=title).exists():
if Book.objects.filter(user=self.user, title=title).exists():
raise forms.ValidationError('YOU WROTE THIS BOOK ')
raise forms.ValidationError('THIS BOOK ALREADY WRITTEN')
return title
Please help me. Thanks so much

You need to pass user in the form kwargs by overriding get_form_kwargs in the class UserCreateChapterView as below:
class UserCreateChapterView(UserPassesTestMixin, CreateView):
...
...
def get_form_kwargs(self):
kwargs = super(UserCreateChapterView, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
Now you can use kwargs.pop('user') in the __init__ method of ChapterCreateForm and it should work.
Hope it helps!

Related

Django-import-export - How to pass user information to ForeignKeyWidget?

I need to somehow pass the user information to ForeignKeyWidget class from resource class, where I create ForeignKey object:
class CompanyWidget(ForeignKeyWidget):
def clean(self, value, row=None, *args, **kwargs):
print(self.user, file=sys.stderr)
if not value:
return None
else:
obj, _ = Company.objects.get_or_create(
name=value,
created_by='I NEED USER INFORMATION HERE SOMEHOW',
)
return obj
What is the best way to do this?
I've tried to solve this on my own and got pretty close, but could not fit the last piece of the puzzle. You override __init__ class in resource and get user information there. Then, I could not figure out how to pass this self.user information into the class variable company.
Here is the code:
class ContactResource(resources.ModelResource):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(ContactResource, self).__init__(*args, **kwargs)
company = fields.Field(
column_name='company',
attribute='company',
widget=CompanyWidget(model=Company, field='name', user='I NEED TO PASS USER HERE FROM __INIT__'))
def after_import_instance(self, instance, new, **kwargs):
instance.created_by = kwargs['user']
If I somehow manage to pass user information in **kwargs of company variable, then I can use it downstream by overriding ForeignKeyWidget's __init__ class:
class CompanyWidget(ForeignKeyWidget):
def __init__(self, model, field='pk', *args, **kwargs):
self.model = model
self.field = field
self.user = kwargs.pop('user', None)
super(CompanyWidget, self).__init__(model, *args, **kwargs)
def clean(self, value, row=None, *args, **kwargs):
print(self.user, file=sys.stderr)
if not value:
return None
else:
obj, _ = Company.objects.get_or_create(
name=value,
created_by=self.user,
)
return obj
Any help would be appreciated, it took me forever to get here and I feel I am really close. Thank you in advance.
It turns out it is easier to implement this without using ForeignKeyWidget at all.
If you have multiple foreign keys that are not unique but have the same name (in my case, same company name created by different users), this is how you could solve the problem:
class ContactResource(resources.ModelResource):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(ContactResource, self).__init__(*args, **kwargs)
company = fields.Field(column_name='company')
class Meta:
model = Contact
skip_unchanged = True
report_skipped = True
exclude =('is_active', 'created_by')
export_order = ('id','first_name','last_name','email','phone','address','description','company','created_on','website','job_title','birthday')
def after_import_instance(self, instance, new, **kwargs):
instance.created_by = self.user # kwargs['user']
def import_field(self, field, obj, data):
field_name = self.get_field_name(field)
method = getattr(self, 'clean_%s' % field_name, None)
if method is not None:
obj = method(field, obj, data)
super(ContactResource, self).import_field(field, obj, data)
def clean_company(self, field, obj, data):
name = data[field.column_name]
company, created = Company.objects.get_or_create(name=name, created_by=self.user)
obj.company = company
return obj

Why is this django form not valid?

Why is this form not validating? It is not even calling the clean() method.
forms.py:
class SingleSampleForm(forms.Form):
sample_id = forms.CharField(label='Sample ID:')
class Meta:
fields = ('sample_id',)
def __init__(self, *args, **kwargs):
super(SingleSampleForm, self).__init__()
self.helper = FormHelper()
self.helper.layout = Layout(
Field('sample_id',
css_class="search-form-label",),
Submit('submit', 'Search sample', css_class='upload-btn')
)
self.helper.form_method = 'POST'
def clean(self):
print('CLEAN')
sample_id = self.cleaned_data['sample_id']
if sample_id:
return sample_id
raise ValidationError('This field is required')
views.py:
class SampleView(View):
sample_form = SingleSampleForm
def get(self, request, *args, **kwargs):
sample_form = self.sample_form()
self.context = {'sample_form': sample_form,}
return render(request,
'results/single_sample_search.html',
self.context)
def post(self, request, *args, **kwargs):
self.sample_form = self.sample_form(request.POST)
if self.sample_form.is_valid():
print('Valid')
else:
print('not valid')
self.context = {
'sample_form': self.sample_form,
}
return render(request,
'results/single_sample_search.html',
self.context)
I don't understand why it is not even calling the clean() method. I have another form which is almost identical which validates. When I do print dir(self.sample_form) after I have passed the request.POST dict it states that validation=unknown. Why is this? How do I check the reason it is not validating?
You need to pass *args and **kwargs when you call super():
def __init__(self, *args, **kwargs):
super(SingleSampleForm, self).__init__(*args, **kwargs)
At the moment, calling __init__ without any *args or **kwargs is equivalent to calling with data=None. The form is unbound, so will never be valid.

Django Crispy form set model field as required

I have a modelform in which I want to set required attribute to True for email validation
field:-email
class RegisterMyBuisinessForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.form_action = '/registermybuisness/'
Field('email', type='email')
self.helper.add_input(Submit('submit', 'Submit',css_class="btn c-theme-btn c-btn-square c-btn-bold c-btn-uppercase"))
super(RegisterMyBuisinessForm, self).__init__(*args, **kwargs)
class Meta:
model = RegistermyBusiness
fields = ['name','email', 'org_name', 'contact','business_description','store_address','message','store_landmark','business_type','city']
I tried
self.fields['email'].required=True
this resulted in class RegisterMyBuisinessForm doesnot have fields error
You can alter self.fields['email'] in the __init__ method. You need to call super() first.
class RegisterMyBuisinessForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
...
super(RegisterMyBuisinessForm, self).__init__(*args, **kwargs)
self.fields['email'].required = True
...

How form class attributes work in django

how Form class attributes work in django ?
class Test(forms.Form):
x = forms.CharField(max_length=20)
def __init__(self, *args, **kwargs):
super(Test, self).__init__(*args, **kwargs)
print hasattr(self, 'x') #
return False ... what type of mechanism works here ?
I think you want to access the form fields in the __init__ method. You should access it from the fields attribute. Like this:
class Test(forms.Form):
x = forms.CharField(max_length=20)
def __init__(self, *args, **kwargs):
super(Test, self).__init__(*args, **kwargs)
print self.fields['x']

django __init__() got an unexpected keyword argument 'param'

My View.py
class AccountCreate(RequestPassingFormViewMixin, MyCreateView):
template_name = 'dashboard/account_form.html'
form_class = AccountForm
model = Account
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(AccountCreate, self).get_form_kwargs(*args, **kwargs)
common = get_object_or_404(Common, pk=self.kwargs['common_pk'])
combination_price = Account(common=common)
kwargs['instance'] = combination_price
return kwargs
def get_success_url(self):
return reverse('dashboard_account_list', kwargs={'chain_pk': self.object.chain.id})
def form_valid(self, form):
self.object = form.save(commit=False)
discount = form.cleaned_data['discount']
account_list = form.cleaned_data['account_list']
self.object.common = get_object_or_404(Common, pk=self.kwargs['common_pk'])
code = Account.get_code(self.object.common, account_list, discount)
self.object.code = code
self.object.save()
form.save_m2m()
return redirect(self.get_success_url())
and this is my form.py file
class AccountForm(autocomplete_light.ModelForm):
class Meta:
model = Account
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(AccountForm, self).__init__(*args, **kwargs)
common = Common.objects.get(pk=self.request.session.get('common_pk'))
products = Account.objects.filter(chain=chain)
form.fields['discount'].queryset = Discount.objects.filter(product__in=products)
form.fields['account_list'].queryset = AccountList.objects.filter(common=common)
def clean(self):
cleaned_data = super(AccountForm, self).clean()
discount = cleaned_data['discount']
if len(discount) <= 1:
self._errors["discount"] = self.error_class(['Choose at least two discount'])
return cleaned_data
account_list = cleaned_data['account_list']
common = Common.objects.get(pk=self.request.session.get('common_pk'))
code =Account.get_code(common, account_list, discount)
if not self.instance or (self.instance.code != code or self.instance.account_list != account_list):
if Account.objects.filter(code=code, account_list=account_list).exists():
msg1 = 'Already exists'
self._errors["discount"] = self.error_class([msg1])
return cleaned_data
I am tryng to add auto suggest option in my m2m field.I have added autocomplete in my form.py file.
But the problem is that,after adding autocomplete in the form,i am facing the error.
i have found the solution,in my forms,the __init__ method don't have the 'param' keyword argument,so i have rewrite my form.py something like this,adding self.param = kwargs.pop("param") and its worked.
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
self.param = kwargs.pop("param")
super(CombinationPriceForm, self).__init__(*args, **kwargs)
chain = Chain.objects.get(pk=self.request.session.get('chain_pk'))
products = Product.objects.filter(chain=chain)
self.fields['variants'].queryset = Variant.objects.filter(product__in=products)
self.fields['price_list'].queryset = PriceList.objects.filter(chain=chain)

Categories