Issue
I had override a save method for my Meeting model which will generate a random id for the meeting_ID whenever user create a meeting.
The save method itself is successful but the problem is that somehow the override save() method generate two random ids instead of just one for the created meeting. Meaning that when I click on Save button, it will create two identical meetings with different meeting_ID.
I don't know what is the issue as I'm a beginner for Django.
Thanks in advance.
Model.py
class Meeting(models.Model):
MEETING_STATUS = (
('Coming Soon', 'Coming Soon'),
('Live', 'Live'),
('Closed', 'Closed')
)
meeting_ID = models.CharField(primary_key=True, max_length=6, validators=[RegexValidator(r'^\d{6,6}$')], null=True)
meeting_title = models.CharField(max_length=400, null=True)
meeting_date = models.DateField()
meeting_time = models.TimeField()
meeting_desc = models.CharField(max_length=500, null=True)
meeting_status = models.CharField(max_length=200, null=True, choices=MEETING_STATUS)
date_created = models.DateTimeField(default=timezone.now, null=True)
def __str__(self):
return self.meeting_ID
def save(self, *args, **kwargs):
meetingID = random.randint(100000,999999)
if not Meeting.objects.filter(meeting_ID=str(meetingID)).exists():
self.meeting_ID = str(meetingID)
print(self.meeting_ID)
super(Meeting, self).save(*args,**kwargs)
class Resolutions_Meeting(models.Model):
reso_ID = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
resolution = models.CharField(max_length=400)
meeting_id = models.ForeignKey(Meeting, related_name="has_meetings", on_delete=CASCADE, null=False)
def __str__(self):
return str(self.meeting_id)
Views.py
class MeetingsCreate(CreateView):
model = Meeting
template_name = 'meetings/create_meetings.html'
# fields = ['meeting_ID', 'meeting_title', 'meeting_date', 'meeting_time', 'meeting_desc', 'meeting_status']
form_class = MeetingForm
success_url = None
def get_context_data(self, **kwargs):
data = super(MeetingsCreate, self).get_context_data(**kwargs)
if self.request.POST:
data['meetings'] = ResolutionsFormSet(self.request.POST)
else:
data['meetings'] = ResolutionsFormSet()
return data
def form_valid(self, form):
context = self.get_context_data()
meetings = context['meetings']
with transaction.atomic():
self.object = form.save()
# print(self.object)
if meetings.is_valid():
meetings.instance = self.object
meetings.save()
return super(MeetingsCreate, self).form_valid(form)
def get_success_url(self):
return reverse_lazy('host_dashboard')
**Template/formset.html**
```
{% load static %}
<html>
<head>
<style type="text/css">
.delete-row {
align-self: center;
}
</style>
</head>
<body>
{% load crispy_forms_tags %}
<table class="col-md-9" style="margin-left: 10px;">
{{ formset.management_form|crispy }}
{% for form in formset.forms %}
<tr class="{% cycle 'row1' 'row2' %} formset_row-{{ formset.prefix }}">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field|as_crispy_field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<br>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js">
</script>
<script src="{% static 'js/jquery.formset.js' %}">
</script>
<script type="text/javascript">
$('.formset_row-{{ formset.prefix }}').formset({
addText: 'add another resolution',
deleteText: 'remove',
prefix: '{{ formset.prefix }}',
});
</script>
</body>
</html>
```
**template/create_meeting.html**
```
{% extends 'meetings/main.html' %}
{% load static %}
{% load crispy_forms_tags %}
<html>
<head>
</head>
<body>
{% block content %}
<div class="container">
<div class="card">
<div class="card-header">
Create Meeting
</div>
<div class="card-body">
{% crispy form %}
</div>
</div>
</div>
{% endblock %}
</body>
</html>
```
Solution
Your form_valid()
method seems wrong: Apparently, you use save()
method twice so this is why you create two instances. The first save()
method should be
form.save(commit=False)
so you do not create an instance on the database. This is what commit = False
does. It is useful because you can manipulate the data after posting a form by a user. Then you can use the second save()
method to create the instance on the database. But I think you only want to validate the form data.
Right now, I cannot test your code but I think it must be like:
def form_valid(self, form):
context = self.get_context_data()
meetings = context['meetings']
if meetings.is_valid():
response = super().form_valid(form)
meetings.instance = self.object
meetings.save()
return response
else:
return super().form_invalid(form)
If it doesn't work, then there is another mistake apart from the one I mention. I can edit my answer in that situation.
Answered By - black
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.