lolz
lolz

Reputation: 245

How to raise forms validation error when ever the user try's to create an object with the object twice

I'v used the unique together model meta, it works but it just comes up with this error. i want to raise a forms validation error, rather than a IntegrityError.

IntegrityError at /name/

UNIQUE constraint failed: canvas_canvas.user_id, canvas_canvas.canvas_name

Request Method: POST Request URL: http://127.0.0.1:8000/name/ Exception Type: IntegrityError Exception Value:

UNIQUE constraint failed: canvas_canvas.user_id, canvas_canvas.canvas_name

Exception Location: C:\Users\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\backends\sqlite3\base.py in execute, line 337

class Canvas(models.Model):
    user                = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
    canvas_name         = models.CharField(
                        max_length=100,
                        validators=[
                            # validate_canvas_title,
                            RegexValidator(
                                    regex=CANVAS_REGEX,
                                    message='Canvas must only contain Alpahnumeric characters',
                                    code='invalid_canvas_title'
                                )],
                        )
    slug                = models.SlugField(max_length=100, blank=True)
    background_image    = models.ImageField(
                        upload_to=upload_location,
                        null=True,
                        blank=True,
                        )
# sort catergory into alphabetical order
    category            = models.ForeignKey('category.Category', default=1, blank=True)
    followers           = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='canvas_followed_by', blank=True)

class Meta:
    unique_together = ['user', 'canvas_name']

form

class CanvasModelForm(ModelForm):
    class Meta:
        model = Canvas
        fields = ['canvas_name', 'category', 'background_image']
        widgets = {
            'canvas_name': TextInput(attrs={'class': 'form-input'}),
            'category': Select(attrs={'class': 'form-input'}),
        }

view

    user = get_object_or_404(User, username=username)

    form_create = CanvasModelCreateForm(request.POST or None)
    if form_create.is_valid():
        instance = form_create.save(commit=False)
        instance.user = request.user
        instance.save()
        return redirect('canvases:canvas', username=request.user.username, slug=instance.slug)

    template = 'pages/profile.html'
    context = {
        'user': user,
        'form_create': form_create,
    }
    return render(request, template, context)

Upvotes: 0

Views: 723

Answers (1)

zaidfazil
zaidfazil

Reputation: 9235

You could do this by passing request.user into the form and use it for validating the canvas_name.

You need to override the form's __init__ method to take an extra keyword argument, user. This stores the user in the form, where it's required, and from where you can access it in your clean method.

def __init__(self, *args, **kwargs):
    self.user = kwargs.pop('user', None)
    super(CanvasModelCreateForm, self).__init__(*args, **kwargs)

def clean_canvas_name(self):
    canvas_name = self.cleaned_data.get('canvas_name')
    if Canvas.objects.get(user=self.user, canvas_name=canvas_name).exists():
        raise forms.ValidationError(u'Canvas with same name already exists.')
    return canvas_name

And you should change in your view like this so,

form_create = CanvasModelCreateForm(request.POST, user=request.user)

Upvotes: 1

Related Questions