UniqueConstraint not throwing an exception, stops on POST

I’m getting nothing in return when I populate fields with the same values.

class Position(models.Model):

    what = models.CharField(max_length=10)
    what_vehicle = models.ForeignKey('Vehicle', on_delete=models.SET_NULL, null=True)
    what_tier = models.ForeignKey('Tier', on_delete=models.SET_NULL, null=True, blank=True)
    brake_percentage = models.IntegerField(blank=True, null=True)
    wire = models.BooleanField(default=True)

    class Meta:
        unique_together = ('what', 'what_vehicle',)

    #     constraints = [
    #         UniqueConstraint(
    #             fields=['what', 'what_vehicle'],
    #             name='what_what_vehicle_unique',
    #         ),
    #     ]

(Tried both)
*

Output:

System check identified no issues (0 silenced).
December 28, 2022 - 23:26:08
Django version 4.1.3, using settings 'forsta.settings'
Starting ASGI/Channels version 3.0.4 development server at http://localhost:8000/
Quit the server with CTRL-BREAK.
Hi from full clean
HTTP POST /verkstad/pos/ 200 [0.05, 127.0.0.1:56714]
WebSocket HANDSHAKING /ws/verkstad/pos [127.0.0.1:56719]
WebSocket CONNECT /ws/verkstad/pos [127.0.0.1:56719]

It just stops on the post request. It won’t save as expected. Form_vaild won’t run either.
Full clean is triggered tho.

Anyone with some smart ideas? :sunny:

Please post the forms and views involved with this. (Also, if you’ve got something that you tried to post here where it says “Tried both”, you need to surround that with the lines of ``` just like you do with code.)

Okay, just meant in the class Meta.

class ChangePosition(UpdateView):
    form_class = PositionForm
    model = Position
    template_name = 'verkstad/position.html'

    def get_success_url(self):
        return reverse_lazy('change-pos', kwargs={'pk': self.object.id})
class PositionForm(forms.ModelForm):
    class Meta:
        model = Position
        exclude = ['brake_percentage']
        widgets = {
            'what': forms.Select(attrs={'class': 'form-control'}),
            'what_vehicle': forms.Select(attrs={'class': 'form-control'}),
            'what_tier': forms.Select(attrs={'class': 'form-control'}),
            'wire': forms.CheckboxInput(attrs={'class': 'form-check-input', 'id': 'knapp1',
                                               'role': 'switch', 'type': 'checkbox'}),
        }
    def __init__(self, *args, **kwargs):
        w_v = kwargs.get('instance', None)
        if w_v:
            w_v = w_v.wire
        else:
            w_ws = kwargs.pop('wire', None)
            if w_ws == 'false':
                w_v = False
            else:
                w_v = True
        super(PositionForm, self).__init__(*args, **kwargs)
        self.fields['what'].widget.choices = self.choices_list(w_v)

    def choices_list(self, wire):
        if wire:
            V_F1_H_F = 'V_F1_H_F'
            V_F1_H_MF = 'V_F1_H_MF'
            V_F1_H_MB = 'V_F1_H_MB'
            V_F1_H_B = 'V_F1_H_B'

            V_F1_V_F = 'V_F1_V_F'
            V_F1_V_MF = 'V_F1_V_MF'
            V_F1_V_MB = 'V_F1_V_MB'
            V_F1_V_B = 'V_F1_V_B'

            WHAT_WIRE = [
                (V_F1_H_F, 'Fack1 Höger Fram'),
                (V_F1_H_MF, 'Fack1 Höger Fram Mitten'),
                (V_F1_H_MB, 'Fack1 Höger Bak Mitten'),
                (V_F1_H_B, 'Fack1 Höger Bak'),
                # Vänster Fack 1
                (V_F1_V_F, 'Fack1 Vänster Fram'),
                (V_F1_V_MF, 'Fack1 Vänster Fram Mitten'),
                (V_F1_V_MB, 'Fack1 Vänster Bak Mitten'),
                (V_F1_V_B, 'Fack1 Vänster Bak')
            ]
            return WHAT_WIRE
        else:
            A1_V = 'A1_V'
            A2_V = 'A2_V'
            A3_V = 'A3_V'
            A4_V = 'A4_V'
            A1_H = 'A1_H'
            A2_H = 'A2_H'
            A3_H = 'A3_H'
            A4_H = 'A4_H'
            OTHER = 'O'

            WHAT = [
                (A1_V, 'Axel 1 Vänster'),
                (A1_H, 'Axel 1 Höger'),
                (A2_V, 'Axel 2 Vänster'),
                (A2_H, 'Axel 2 Höger'),
                (A3_V, 'Axel 3 Vänster'),
                (A3_H, 'Axel 3 Höger'),
                (A4_V, 'Axel 4 Vänster'),
                (A4_H, 'Axel 4 Höger'),
                (OTHER, 'Annat'),
            ]
            return WHAT

My first reaction to these symptoms are that the form being submitted isn’t valid for some reason.
Are you rendering form errors in your template? (What does the template look like? Are you rendering fields individually or just rendering the complete form?)

You could override your form_invalid method of your view to just print all the errors if you don’t want to modify the template - that would at least show you why the form is being rejected.

I was so focused on that Django would throw me an exception because of the SQL UniqueConstraint.
How come I don’t get that friendly little “pop-up” as if I would set requeird=True in a model row?

This field is Required

Now I can style the error message a bit and make it work.

Thanks a lot for the help. :slight_smile:

    def form_invalid(self, form):
        print(form.errors)

Out

<ul class="errorlist"><li>__all__<ul class="errorlist nonfield"><li>Position with this What and What vehicle already exists.</li><li>Position with this What and What vehicle already exists.</li></ul></li></ul>

Added {{ form.errors }} to template (don’t know why I didn’t start with that)

{% extends "verkstad/base.html" %}
{% load static %}
{% block content %}
    <form action="" method="post" enctype="multipart/form-data">
        {{ form.errors }}
        {% csrf_token %}
        <div class="container position-relative">
            <div class="input-group">
                <span style="width: 100px" class="input-group-text">Placering</span>
                {{ form.what }}
                <span style="width: 100px" class="input-group-text">Fordon</span>
                {{ form.what_vehicle }}
                <span id="wire_not_span" style="width: 100px" class="input-group-text">Däck</span>
                <div id="wire_id_not">
                    {{ form.what_tier }}
                </div>
            </div>
            <div class="form-check form-switch" style="width: 200px">
                {{ form.wire }}
                <label class="form-check-label" for="knapp1">
                    Wire
                </label>
            </div>
            <br/>
            <button type="submit" style="width: 5rem; height:3rem;" class="btn btn-success position-absolute top-100 start-50">Spara</button>
        </div>
    </form>
    <script>
        const socket = new WebSocket("ws://" + window.location.host + "/ws/verkstad/pos");
                {#---- select blir fältet som ändras ----#}
        const select = document.querySelector('#knapp1');
        check_wire()
        select.addEventListener('change', function () {
            socket.send(select.checked)
            check_wire()

        });

        let vi = document.querySelector('#id_what')
        socket.onmessage = function (event) {
            let v = JSON.parse(event.data)
            vi.innerHTML = v['what']
            console.log(event.data)
        }

        function check_wire() {
            let form_not_wire = document.querySelector('#wire_id_not')
            let wire_span = document.querySelector('#wire_not_span')
            if(select.checked === false) {
                form_not_wire.style.display = 'block'
                wire_span.style.display = 'block'
            } else if(select.checked === true){
                form_not_wire.style.display = 'none'
                wire_span.style.display = 'none'
                document.querySelector('#id_what_tier').selectedIndex = 0
            }
        }
    </script>

{% endblock content %}

I’m not sure I know what “pop-up” that you are referring to. Generally, pop-ups are something done on the client-side - either taking advantage of a feature within the browser or some JavaScript code being run. Either way, it may be an issue of the widget being used.

This is popping up on some fields. Guess it is the browser.

Yes, depending upon your browser and the html being rendered, it could be the browser. (It still could be some JavaScript library - you’d have to investigate it using your browser’s developer tools to be sure.)

1 Like

You are spot on like always :smiley:
Happy new year!

@ Validation · Bootstrap v5.0

Browser defaults

Not interested in custom validation feedback messages or writing JavaScript to change form behaviors? All good, you can use the browser defaults. Try submitting the form below. Depending on your browser and OS, you’ll see a slightly different style of feedback.

While these feedback styles cannot be styled with CSS, you can still customize the feedback text through JavaScript.

1 Like