Hi!
I’m currently building a server monitoring application with django and I’m a bit stuck on how to structure my form. The form creates an instance of a model with a one to one field and I’d like to automatically create and assign an instance from another model to this one. I’m currently getting an error due to missing this behaviour IntegrityError at / NOT NULL constraint failed: checker_icmpmonitor.monitor_id_id
Here are my current models:
class MonitorChoices(models.IntegerChoices):
__empty__ = "Please select a monitor option"
ICMP = 0, "ICMP monitor"
OPEN_PORT = 1, "Open port monitor"
class MonitorList(models.Model):
"""
List with all the monitors
"""
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
choice = models.IntegerField(choices=MonitorChoices.choices)
class BaseMonitor(models.Model):
"""
Base class for a monitor
"""
monitor_id = models.OneToOneField(MonitorList, on_delete=models.CASCADE)
description = models.TextField(blank=True)
created = models.DateField(auto_now=True)
error_email = models.EmailField()
endpoint = models.CharField(max_length=100)
sleep_time = models.PositiveSmallIntegerField(default=60)
message_sleep_time = models.PositiveSmallIntegerField(default=300)
def __str__(self):
return self.monitor_id.name
class Meta:
abstract = True
class IcmpMonitor(BaseMonitor):
ping_timeout = models.PositiveSmallIntegerField()
class OpenPortMonitor(BaseMonitor):
port_to_check = models.PositiveSmallIntegerField(
validators=[MinValueValidator(1), MaxValueValidator(65535)]
)
forms:
class AddIcmpMonitorForm(forms.ModelForm):
name = forms.CharField(max_length=200)
class Meta:
model = IcmpMonitor
fields = [
"description",
"error_email",
"endpoint",
"sleep_time",
"message_sleep_time",
"ping_timeout",
]
views:
class MonitorListListView(ListView):
model = MonitorList
template_name = "checker/index.html"
class IcmpMonitorCreateView(CreateView):
model = IcmpMonitor
form_class = AddIcmpMonitorForm
template_name = "checker/add_form.html"
def get_success_url(self) -> str:
return reverse_lazy("index-view")
index.html template:
<h1>Monitor List</h1>
<table>
<tr>
<th scope="col">Name</th>
<th scope="col">Type</th>
</tr>
<tr>
{% for monitor in object_list %}
<th scope="row">{{ monitor.name }}</th>
<td>{{ monitor.choice }}</td>
{% empty %}
<li>No Monitors yet.</li>
{% endfor %}
</tr>
</table>
add_form.html template:
<form action={% url "index-view" %} method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
Thanks in advance