Model:
class ProjectType(models.Model):
project_type_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=45, help_text='Type of project', verbose_name='Project Type')
slug = models.SlugField(max_length=45, blank=True)
description = models.CharField(max_length=400, help_text='Description of the main purpose of the project', verbose_name='Project Type Description')
default = models.BooleanField(default=False)
owner = models.ForeignKey(User)
class Meta:
...
unique_together = (('slug', 'owner'),('name', 'owner'))
I need a form to create/update ProjectType's. Please note the owner field - it is supposed to be current logged-in user. The question is how to ensure that constraints in the unique_together are validated correctly.
I do not want to show owner field on the form - it's the current user, so it should be set automatically by the system. But no matter how I try to do this, either validation does not work, or there are other errors.
Among approaches I tried (individually or in combination):
Defining init in ProjectTypeForm (in various ways), for example:
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(ProjectTypeForm, self).__init__(*args, **kwargs)
self.fields['owner'].initial = self.user
Setting values in the view like:
...
if request.method == 'POST':
project_type = ProjectType(owner=request.user)
form = ProjectTypeForm(request.POST, instance=project_type, user = request.user.pk) # also tries w/o pk
...
Overriding clean() method of the form in various ways, along these lines:
def clean(self):
cleaned_data = super(ProjectTypeForm, self).clean()
slug=cleaned_data.get('slug')
owner = cleaned_data.get('owner')
if slug:
user = User.objects.get(pk=owner)
...
Many of these approaches are based on various answers found on stackoverflow.com. However, no matter what I try, I cannot find a way to accomplish what I need: (1) auto-setting of the owner field and (2) validation for uniqueness: owner/type_name and owner/type_slug. Typical errors I have is that (a) owner is not recognized as a User (it's treated as a PK), (b) incorrect validation (like lack of it or it misses the fact that it's the same record being edited, etc.), (c) owner is a required field.
For the record - if the owner is a regular field in the form, everything works as expected, but I cannot allow users to set the owner value.
Is there any, hopefully elegant, solution to this?
Thanks!
Exclude the owner field from your form, and save the user in your form's init method - then you can use it to validate the form, eg
class ProjectTypeForm(...):
...
def __init__(self, user, *args, **kwargs):
super(ProjectTypeForm, self).__init__(*args, **kwargs)
self.user = user
def clean(self):
user_projects = ProjectType.objects.filter(owner=self.user)
if user_projects.filter(slug=self.cleaned_data['slug']):
raise forms.ValidationError('...')
elif user_projects.filter(name=self.cleaned_data['name']):
raise forms.ValidationError('...')
else:
return self.cleaned_data
Then in your view, do something like this when creating a new ProjectType:
if request.method == 'POST':
form = ProjectTypeForm(request.user, request.POST)
if form.is_valid():
ptype = form.save(commit=False)
ptype.owner = request.user
ptype.save()
You shouldn't need that to save existing ProjectType objects though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With