无论我对 Postgres 数据库做什么,手动 Django 表单都不会保存

问题描述 投票:0回答:1

我在将表单保存到数据库时遇到问题。我尝试过的所有方法都不起作用,我真的不知道还能做什么。

我在 Django 中创建了一个手动表单,保存时绝对没有错误,一切正常,没有任何错误,我什至被重定向到成功页面,但数据库中什么也没有。

# models.py

class Lead(Model):
    lead_status = CharField(choices=STATUS, default='Activă', verbose_name='Status cerere')
    property_type = CharField(choices=TIP_PROPRIETATE, default='Apartament', verbose_name='Tip cerere')
    transaction_type = CharField(choices=TIP_TRANZACTIE, verbose_name='Tip tranzacție')

    contact = ForeignKey(Contact, on_delete=SET_NULL, null=True, verbose_name='Contact asociat')

    county = CharField(choices=JUDETE, verbose_name='Județ')
    city = CharField(max_length=30, verbose_name='Localitate')
    zone = CharField(max_length=30, null=True, blank=True, verbose_name='Zonă')
    street = CharField(max_length=40, null=True, blank=True, verbose_name='Stradă')

    budget = IntegerField(null=True, blank=True, verbose_name='Buget alocat')
    payment_method = CharField(choices=MODALITATE_PLATA, null=True, blank=True, verbose_name='Modalitate plată', )

    urgency = CharField(choices=URGENTA, default='Normal', verbose_name='Urgență')
    other_details = TextField(max_length=2000, null=True, blank=True, verbose_name='Alte detalii')

    labels = CharField(choices=ETICHETA, null=True, blank=True, verbose_name='Etichete')
    notes = TextField(max_length=2000, null=True, blank=True, verbose_name='Notițe proprii')

    created_at = DateTimeField(auto_now_add=True, verbose_name='Data introducerii')
    updated_at = DateTimeField(auto_now=True, verbose_name='Data ultimei actualizări')
    deadline_date = DateField(null=True, blank=True, verbose_name='Data limită')
    deadline_time = TimeField(null=True, blank=True, verbose_name='Ora limită')

    class Meta:
        abstract = True

    def __str__(self):
        return f'{self.contact}'


class ApartmentLead(Lead):
    apartment_type = CharField(choices=TIP_APARTAMENT, verbose_name='Tip apartament')
    destination = CharField(choices=DESTINATIE_AP, verbose_name='Destinație')

    rooms_number = IntegerField(null=True, blank=True, verbose_name='Număr camere')
    nr_bedrooms = IntegerField(null=True, blank=True, verbose_name='Număr dormitoare')
    nr_bathrooms = IntegerField(null=True, blank=True, verbose_name='Număr băi')
    bathroom_window = BooleanField(default=False, verbose_name='Geam la baie')
    floor = CharField(choices=ETAJ_AP, null=True, blank=True, verbose_name='Etaj')
    excluded_ground_floor = BooleanField(default=False, verbose_name='Exclus parter')
    excluded_top_floor = BooleanField(default=False, verbose_name='Exclus ultimul etaj')
    nr_floors = IntegerField(null=True, blank=True, verbose_name='Număr etaje')

    minimal_surface = DecimalField(max_digits=5, decimal_places=2, null=True, blank=True, verbose_name='Suprafață minimă (mp)')
    construction_status = CharField(choices=STADIU_CONSTRUCTIE, null=True, blank=True, verbose_name='Stadiu construcție')
    furniture = CharField(choices=MOBILIER, null=True, blank=True, verbose_name='Mobilier')
    comfort = CharField(choices=CONFORT, null=True, blank=True, verbose_name='Confort')
    ap_compart = CharField(choices=COMPARTIMENTARE_AP, null=True, blank=True, verbose_name='Compartimentare')
    orientation = CharField(choices=ORIENTARE, null=True, blank=True, verbose_name='Orientare')
    interior_finishes = CharField(choices=FINISAJE, null=True, blank=True, verbose_name='Stare interior')
    construction_year = IntegerField(null=True, blank=True, verbose_name='Anul construcției')

    basement = BooleanField(default=False, verbose_name='Subsol')
    semi_basement = BooleanField(default=False, verbose_name='Demisol')
    technical_floor = BooleanField(default=False, verbose_name='Etaj tehnic')
    loft = BooleanField(default=False, verbose_name='Mansardă')
    attic = BooleanField(default=False, verbose_name='Pod')
    elevator = BooleanField(default=False, verbose_name='Lift')

    created_by = ForeignKey(User, on_delete=SET_NULL, null=True, blank=True, related_name='my_apartment_key', verbose_name='Agent asociat')
    assigned_listings = ForeignKey(Apartment, on_delete=SET_NULL, null=True, blank=True,
                                   related_name='assigned_apartment_key', verbose_name='Proprietăți asociate')

    def __str__(self):
        return f'{self.apartment_type} - {self.created_by}'
# forms.py

class LeadCreateForm(ModelForm):
    class Meta:
        model = Lead
        fields = '__all__'
        widgets = {
            'status': Select(attrs={'class': 'form-control'}),
            'property_type': Select(attrs={'class': 'form-control'}),
            'transaction_type': Select(attrs={'class': 'form-control'}),

            'contact': Select(attrs={'class': 'form-control'}),

            'county': TextInput(attrs={'class': 'form-control'}),
            'city': TextInput(attrs={'class': 'form-control'}),
            'zone': TextInput(attrs={'class': 'form-control'}),
            'street': TextInput(attrs={'class': 'form-control'}),

            'budget': TextInput(attrs={'class': 'form-control'}),
            'payment_method': Select(attrs={'class': 'form-control'}),

            'urgency': Select(attrs={'class': 'form-control'}),
            'other_details': Textarea(attrs={'class': 'form-control', 'rows': '3'}),

            'labels': Select(attrs={'class': 'form-control'}),
            'notes': Textarea(attrs={'class': 'form-control', 'rows': '3'}),

            'created_at': DateInput(attrs={'class': 'form-control'}),
            'updated_at': DateInput(attrs={'class': 'form-control'}),
            'deadline_date': DateInput(attrs={'type': 'date'}),
            'deadline_time': TimeInput(attrs={'type': 'time', 'step': '600'})
        }


class ApartmentLeadCreateForm(LeadCreateForm):
    class Meta:
        model = ApartmentLead
        fields = '__all__'
        widgets = {
            'apartment_type': SelectMultiple(attrs={'class': 'form-control'}),
            'destination': Select(attrs={'class': 'form-control'}),

            'rooms_number': NumberInput(attrs={'class': 'form-control'}),
            'nr_bedrooms': NumberInput(attrs={'class': 'form-control'}),
            'nr_bathrooms': NumberInput(attrs={'class': 'form-control'}),
            'bathroom_window': CheckboxInput(attrs={'class': 'form-check-input'}),
            'floor': SelectMultiple(attrs={'class': 'form-control'}),
            'excluded_ground_floor': CheckboxInput(attrs={'class': 'form-check-input'}),
            'excluding_top_floor': CheckboxInput(attrs={'class': 'form-check-input'}),
            'nr_floors': NumberInput(attrs={'class': 'form-control'}),

            'minimal_surface': NumberInput(attrs={'class': 'form-control'}),
            'construction_status': SelectMultiple(attrs={'class': 'form-control'}),
            'furniture': SelectMultiple(attrs={'class': 'form-control'}),
            'comfort': SelectMultiple(attrs={'class': 'form-control'}),
            'ap_compart': SelectMultiple(attrs={'class': 'form-control'}),
            'orientation': SelectMultiple(attrs={'class': 'form-control'}),
            'interior_finishes': SelectMultiple(attrs={'class': 'form-control'}),
            'construction_year': NumberInput(attrs={'class': 'form-control'}),

            'basement': CheckboxInput(attrs={'class': 'form-check-input'}),
            'semi_basement': CheckboxInput(attrs={'class': 'form-check-input'}),
            'technical_floor': CheckboxInput(attrs={'class': 'form-check-input'}),
            'loft': CheckboxInput(attrs={'class': 'form-check-input'}),
            'attic': CheckboxInput(attrs={'class': 'form-check-input'}),
            'elevator': CheckboxInput(attrs={'class': 'form-check-input'}),

            'assigned_listings': TextInput(attrs={'class': 'form-control'}),
        }

    def clean(self):
        cleaned_data = super().clean()

        rooms_number = cleaned_data.get('rooms_number')
        bedrooms_number = cleaned_data.get('nr_bedrooms')

        if bedrooms_number is not None and rooms_number is not None and bedrooms_number > rooms_number:
            raise ValidationError('Numărul de dormitoare nu poate fi mai mare decât numărul total de camere.')

        floor = cleaned_data.get('floor')
        nr_floors = cleaned_data.get('nr_floors')

        if floor is not None and nr_floors is not None and floor > nr_floors:
            raise ValidationError('Numărul etajului apartamentului nu poate fi mai mare decât numărul total de etaje.')

        return cleaned_data
# urls.py

app_name = 'leads'

urlpatterns = [
    path('add-apartment-lead', ApartmentLeadCreateView.as_view(), name='add_apartment_lead'),
]
# views.py

class ApartmentLeadCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
    model = ApartmentLead
    form_class = ApartmentLeadCreateForm
    template_name = 'leads/apartments/add_apartment_lead.html'
    success_url = reverse_lazy('leads:lead_added')
    permission_required = 'leads.add_apartmentlead'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        stored_contact = self.request.session.get('storedContactId')
        stored_type = self.request.session.get('storedType')
        context['storedContactId'] = stored_contact
        context['storedType'] = stored_type
        return context

    def form_valid(self, form):
        form.instance.created_at = timezone.now()
        form.instance.updated_at = timezone.now()
        form.instance.created_by = self.request.user

        try:
            response = super().form_valid(form)
            return response
        except Exception as e:
            print(f"Eroare în timpul salvării datelor: {e}")
            return HttpResponseRedirect(self.get_success_url())
# HTML & JavaScript

{% extends 'partials/base.html' %}
{% load static %}
{% block title %} Cerere nouă | Apartament {% endblock title %}

{% block content %}
    
    {% block pagetitle %}
        {% include "partials/page_title.html" with pagetitle="Cereri" title="Cerere nouă | Apartament" %}
    {% endblock pagetitle %}
    
    {% if user.is_authenticated %}
        {% if perms.leads.add_apartmentlead %}
            <div class="row">
                <div class="col-md-12">
                    <div class="card">
                        <div class="card-body">
                            <form id="add_lead_form" method="post" enctype="multipart/form-data" class="row" 
                                  action="{% url 'leads:add_apartment_lead' %}">
                                {% csrf_token %}
                                <div class="col-lg-3 col-md-6 col-sm-6">
                                    <div class="card">
                                        <div class="card-body">
                                            <div id="contactInfo">
                                                <h5><span id="firstName"></span> <span id="lastName"></span></h5>
                                                <div id="phoneNumber"></div>
                                                <div id="email"></div>
                                            </div>
                                            <input id="contact" name="contact" type="hidden" value="{{ storedContactId }}" 
                                                   required>
                                            <hr class="border-secondary-subtle">
                                            <div class="col-lg-12 mb-3">
                                                <label for="property_type" class="form-label">Tip cerere <span 
                                                        class="text-danger">*</span></label>
                                                <input id="property_type" class="form-control text-muted" 
                                                       name="property_type" value="{{ storedType }}" readonly required>
                                            </div>
                                            <div class="col-lg-12 mb-3">
                                                <label for="apartment_type" class="form-label">
                                                    Tip apartament <span class="text-danger">*</span></label>
                                                <select id="apartment_type" class="form-select" name="apartment_type" 
                                                        required>
                                                    {% for value, label in form.fields.apartment_type.choices %}
                                                        <option value="{{ value }}">{{ label }}</option>
                                                    {% endfor %}
                                                </select>
                                            </div>
                                            <div class="col-lg-12 mb-3">
                                                <label for="transaction_type" class="form-label">Tip tranzacție <span
                                                        class="text-danger">*</span></label>
                                                <select id="transaction_type" class="form-select" name="transaction_type" 
                                                        required>
                                                    {% for value, label in form.fields.transaction_type.choices %}
                                                        <option value="{{ value }}">{{ label }}</option>
                                                    {% endfor %}
                                                </select>
                                            </div>
                                            <div class="col-lg-12">
                                                <label for="lead_status" class="form-label">Status cerere <span
                                                        class="text-danger">*</span></label>
                                                <select id="lead_status" class="form-select" name="lead_status" required>
                                                    {% for value, label in form.fields.lead_status.choices %}
                                                        <option value="{{ value }}">{{ label }}</option>
                                                    {% endfor %}
                                                </select>
                                            </div>
                                            <hr class="border-secondary-subtle">
                                            <div class="col-lg-12 mb-3">
                                                <label for="county" class="form-label">Județ <span
                                                        class="text-danger">*</span></label>
                                                <select id="county" class="form-control" name="county" data-choices 
                                                        required>
                                                    {% for value, label in form.fields.county.choices %}
                                                        <option value="{{ value }}">{{ label }}</option>
                                                    {% endfor %}
                                                </select>
                                            </div>
                                            <div class="col-lg-12 mb-3">
                                                <label for="city" class="form-label">Localitate <span
                                                        class="text-danger">*</span></label>
                                                <input id="city" class="form-control" name="city" type="text" required>
                                            </div>
                                            <div class="col-lg-12 mb-3">
                                                <label for="zone" class="form-label">Zonă</label>
                                                <input id="zone" class="form-control" name="zone" type="text">
                                            </div>
                                            <div class="col-lg-12">
                                                <label for="street" class="form-label">Stradă</label>
                                                <input id="street" class="form-control" name="street" type="text">
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="col-lg-3 col-md-6 col-sm-6">
                                    <div class="card">
                                        <div class="card-body">
                                            <div class="col-lg-12 mb-3">
                                                <label for="budget" class="form-label">Buget alocat</label>
                                                <input id="budget" class="form-control" name="budget" type="text">
                                            </div>
                                            <div class="col-lg-12 mb-3">
                                                <label for="payment_method" class="form-label">Metodă de plată</label>
                                                <select id="payment_method" class="form-select" name="payment_method">
                                                    {% for value, label in form.fields.payment_method.choices %}
                                                        <option value="{{ value }}">{{ label }}</option>
                                                    {% endfor %}
                                                </select>
                                            </div>
                                            <hr class="border-secondary-subtle">
                                            <div class="col-lg-12 mb-3">
                                                <label for="urgency" class="form-label">Urgență</label>
                                                <select id="urgency" class="form-select" name="urgency">
                                                    {% for value, label in form.fields.urgency.choices %}
                                                        {% if value == "Normal" %}
                                                            <option value="{{ value }}" selected>{{ label }}</option>
                                                        {% else %}
                                                            <option value="{{ value }}">{{ label }}</option>
                                                        {% endif %}
                                                    {% endfor %}
                                                </select>
                                            </div>
                                            <div class="col-lg-12 mb-3">
                                                <label for="deadline_date" class="form-label">Data limită</label>
                                                <input id="deadline_date" class="form-control" name="deadline_date" 
                                                       type="date" placeholder="ZZ.LL.AAAA">
                                            </div>
                                            <div class="col-lg-12 mb-3">
                                                <label for="deadline_time" class="form-label">Ora limită</label>
                                                <input id="deadline_time" class="form-control" name="deadline_time" 
                                                       type="time" step="600" placeholder="OO:MM">
                                            </div>
                                            <div class="col-lg-12 mb-3">
                                                <label for="assigned_listings" class="form-label">
                                                    Proprietăți asociate</label>
                                                <select id="assigned_listings" class="form-control" 
                                                        name="assigned_listings" multiple>
                                                    {% for value, label in form.fields.assigned_listings.choices %}
                                                        <option value="{{ value }}"></option>
                                                    {% endfor %}
                                                </select>
                                            </div>
                                            <div class="col-lg-12 mb-3">
                                                <label for="labels" class="form-label">Etichete</label>
                                                <select id="labels" class="form-select" name="labels" multiple>
                                                    {% for value, label in form.fields.labels.choices %}
                                                        <option value="{{ value }}"></option>
                                                    {% endfor %}
                                                </select>
                                            </div>
                                            <div class="col-lg-12">
                                                <label for="notes" class="form-label">Notițe proprii</label>
                                                <textarea id="notes" class="form-control" name="notes" type="text" 
                                                          rows="4"></textarea>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="card-footer">
                                    <div class="row">
                                        <div class="col-md-12">
                                            <button type="submit" class="btn btn-subtle-success float-end">
                                                Salvează cererea
                                            </button>
                                        </div>
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        {% endif %}
    {% endif %}

{% endblock content %}

{% block extra_javascript %}
    
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            console.log('Conținutul DOM a fost încărcat.');
            
            var storedType = sessionStorage.getItem('selectedType');
            var storedContactId = sessionStorage.getItem('selectedContact');
            
            console.log('Tip cerere:', storedType);
            console.log('ID contact:', storedContactId);
            
            if (document.getElementById('property_type')) {
                document.getElementById('property_type').value = storedType;
            }
            if (document.getElementById('contact')) {
                document.getElementById('contact').value = storedContactId;
            }
            
            if (storedContactId) {
                fetch('/contacts/api/contact-details/' + storedContactId)
                    .then(response => {
                        if (!response.ok) {
                            throw new Error('Eroare la solicitarea datelor contactului!');
                        }
                        return response.json();
                    })
                    .then(data => {
                        document.getElementById('firstName').innerText = data.first_name;
                        document.getElementById('lastName').innerText = data.last_name;
                        document.getElementById('phoneNumber').innerText = data.phone_number;
                        document.getElementById('email').innerText = data.email;
                    })
                    .catch(error => {
                        console.error('Eroare:', error);
                    });
            }
            
            var leadAssignedListings = document.getElementById('assigned_listings');
            new Choices(leadAssignedListings, {
                allowHTML: true,
                loadingText: 'Se încarcă...',
                noResultsText: 'Nu există proprietăți disponibile.'
            });
            
            var leadLabels = document.getElementById('labels');
            new Choices(leadLabels, {
                allowHTML: true,
                loadingText: 'Se încarcă...',
                noResultsText: 'Nu există alte etichete.'
            });
            
            document.getElementById('add_lead_form').addEventListener('submit', function(event) {
                event.preventDefault();
                
                var formData = new FormData(this);
                
                console.log('Datele trimise sunt:', formData);
                
                fetch('/leads/add-apartment-lead', {
                    method: 'POST',
                    body: formData,
                })
                .then(response => {
                    if (!response.ok) {
                        throw new Error('A apărut o eroare în timpul salvării.');
                    }
                    return response.text();
                })
                .then(data => {
                    console.log('Datele au fost salvate cu succes:', data);
                    window.location.href = 'lead-added';
                })
                .catch(error => {
                    console.error('Eroare în timpul salvării:', error);
                });
            });
        });
    </script>
    
{% endblock extra_javascript %}

我也尝试过使用 {{ form }} 但仍然不起作用。我注意到,我首先在上一页上选择联系人和属性类型,将这两个项目保存到 sessionStorage 中,但关键是整个表单看起来都是空的,就好像我实际上在表单上的任何字段中都没有任何内容一样.

html 文件不完整,因为它太长了,但是其中有很多重要字段,因此您可以弄清楚它的内容。完整的 html 页面可以在这里查看: https://github.com/dolca/crmSystem/blob/main/templates/leads/apartments/add_apartment_lead.html

提前致谢,感谢任何帮助!

django postgresql
1个回答
0
投票

在您的模型中,您有:

类元: 抽象=真实

除非我遗漏了什么,否则最好将其删除。如果我们查看 django 文档,它会说

此模型将不会用于创建任何数据库表

来源:抽象模型

© www.soinside.com 2019 - 2024. All rights reserved.