Django 自定义用户创建表单 - 重复条目

时间:2021-06-25 17:48:01

标签: django

创建用于创建新用户的自定义页面。该页面编辑和删除用户没有问题。当我创建一个用户时,我收到 django.db.utils.IntegrityError: (1062, "Duplicate entry 'johndoe@gmail.com' for key 'accounts_user.email'")。我知道我的代码试图保存该条目两次。根据我的回溯,我认为这与表单中的保存函数与视图中的 form.save() 冲突有关。这是所有代码。我已经用尽了我(有限的)想法。

views.py

@admin_only
def index(request):
    user_accounts = User.objects.all()
    print(user_accounts)
    context = {'accounts': user_accounts}
    return render(request, 'accounts/user_accounts.html', context)

@admin_only
def create_account(response):
    data = dict()
    form = CreateAccountForm()
    if response.method == 'POST':
        form = CreateAccountForm(response.POST)
        if form.is_valid():
            form.save()
            data['form_is_valid'] = True
            user_accounts = User.objects.all().order_by('id')
            data['accounts_list'] = render_to_string('accounts/account_list.html', {'accounts': user_accounts})
        else:
            data['form_is_valid'] = False
    context = {'form': form}
    data['html_form'] = render_to_string('accounts/create_account.html', context, request=response)
    return JsonResponse(data)
forms.py

class UserAdminCreationForm(forms.ModelForm):
    
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
    first_name = forms.CharField(required=True)
    last_name = forms.CharField(required=True)

    class Meta:
        model = User
        fields = (
            'email',
            'first_name',
            'last_name',
        )

    def clean_password2(self):
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserAdminCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

class CreateAccountForm(UserAdminCreationForm):
    email = forms.EmailField()

    class Meta:
        model = User
        fields = [
            "first_name",
            "last_name",
            "email",
            "phone",
            "mobile_phone",
            "sms_messages",
            "active",
            "staff",
            "admin",
            "H1A",
            "H1B",
            "H2A",
            "H2B",
            "H3A",
            "H3B",
            "H5A",
            "H5B",
            "H6A",
            "H6B",
            "backshop",
            "DoD_P8",
            "Commercial",
            "password1",
            "password2",
        ]
user_accounts.html
{% extends "main/base.html" %}
{% block title %}
Manage User Accounts
{% endblock %}
{% block content %}
{% load crispy_forms_tags %}
<head>
</head>
<div class="container-xl-fluid mx-auto" style="width: 95%">
  <div class="row justify-content-md-center mb-2" style="padding-top: 20px">
    <div class="col-md-12 mb-4 shadow-lg p-3 bg-white rounded">
      <div id="dashboard_parent" class="header mb-2">
        <h3 class="header mb-2 text-center">Manage User Accounts</h3>
          <!-- Modal -->
            <div id="modal-aircraft" class="modal fade" data-backdrop="static" data-keyboard="false" role="dialog">
                <div class="modal-dialog modal-lg">
                    <!-- Modal content-->
                    <div class="modal-content" style="margin-top: 4vh;"></div>
                </div>
            </div>
            <div id="toolbar">
                <button class="btn show-form" data-url="{% url 'create_account' %}" title="Add Account" style="color: Dodgerblue;"><i class="fas fa-plus fa-lg"></i></button>
            </div>
              <table id="table" class="accounts table table-sm table-bordered w-auto mx-auto"
                     data-toolbar="#toolbar"
                     data-toggle="table"
                    data-search="true"
                    data-show-export="true"
                    data-show-print="true"
                    data-show-multi-sort="true"
                    data-show-multi-sort-button="true"
                    data-method="multiSort"
                    data-export-types="['pdf', 'txt', 'csv', 'xlsx']"
                    data-buttons-align="left"
                    data-search-align="left"
                    data-show-refresh="false"
                >
                  <thead class="accounts_header">
                    <tr id="header_accounts" class="text-center">
                        <th></th>
                        <th data-field="id" data-sortable="true">ID</th>
                        <th data-field="first_name" data-sortable="true">First Name</th>
                        <th data-field="last_name" data-sortable="true">Last Name</th>
                        <th data-field="email" data-sortable="true">email</th>
                        <th data-field="phone" data-sortable="true">Phone</th>
                        <th data-field="mobile_phone" data-sortable="true">Mobile Phone</th>
                        <th data-field="sms_messages" data-sortable="true">SMS</th>
                        <th data-field="active" data-sortable="true">Active</th>
                        <th data-field="staff" data-sortable="true">Staff</th>
                        <th data-field="admin" data-sortable="true">Admin</th>
                        <th data-field="H1A" data-sortable="true">H1A</th>
                        <th data-field="H1B" data-sortable="true">H1B</th>
                        <th data-field="H2A" data-sortable="true">H2A</th>
                        <th data-field="H2B" data-sortable="true">H2B</th>
                        <th data-field="H3A" data-sortable="true">H3A</th>
                        <th data-field="H3B" data-sortable="true">H3B</th>
                        <th data-field="H5A" data-sortable="true">H5A</th>
                        <th data-field="H5B" data-sortable="true">H5B</th>
                        <th data-field="H6A" data-sortable="true">H6A</th>
                        <th data-field="H6B" data-sortable="true">H6B</th>
                        <th data-field="backshop" data-sortable="true">Backshop</th>
                        <th data-field="Commercial" data-sortable="true">Commercial</th>
                        <th data-field="DoD_P8" data-sortable="true">P-8A</th>
                        <th></th>
                    </tr>
                  </thead>
                    <tbody id="account-table-body" class="searchable">
                        {% include "accounts/account_list.html" %}
                    </tbody>
                </table>
      </div>
    </div>
  </div>
</div>


{% endblock content%}
create_account.html
{% load crispy_forms_tags %}
<form method="POST" enctype="multipart/form-data" data-url="{% url 'create_account' %}" id="create-form" class="create-form">
    {% csrf_token %}
    <div class="modal-header">
    <!--<button type="button" class="close ml-0 pl-0" data-dismiss="modal">&times;</button>-->
        <h4 class="modal-title">Create New Account</h4>
    </div>
        <div class="modal-body">
            <div class="col">
                <form method="POST" id="create-account" class="form-group create-form">
                {% csrf_token %}
                <div class="form-row d-flex justify-content-center">
                    <div class="form-group col-md-4-mb-0">
                        {{form.first_name|as_crispy_field}}
                    </div>
                    <div class="form-group col-md-4-mb-0">
                        {{form.last_name|as_crispy_field}}
                    </div>
                    <div class="form-group col-md-4-mb-0">
                        {{form.email|as_crispy_field}}
                    </div>
                </div>
                <div class="form-row d-flex justify-content-center">
                    <div class="form-group col-md-4-mb-0">
                        {{form.phone|as_crispy_field}}
                    </div>
                    <div class="form-group col-md-4-mb-0">
                        {{form.mobile_phone|as_crispy_field}}
                    </div>
                </div>
                <div class="form-row d-flex justify-content-center">
                        {{form.sms_messages|as_crispy_field}}
                </div>
                <div class="text-center border-top">
                    <h5>Account Status</h5>
                </div>
                <div class="form-row d-flex justify-content-center">
                    <div class="form-group col-md-6-mb-0" id="active">
                        {{form.active}}
                        <label class="form-check-label" for="active">
                            Active |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="staff">
                        {{form.staff}}
                        <label class="form-check-label" for="staff">
                            Staff |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="admin">
                        {{form.admin}}
                        <label class="form-check-label" for="admin">
                            Admin
                        </label>
                    </div>
                </div>
                <div class="text-center border-top">
                    <h5>Account Permissions</h5>
                </div>
                <div class="form-row d-flex justify-content-center">
                    <div class="form-group col-md-6-mb-0" id="DoD_P8">
                        {{form.DoD_P8}}
                        <label class="form-check-label" for="DoD_P8">
                            DoD_P8 |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="Commercial">
                        {{form.Commercial}}
                        <label class="form-check-label" for="Commercial">
                            Commercial
                        </label>
                    </div>
                </div>
                <div class="text-center border-top">
                    <h5>Assigned Work Stations</h5>
                </div>
                <div class="form-row d-flex justify-content-center">
                    <div class="form-group col-md-6-mb-0" id="H1A">
                        {{form.H1A}}
                        <label class="form-check-label" for="H1A">
                            H1A |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="H2A">
                        {{form.H2A}}
                        <label class="form-check-label" for="H2A">
                            H2A |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="H3A">
                        {{form.H3A}}
                        <label class="form-check-label" for="H3A">
                            H3A |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="H5A">
                        {{form.H5A}}
                        <label class="form-check-label" for="H5A">
                            H5A |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="H6A">
                        {{form.H6A}}
                        <label class="form-check-label" for="H6A">
                            H6A
                        </label>
                    </div>
                </div>
                <div class="form-row d-flex justify-content-center">
                    <div class="form-group col-md-6-mb-0" id="H1B">
                        {{form.H1B}}
                        <label class="form-check-label" for="H1B">
                            H1B |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="H2B">
                        {{form.H2B}}
                        <label class="form-check-label" for="H2B">
                            H2B |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="H3B">
                        {{form.H3B}}
                        <label class="form-check-label" for="H3B">
                            H3B |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="H5B">
                        {{form.H5B}}
                        <label class="form-check-label" for="H5B">
                            H5B |
                        </label>
                    </div>
                    <div class="form-group col-md-6-mb-0" id="H6B">
                        {{form.H6B}}
                        <label class="form-check-label" for="H6B">
                            H6B
                        </label>
                    </div>
                </div>
                <div class="form-row d-flex justify-content-center">
                    <div class="form-group col-md-6-mb-0" id="backshop">
                        {{form.backshop}}
                        <label class="form-check-label" for="backshop">
                            Backshop
                        </label>
                    </div>
                </div>
                <div class="form-row d-flex justify-content-center">
                    <div class="form-group col-md-4-mb-0">
                        {{form.password1|as_crispy_field}}
                    </div>
                    <div class="form-group col-md-4-mb-0">
                        {{form.password2|as_crispy_field}}
                    </div>
                </div>
                {% if request.GET.next %}
                    <input type="hidden" name="next" value="{{request.GET.next}}">
                {% endif %}
                <button type="submit" class="btn btn-primary">Save</button>
                <button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
                </form>
            </div>
        </div>
    <div class="modal-footer">
    </div>
</form>
script.js

// create account records
$('.show-form').click(ShowAccountForm);
$('#modal-aircraft').on('submit', '.create-form', SaveAccountForm)

// update account records
$('#account-table-body').on('click', '.show-form-update', ShowAccountForm)
$('#modal-aircraft').on('submit', '.update-form', SaveAccountForm)

// delete account records
$('#account-table-body').on('click', '.show-form-delete', ShowAccountForm)
$('#modal-aircraft').on('submit', '.delete-form', SaveAccountForm)

var SaveAccountForm = function(){
        var form = $(this);
        $.ajax({
            url: form.attr('data-url'),
            data: form.serialize(),
            type: form.attr('method'),
            dataType: 'json',
            success: function(data){
                if(data.form_is_valid){
                    $('#account-table-body').html(data.accounts_list);
                    $('#modal-aircraft').modal('hide');
                } else {
                    $('#modal-aircraft .model-content').html(data.html_form)
                }
            }
        })
        return false;
    }


var ShowAccountForm = function(){
        var btn = $(this);
        $.ajax({
            url: btn.attr('data-url'),
            type: 'get',
            dataType: 'json',
            beforeSend: function(){
                $('#modal-aircraft').modal('show');
            },
            success: function(data){
                $('#modal-aircraft .modal-content').html(data.html_form);
            }
        });
    };
traceback

Internal Server Error: /accounts/create_account/
Traceback (most recent call last):
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\backends\utils.py", line 86, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\backends\mysql\base.py", line 74, in execute
    return self.cursor.execute(query, args)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\MySQLdb\cursors.py", line 209, in execute
    res = self._query(query)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\MySQLdb\cursors.py", line 315, in _query
    db.query(q)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\MySQLdb\connections.py", line 239, in query
    _mysql.connection.query(self, query)
MySQLdb._exceptions.IntegrityError: (1062, "Duplicate entry 'johndoe@gmail.com' for key 'accounts_user.email'")

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\antho\Developer Apps\PyCharmProjects\EGHub\accounts\views.py", line 51, in _inner
    return function(request, *args, **kwargs)
  File "C:\Users\antho\Developer Apps\PyCharmProjects\EGHub\accounts\views.py", line 85, in create_account
    form.save()
  File "C:\Users\antho\Developer Apps\PyCharmProjects\EGHub\accounts\forms.py", line 64, in save
    user.save()
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\contrib\auth\base_user.py", line 66, in save
    super().save(*args, **kwargs)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\models\base.py", line 745, in save
    self.save_base(using=using, force_insert=force_insert,
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\models\base.py", line 782, in save_base
    updated = self._save_table(
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\models\base.py", line 887, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\models\base.py", line 924, in _do_insert
    return manager._insert(
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\models\query.py", line 1204, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\models\sql\compiler.py", line 1392, in execute_sql
    cursor.execute(sql, params)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\backends\utils.py", line 100, in execute
    return super().execute(sql, params)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\backends\utils.py", line 68, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\backends\utils.py", line 77, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\backends\utils.py", line 86, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\backends\utils.py", line 86, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\backends\mysql\base.py", line 74, in execute
    return self.cursor.execute(query, args)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\MySQLdb\cursors.py", line 209, in execute
    res = self._query(query)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\MySQLdb\cursors.py", line 315, in _query
    db.query(q)
  File "C:\Users\antho\AppData\Local\Programs\Python\Python38\lib\site-packages\MySQLdb\connections.py", line 239, in query
    _mysql.connection.query(self, query)
django.db.utils.IntegrityError: (1062, "Duplicate entry 'johndoe@gmail.com' for key 'accounts_user.email'")


0 个答案:

没有答案