Django model field validators doesn't work at all - python

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?

Related

How to fix missing 1 required positional argument 'request' error?

TypeError at /risk/riskset
get_context_data() missing 1 required positional argument: 'request'.
See code here:
models.py
class RiskSet(models.Model):
name = models.CharField('Risk set', max_length=500, blank=True, default = '')
owner = models.ForeignKey(User, verbose_name = 'owner', on_delete=models.PROTECT, null=True)
risk = models.ForeignKey(Risk, verbose_name = 'risk', on_delete=models.PROTECT, null = True)
parent_risk_set = models.ForeignKey('self', related_name="child_risk_set", on_delete=models.PROTECT, blank=True, null=True)
def __str__(self):
return "{}".format(self.name)
forms.py
class RiskSetForm(forms.ModelForm):
RiskID1 = forms.ModelMultipleChoiceField(queryset=Risk.objects.all(), required=True,
widget=forms.SelectMultiple(attrs={'class': 'select2'}),
label = 'Risk id')
def __init__(self, *args, **kwargs):
super(RiskSetForm, self).__init__(*args, **kwargs)
print(self)
for visible in self.visible_fields():
visible.field.widget.attrs['class'] = 'form-control'
class Meta:
model = RiskSet
fields = ['name', 'owner', 'risk', 'parent_risk_set']
views.py
class RiskSet(FormView, SingleTableMixin):
template_name = "risk/RiskSet.html"
model = RiskSet
form_class = RiskSetForm
def get_context_data(self, request):
form = RiskSetForm(request.POST or None)
if form.is_valid():
form.save()
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in a QuerySet of all the books
context['page'] = 'risk'
return context
Now I get the error:
TypeError at /risk/riskset
get_context_data() missing 1 required positional argument: 'request'
Please help!
get_context_data does not work with a request parameter. You can pass an arbitrary number of parameters, but here your get_context_data will only run if it is called with the request. You access the request with self.request:
class RiskSet(SingleTableMixin, FormView):
template_name = "risk/RiskSet.html"
model = RiskSet
form_class = RiskSetForm
def get_context_data(self, *args, **kwargs):
form = RiskSetForm(self.request.POST or None)
if form.is_valid():
form.save()
# Call the base implementation first to get a context
context = super().get_context_data(*args, **kwargs)
# Add in a QuerySet of all the books
context['page'] = 'risk'
return context
Furthermore it makes no sense to do this in the get_context_data method. A FormView has routines in place for this. It You can probably also work with a CreateView which will remove more boilerplate code, like:
from django.views.generic import CreateView
class RiskSet(SingleTableMixin, CreateView):
template_name = "risk/RiskSet.html"
model = RiskSet
form_class = RiskSetForm
success_url = 'path-to-url-when-form-is-valid'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
# Add in a QuerySet of all the books
context['page'] = 'risk'
return context

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 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.

Django - Query to retrieve pk from other model

I am trying to create a query to grab the pk of the current post from the database. Then set it as the foreign key of the new post. I am using formview, and the model I am trying to retrieve the 'id' from is called Projects. Id is the primary key of the model Projects.
How would I be able to go about this?
pk=5 because I didn't know how to get the current one.
views.py
class ProjectDetailToDoForm(FormView):
model = ProjectsToDo
form_class = ProjectToDoForm
success_url = '../..'
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(ProjectDetailToDoForm, self).dispatch(request, *args, **kwargs)
def form_valid(self,form):
self.object = form.save(commit=False)
self.object.project = Projects.objects.get(pk=5)
self.object.save()
return super(ProjectDetailToDoForm, self).form_valid(form)
class ProjectDetail(generic.DetailView):
model = Projects
context_object_name = 'indprojects'
template_name = 'projectpage.html'
def get_context_data(self, *args, **kwargs):
context = super(ProjectDetail, self).get_context_data(*args, **kwargs)
context['todolist'] = ProjectsToDo.objects.order_by('project_tododate')
context['todoform'] = ProjectToDoForm()
context['form'] = ProjectForm(instance=Projects.objects.get(slug=self.kwargs['slug']))
return context
def get_queryset(self):
return Projects.objects.filter(user=self.request.user)
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(ProjectDetail, self).dispatch(request, *args, **kwargs)
models.py
class Projects(models.Model):
user = models.ForeignKey(User)
slug = models.SlugField()
project_title = models.CharField(max_length=30)
project_shortdesc = models.CharField(max_length=248)
project_desc = models.TextField()
def save(self):
super(Projects, self).save()
date = datetime.date.today()
self.slug = '%i%i%i%s' % (
date.year, date.month, date.day, slugify(self.project_title)
)
super(Projects, self).save()
class ProjectsToDo(models.Model):
project_tododate = models.DateField()
project_tododesc = models.TextField(max_length = 500)
project = models.ForeignKey(Projects)
def __unicode__(self):
return '%s %s' % (self.project_tododesc, self.project_tododate)
I am guessing that you define the active project using the url. In that case, you can do something like this:
urls.py
url(r'^(?P<project_slug>[\w-]+)/add_todo/$',
views.ProjectDetailToDoForm.as_view(),
name='add_todo',
),
...
view
def form_valid(self, form):
self.object = form.save(commit=False)
project = Project.objects.get(slug=self.kwargs["project_slug"])
self.object.project = project
self.object.save()
return super(ProjectDetailToDoForm, self).form_valid(form)

Pass kwargs from CreateView to ModelForm?

I am trying to pass a kwarg from CreateView to a ModelForm so I can dynamically adjust the fields based on values in the related Parent object. Other answers have indicated that passing a kwarg by overriding get_form_kwargs in the view and catching it with kwarg.pop in the form should work, but I get an AttributeError: 'ChildForm' has no attribute 'get' when I try. Passing the kwarg into the view context works, but doesn't give me access to the value inside the form instance.
models.py:
class Parent(models.Model):
name = models.CharField(max_length=255)
details = models.CharField(max_length=255)
detailstwo = models.CharField(max_length=255, null=True)
child_mod = models.BooleanField(default=False)
slug = models.SlugField()
creator = models.ForeignKey(User)
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(self.name)
super(Parent, self).save(*args, **kwargs)
def __str__(self):
return self.name
class Child(models.Model):
parent = models.ForeignKey(Parent)
parent_mod = models.CharField(max_length=255)
child_name = models.CharField(max_length=255)
def __unicode__(self):
return self.child_name
views.py:
class ChildCreateView(CreateView):
model = Child
form_class = ChildForm
template_name = 'testapp/child_form.html'
def dispatch(self, *args, **kwargs):
return super(ChildCreateView, self).dispatch(*args, **kwargs)
def get_form_kwargs(self, **kwargs):
kwargs = super(ChildCreateView, self).get_form_kwargs()
parent = get_object_or_404(Parent, slug=self.kwargs['parent_slug'])
kwargs['parent'] = parent
return kwargs
def get_context_data(self, **kwargs):
context = super(ChildCreateView, self).get_context_data(**kwargs)
parent = get_object_or_404(Parent, slug=self.kwargs['parent_slug'])
context['parent'] = parent
return context
def form_valid(self, form):
child = form.save(commit=False)
parent_slug = form.data['parent_slug']
parent = get_object_or_404(Parent, slug=parent_slug)
child.parent = parent
return super(ChildCreateView, self).form_valid(form)
def get_success_url(self):
return reverse('testapp:parent_view', kwargs={'slug': self.object.parent.slug})
forms.py:
class ChildForm(forms.ModelForm):
class Meta:
model = Child
fields = ['parent', 'parent_mod', 'child_name']
def __init__(self, *args, **kwargs):
self.parent_object = kwargs.pop('parent')
assert isinstance(self.parent_object, Parent)
super(ChildForm, self).__init__(self, *args, **kwargs)
self.fields["parent_slug"] = forms.CharField(widget=forms.HiddenInput())
if not self.parent_object.child_mod:
del self.fields['parent_mod']
Full Traceback is here: http://dpaste.com/2QBMRJX

Categories